Форум » Консультации по программированию » Паттерны ПрайсЭкшен через структуру » Ответить

Паттерны ПрайсЭкшен через структуру

evbut: Игорь добрый день! Перенесу сюда свои мытарства с перепрограммированием индикатора по паттернам под свои нужды. В той ветке я показал, что кое-какие сдвиги к получению желаемого мной результата есть. В текущем варианте как вы видели по картинкам он уже отрисовывает паттерны и их цели, способен перекрасить паттерны, если его таргет пробит. Вопрос по удалению перекрытых паттернов пока откладываю на потом, поскольку возник более актуальный. Повторю здесь кусок кода, где происходят главные события с паттернами: [more] [quote]void FindAndShowPatterns(int index) { int startBar, patternDir,patternName; GetData(index,startBar,patternDir,patternName); double lowPrice = ND(Low[iLowest(NULL, 0, MODE_LOW, // Нижняя граница паттерна startBar - index + 1, index)]); double highPrice = ND(High[iHighest(NULL, 0, MODE_HIGH, // Верхняя граница паттерна startBar - index + 1, index)]); double patternHeight = highPrice - lowPrice; double BuyTP = ND(lowPrice + patternHeight * FiboTarget / 100.0); double SellTP = ND(highPrice - patternHeight * FiboTarget / 100.0); // string nameofpattern = PatternName(patternName); int patternArray = ArraySize(g_patterns); if(patternDir !=0) { if( ArrayResize(g_patterns, patternArray+1, ARRAY_RESERVE_SIZE) < 0) { Alert(WindowExpertName(),(g_isRussianLang)? ": Недостаточно памяти для продолжения работы программы. Индикатор отключен.": ": Not enough memory to continue work the program. Indicator is turned off."); } g_patterns[patternArray].patternType = patternDir; g_patterns[patternArray].patternName = patternName; g_patterns[patternArray].leftBarIndex = startBar; g_patterns[patternArray].rightBarIndex = index; g_patterns[patternArray].patternHighPrice = highPrice; g_patterns[patternArray].patternLowPrice = lowPrice; if(patternDir == BEAR_TYPE) g_patterns[patternArray].patternColor = RegcolorBears; else g_patterns[patternArray].patternColor = RegcolorBulls; if(patternDir == BULL_TYPE) g_patterns[patternArray].patternTarget = BuyTP; else g_patterns[patternArray].patternTarget = SellTP; //Проверка паттерна на отработку таргета if(IsShowWorked) for(int i = ArraySize(g_patterns)-1; i >= 0; i--) { if(g_patterns.patternType == BEAR_TYPE) { for(int k = g_patterns.rightBarIndex-1; k >= 0; k--) { if(iLow(NULL, 0, k) < g_patterns.patternTarget) g_patterns.patternColor = WorkColor; } } if(g_patterns.patternType == BULL_TYPE) { for(int k = g_patterns.rightBarIndex-1; k >= 0; k--) { if(iHigh(NULL, 0, k) > g_patterns.patternTarget) g_patterns.patternColor = WorkColor; } } } // == Запишем факт отработки паттерна ====================== int getTarget = IsActualPattern(g_patterns[patternArray]); g_patterns[patternArray].getTarget = getTarget; // === Отрисуем паттерны =========== /*if(!IsShowALLPatterns) DeleteAnyPattern(g_patterns[patternArray], index); */ // Удаление перекрытых паттернов if(IsRectangleShow) { string name = GetUniqueID(g_patterns[patternArray], FIRST_PART); /*string name = GetObjectName(g_patterns[patternArray].rightBarIndex, g_patterns[patternArray].patternType, FIRST_PART);// Имя объекта паттерна*/ ShowRectangle(name, Time[g_patterns[patternArray].leftBarIndex], g_patterns[patternArray].patternLowPrice, Time[g_patterns[patternArray].rightBarIndex],g_patterns[patternArray].patternHighPrice, "",g_patterns[patternArray].patternColor); } /*string name = GetObjectName(g_patterns[patternArray].rightBarIndex, g_patterns[patternArray].patternType, SECOND_PART);// Имя объекта паттерна */ string name = GetUniqueID(g_patterns[patternArray], SECOND_PART); ShowTarget(name, Time[g_patterns[patternArray].leftBarIndex], g_patterns[patternArray].patternTarget, Time[g_patterns[patternArray].rightBarIndex], g_patterns[patternArray].patternTarget, "",g_patterns[patternArray].patternColor); [/quote][/more] Отображает он все как мне хотелось бы. При наведении мышки на паттерн отображает информацию из функции GetUniqueID: [quote]string GetUniqueID(const Pattern & pattern, string middlePart) { return(PREFIX + EnumToString(pattern.patternName)+EnumToString(pattern.getTarget)+"_" +EnumToString(pattern.patternType)+ middlePart + string(Time[pattern.rightBarIndex])); } [/quote] Но тут где-то собака зарылась, не пойму относительно отображения EnumToString(pattern.getTarget), которая определяется отдельной функцией (кстати подобными строками перекрашиваются паттерны): [quote] int IsActualPattern(Pattern &pattern) { for(int i = ArraySize(g_patterns)-1; i >= 0; i--) { if(g_patterns.patternType == BEAR_TYPE) { for(int k = g_patterns.rightBarIndex-1; k >= 0; k--) { if(iLow(NULL, 0, k) < g_patterns.patternTarget) g_patterns.getTarget = WORKED; else g_patterns.getTarget = ACTUAL; } } if(g_patterns.patternType == BULL_TYPE) { for(int k = g_patterns.rightBarIndex-1; k >= 0; k--) { if(iHigh(NULL, 0, k) > g_patterns.patternTarget) g_patterns.getTarget = WORKED; else g_patterns.getTarget = ACTUAL; } } } return (g_patterns[ArraySize(g_patterns)-1].getTarget); } [/quote] Так вот... Eсли медвежий паттерн отработан (WORKED) - то окрашивается он как отработанный, и в подписи к нему EnumToString(pattern.getTarget) пишет WORKED, а вот с бычьими почему-то не пишет... окрашивает как отработанный, но в подписи и в принте пишет что он актуальный (см. рис). Как побороть это недоразумение? Сдается мне что тут вина в implicit enum conversion в строке g_patterns[patternArray].getTarget = getTarget, его энум [more][quote] enum ENUM_GET_TARGET { NONE , ACTUAL, //Actual pattern WORKED //Worked pattern }; [/quote][/more] Кроме этого таких предупреждений еще два штуки есть по коду в строках: g_patterns[patternArray].patternType = patternDir, его Энум выглядит так [more][quote] enum ENUM_PATTERN_TYPE { NONE_TYPE, //0 - No pattern BULL_TYPE, //1 - Bull pattern BEAR_TYPE, //2 - bear pattern }; [/quote][/more] и g_patterns[patternArray].patternName = patternName, его энум [more][quote] enum ENUM_PATTERN_NAME { NONE_INDEX = -1, RAILS_ = 0, OVB_ = 1, PPR_ = 2 }; [/quote][/more] Ну и все они в структуре объявлены и инициализированы вот так patternType = NONE_TYPE; patternName = NONE_INDEX; getTarget = NONE; И на всякий случай функция GetData [more][quote] void GetData(int index, int& startBar, int &type, int &patternName) { //- 1 - == Определим тип найденного паттерна по направлению ===================== if(IsBullsRailsPattern(index)|| IsBUOVBPattern(index) || IsBullsPPRPattern(index)) type = BULL_TYPE; if(IsBearsRailsPattern(index) || IsBEOVBPattern(index)|| IsBearsPPRPattern(index)) type = BEAR_TYPE; //- 1 - == Конец =============================================================== //- 2 - == Определим левую границу найденного паттерна ========================= if(IsBullsPPRPattern(index) || IsBearsPPRPattern(index)) startBar = index+2; if(IsBUOVBPattern(index) || IsBEOVBPattern(index)|| IsBearsRailsPattern(index) || IsBullsRailsPattern(index)) startBar = index+1; //- 2 - == Конец =============================================================== //- 3 - == Ообозначим паттерн по названию======================================= if(IsBullsRailsPattern(index) || IsBearsRailsPattern(index)) patternName = RAILS_; if(IsBUOVBPattern(index) || IsBEOVBPattern(index)) patternName = OVB_; if(IsBullsPPRPattern(index)|| IsBearsPPRPattern(index)) patternName = PPR_; //- 3 - == Конец =============================================================== } [/quote][/more] Ткните, плиз носом, как победить этот недуг Просмотрев немного по истории, точной закономерности не выявил, но вот покажу участок, где стрелками показаны два по рассраске отработанных бычьих паттерна, между ними 8 свечей (две стрелки указывают на один и тот паттерн). Но подписи у них разные... тот что ниже слева - пишет WORKED, а тот что через 8 свечей справа - ACTUAL. Чо к чему... не пойму А главное как так-то? Может в коде какого дополнительного условия не хватает в функции IsActualPattern? Или это не понятные примудрусти какие-то в функции строки подписи? [more][quote] //+-------------------------------------------------------------------------------------+ string GetUniqueID(const Pattern & pattern, string middlePart) { return(PREFIX + EnumToString(pattern.patternName)+EnumToString(pattern.getTarget)+"_" +EnumToString(pattern.patternType)+ "\n"+ middlePart +"\n" + "TARGET = " + DoubleToString(pattern.patternTarget,_Digits)); } [/quote][/more]

Ответов - 87, стр: 1 2 3 4 5 6 All

Scriptong: evbut пишет: Откуда такая разница в вызове этих строк, ведь они выполняют похожие действия и баров одинаковое количество проверяют? По логике их должно быть максимум 278 каждая... Дело то не столько в двойном вызове функции, а в том, что она делает огромное количество повторяющихся действий. Разберем по полочкам, что же происходит. 1. Цикл i в ShowIndicatorData указывает на бар с индексом 1000. Допустим, на этом баре найден какой-то паттерн. В итоге вызывается функция IsPatternWorked(), которая запускает свой цикл от бара 1000 до бара с индексом 0. Получаем 1000 итераций сходу. 2. Цикл i в ShowIndicatorData указывает на бар с индексом 998. Допустим, на этом баре найден еще какой-то паттерн. Уже два паттерна. В итоге два раза вызывается функция IsPatternWorked(), которая запускает цикл от бара 998 до бара с индексом 0. Получаем 1996 итераций. Причем заметьте, что цикл для предыдущего найденного паттерна повторяет 998 итераций, которые были совершены на итерации цикла i = 1000 в ShowIndicatorData. 3. Цикл i в ShowIndicatorData указывает на бар с индексом 995. Допустим, на этом баре найден еще какой-то паттерн. Уже три паттерна. В итоге три раза вызывается функция IsPatternWorked(), которая запускает цикл от бара 995 до бара с индексом 0. Получаем 2985 итераций. Здесь уже два цикла лишних, т. к. эта работа уже давно выполнена. 4. Цикл i в ShowIndicatorData указывает на бар с индексом 500. Допустим, к этому моменту найдено 100 паттернов. В итоге 100 раз вызывается функция IsPatternWorked(), которая запускает цикл от бара 500 до бара с индексом 0. Получаем 500 * 100 = 50 000 итераций. В итоге за 500 обработанных баров было совершено огромное количество лишней работы, которая и приводит к такому медленному выполнению индикатора. Чтобы уйти от такой неоптимальности, в функции IsPatternWorked() нужно избавиться от циклов. Они не нужны. Достаточно проверить отработку каждого найденного на данный момент паттерна на текущем баре (тот, который в цикле i ShowIndicatorData). P. S. Ну а разность вызовов iLow и iHigh объясняется просто: они ведь вызываются в зависимости от типа паттерна.

evbut: Игорь, здравствуйте! Появилось желание сделать индикатор под МТ5. Судя по ошибкам, выдаваемым компилятором МТ5 главная загвоздка будет состоять в переделке в функциях нахождения паттернов, а именно всякие Low, High, Close и подобные, которых в mql5 нету... Универсальности кода по-видимому не получиться... Нужно искать аналоги... На что еще стоит обратить внимание в испытуемом коде при переносе в mql5 для корректной работы?

Scriptong: evbut пишет: Игорь, здравствуйте! Появилось желание сделать индикатор под МТ5. Судя по ошибкам, выдаваемым компилятором МТ5 главная загвоздка будет состоять в переделке в функциях нахождения паттернов, а именно всякие Low, High, Close и подобные, которых в mql5 нету... Универсальности кода по-видимому не получиться... Нужно искать аналоги... На что еще стоит обратить внимание в испытуемом коде при переносе в mql5 для корректной работы? Чтобы переходить на МТ5, сначала следует полностью отладить программу на МТ4. Без этого никак. Ну а универсальность кода для индикаторов вполне достижима (для советников - нет). Чтобы написать в стиле МТ5, используйте функции типа Copy (CopyRates, CopyHigh, CopyLow и т. д.) вместо iLow, iHigh И т. д. Правда придется немного поменять подход к их использованию, готовя данные заранее, а не беря их в том месте, где потребовались.


evbut: Вы убрали цикл из этой функции? Нет... с цикломосталось, но через свич ENUM_GET_TARGET IsPatternWorked(Pattern &pattern) { for(int k = iBarShift(NULL,0,pattern.rightTime); k > 0; k--) { switch(pattern.patternType) { case BULL_TYPE : if(iHigh(NULL,0,k) > pattern.patternTarget) return pattern.getTarget = WORKED; break; case BEAR_TYPE : if(iLow(NULL,0,k) < pattern.patternTarget) return pattern.getTarget = WORKED; break; } } return (g_patterns[ArraySize(g_patterns)-1].getTarget); }

Scriptong: evbut пишет: Нет... с цикломосталось, но через свич Настоятельно рекомендую сделать так: ENUM_GET_TARGET IsPatternWorked(Pattern &pattern, int nBarIndex) { if (pattern.getTarget == WORKED) return pattern.getTarget; switch(pattern.patternType) { case BULL_TYPE : if (iHigh(NULL,0,nBarIndex) > pattern.patternTarget) pattern.getTarget = WORKED; break; case BEAR_TYPE : if(iLow(NULL,0,nBarIndex) < pattern.patternTarget) pattern.getTarget = WORKED; break; } return (pattern.getTarget); } Не проверял синтаксис, могут быть ошибки. В целом смысл такой: передавать в функцию IsPatternWorked индекс обрабатываемого бара. И только на нем проверять отработку паттерна. Не нужно на каждом баре проверять отработку паттерна от момента его регистрации до нулевого бара. Это огромное количество лишней работы. Итогом станет многократный рост производительности индикатора.

evbut: Настоятельно рекомендую сделать так: Не работает так с имеющимся кодом - еще на начальном этапе ее конструирования она ничего не делала - как были паттерны ACTUAL, так и остаются, поскольку эта функция передает свой результат в функцию FindPatternsAndFillDB (int index) g_patterns[patternArray].getTarget = (IsPatternWorked(g_patterns[patternArray],index) == WORKED)? WORKED : ACTUAL; Откуда должен передаваться индекс обрабатываемого бара?

Scriptong: evbut пишет: Не работает так с имеющимся кодом Тогда нужен весь имеющийся код. Понятно, что проблема комплексная. Но, имея лишь фрагменты кода, я не смогу помочь с решением. evbut пишет: Откуда должен передаваться индекс обрабатываемого бара? Из функции ShowIndicatorData.

evbut: ЗДЕСЬ 14 Дней будет лежать Крайняя версия индикатора. В ней мал-мало переделал функцию неотображения перекрывающихся паттернов, добавил опцию удаления отработанных, а также добавил еще один паттерн - Fakey.

Scriptong: evbut пишет: ЗДЕСЬ 14 Дней будет лежать Крайняя версия индикатора. В ней мал-мало переделал функцию неотображения перекрывающихся паттернов, добавил опцию удаления отработанных, а также добавил еще один паттерн - Fakey. К сожалению, меня не было здесь больше - был в отпуске. Повторите, пожалуйста.

evbut: С возвращением в суровые будни )) Надеюсь отпуск удался? Пожалуйста

Scriptong: evbut пишет: С возвращением в суровые будни )) Надеюсь отпуск удался? Пожалуйста Скачал. Чуть позже гляну.

Scriptong: evbut пишет: С возвращением в суровые будни )) Надеюсь отпуск удался? Пожалуйста Уже намного выше быстродействие, чем было. Внес несколько правок.

evbut: На перспективу появилось жгучее желание сделать из него мульти кросплатформенную (MT4/MT5) версию, чтоб на желаемых инструментах из списка и на любых ТФ искал паттерны, а потом отображал в виде таблицы на подобии Этой Панели. Эх, жалко что нет исходника этой панельки - так бы можно было бы пошаманить... А поскольку там уже классы используются, то задумку придется отложить в долгий ящик, пока не пойму что это такое - классы ... Со структурой то еще шибко храмают навыки... А тут классы - дремучий лес ))) А вообще, как вы считаете будет ли достаточным в структуру struct Pattern просто добавить такие переменные как patternSymbol и patternTimeFrame, что бы бы сделать его по моему желанию? Или можно обойтись вообще без структуры -получать данные из функций типа IsBullsRailsPattern, IsBearsRailsPattern и т.д? Ведь по большому счету нужен будет лишь факт нахождения на конкретном символе, конкретного ТФ на первом баре конкретного паттерна и его таргета...

Scriptong: evbut пишет: Эх, жалко что нет исходника этой панельки - так бы можно было бы пошаманить... У меня имеется подобная, правда не в подокне, а в основном окне. Делалось для поиска дивергенций на разных символах/периодах - Сканер дивергенций.

Scriptong: evbut пишет: А вообще, как вы считаете будет ли достаточным в структуру struct Pattern просто добавить такие переменные как patternSymbol и patternTimeFrame, что бы бы сделать его по моему желанию? Или можно обойтись вообще без структуры -получать данные из функций типа IsBullsRailsPattern, IsBearsRailsPattern и т.д? Ведь по большому счету нужен будет лишь факт нахождения на конкретном символе, конкретного ТФ на первом баре конкретного паттерна и его таргета... Есть разные пути для внедрения мультимивола/мультипериода. Можно обойтись и без классов/структур в процедурном стиле. Но элегантнее код будет выглядеть для таких случаев именно в ООП. Соответственно, его отладка станет намного проще процедурного подхода.



полная версия страницы