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

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

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 пишет: Уже и не помню ту версию что высылал вам Вот и мне трудно поддерживать именно тот исходник, с которым Вы работаете, отслеживая изменения по Вашим постам. Пожалуйста, прикрепляйте свою последнюю версию, с которой работаете. Тогда легче будет поддерживать предметный разговор. А иначе я просто теряюсь в догадках.

evbut: Scriptong пишет: Вот и мне трудно поддерживать именно тот исходник, ЗДЕСЬ можно взять крайнюю версию индикатора... Всё перерыл в коде... не найду отчего так отрисовывает и подписывает (( Все функции поиска паттернов взяты из вашего индикатора, за исключением WRB. Поглядите своим опытным глазом, пожалуйста... Ссылка живая будет 7 дней.

Scriptong: evbut пишет: И вот при отображении только паттерна Рельсы на некоторых участках встречается вот такое как для бычьих так и для медвежьих направлений (см рис), что совсем не понятно откуда всплывает - Прямоугольник показывает ППР да и выглядит это комбинация свечей как ППР, а в подписи Рельсы (( В настройках параметры Рельс стоят 20 и 10 Проблема кода в том, что решение о регистрации паттерна разбросано по нескольким независимым функциям. Так, в основной функции FillPatternsDB несколько раз производятся одни и те же действия. Сначала определяется направление паттерна: ENUM_PATTERN_TYPE newPattern = PatternDir(index); Сразу заметим, что функция PatternDir() вызывает функции IsBullsRailsPattern(), IsBUOVBPattern(), IsBullsPPRPattern() и IsBullsWRBPattern(). Причем этот вызов никак не реагирует на значения настроечных параметров, определяющих, какой паттерн следует искать. Как бы мы не настраивали индикатор, все равно он будет искать все включенные в него паттерны. Уже просчет. Возвращаемся в FillPatternsDB(). Следующая строка: ENUM_PATTEN_NAME newPatternName = NamePattern(index); определяет имя паттерна. Как это делается? Снова через вызов функций IsBullsRailsPattern(), IsBUOVBPattern(), IsBullsPPRPattern() и IsBullsWRBPattern(). Но ведь мы вызывали эти функции для бара index! То есть снова выполняется уже проделанная работа. Если идти далее, то видим третью строку FillPatternsDB(): int startBar = GetStartBar(index); Причем функция GetStartBar() вновь оперирует теми же самыми функциями: IsBullsRailsPattern(), IsBUOVBPattern(), IsBullsPPRPattern() и IsBullsWRBPattern(). То есть эти функции были вызваны три раза на одном и том же баре. Но и это еще не беда. Беда в том, что функции вызываются каждый раз в разном порядке: 1. В PatternDir() порядок такой: Рельсы, OVB, PPR, WRB. 2. В NamePattern: Рельсы, OVB, PPR, WRB. 3. В GetStartBar: PPR, WRB, OVB, Рельсы. В итоге получается каша. Если на одном и том же баре имеется несколько разных паттернов, то имя и направление берется от одного паттерна, а номер стартового бара - от другого. Вывод. Таким образом, по озвученной проблеме рецепт такой: во всех функциях сделать единый порядок проверки паттернов, чтобы не было расхождений в регистрации. По всему коду вывод другой: сделать централизованную регистрацию паттернов, без необходимости поиска паттернов на одном баре несколько раз. То есть, вызвав условную функцию ЕстьЛиПаттернНаЭтомБаре(), нужно сразу получить и тип паттерна, и его направление, и стартовый бар. Именно в этой функции следует разместить проверки значений настроечных параметров, указывающих, какой паттерн следует искать, а какой - нет. Это значительно ускорит работу индикатора. Кроме того нужно заранее продумать приоритеты паттернов. В тех случаях, когда на одном баре возникает сразу несколько паттернов и все они подлежат отображению, то из найденных следует выбрать только один паттерн, с наибольшим приоритетом.


evbut: Scriptong пишет: сделать централизованную регистрацию паттернов, без необходимости поиска паттернов на одном баре несколько раз. Это значительно ускорит работу индикатора В целом омтечается заторможенность работы индикатора в этом виде кода, особенно когда историю большую ставишь... Если я правильно понял, стоит вернуть ваши функции FindAndShow-бла-блаPattern, что позволит ускорить его работу... Или будет достаточно расширить функционал функции FillPatternDB? В тех случаях, когда на одном баре возникает сразу несколько паттернов и все они подлежат отображению, то из найденных следует выбрать только один паттерн, с наибольшим приоритетом. Не совсем понимаю как задать приоритет паттернов программно. Переменная указанная ниже не решает этот вопрос? enum ENUM_PATTEN_NAME { NONE_INDEX =-1, RAILS_, OVB_, PPR_, WRB_ };

Scriptong: evbut пишет: Или будет достаточно расширить функционал функции FillPatternDB Нужно сделать так, чтобы на одном и том же баре не повторялись одни и те же действия. То есть вместо нескольких отдельных вызовов разных функций (PatternDir(), NamePattern(), GetStartBar()) нужно сделать одну функцию, которая все это вычисляет. Ведь все равно задача каждой из этих функций сводится к вызову одних и тех же функций. В итоге вместо трех вызовов функций IsBullsRailsPattern(), IsBUOVBPattern(), IsBullsPPRPattern() и IsBullsWRBPattern() будет лишь один их вызов. Кстати, далее по коду FillPatternsDB() следует еще один вызов PatternDir(). Для чего? Ведь результат ее вызова уже кеширован в переменной newPattern. Вообще это очень плохая практика - прибегать к вызову одной и той же функции в прилежащих кусках кода. Ведь в этом случае Вы делаете упор на то, что результат вычислений функции будет один и тот же. Но это бывает далеко не всегда. К примеру, имеется такая распространенная ошибка у программистов, которая приводит к получению фатальной ошибки zero divide: if (AccountEquity() != 0.0) fPercent = fProfit / AccountEquity() Здесь, казалось бы, перед операцией деления имеется проверка результата функции на равенство нулю. Но между двумя вызовами этой функции проходит время (пусть небольшое). За этот период времени значение, возвращаемое AccountEquity(), может измениться и стать равным нулю. Правильный подход в данном случае такой: double fEquity = AccountEquity(); if (fEquity != 0.0) fPercent = fProfit / fEquity evbut пишет: Не совсем понимаю как задать приоритет паттернов программно. Сделать везде одинаковый порядок вызова функций, определяющих наличие паттерна. Паттерн, обрабатываемый первым, получит наивысший приоритет.

evbut: Scriptong пишет: То есть вместо нескольких отдельных вызовов разных функций (PatternDir(), NamePattern(), GetStartBar()) нужно сделать одну функцию, которая все это вычисляет. Не знаю насколько оптимальное решение, но все эти функции вывел в FillPatternsDB (переименовал ее трохи) void FindPatternsAndFillDB(int index) { ENUM_PATTERN_TYPE newPattern = NONE_TYPE; ENUM_PATTEN_NAME newPatternName = NONE_INDEX; int startBar = index; int endBar = index; // поищем Рельсы if(IsShowRailsPattern) { if(IsBullsRailsPattern(index)) { newPattern = BULL_TYPE; newPatternName = RAILS_; startBar = index + 1; } if(IsBearsRailsPattern(index)) { newPattern = BEAR_TYPE; newPatternName = RAILS_; startBar = index + 1; } } if(IsShowOVBPattern) { if(IsBUOVBPattern(index)) { newPattern = BULL_TYPE; newPatternName = OVB_; startBar = index + 1; } if(IsBEOVBPattern(index)) { newPattern = BEAR_TYPE; newPatternName = OVB_; startBar = index + 1; } } if(IsShowSourcePattern) { if(IsBullsWRBPattern(index)) { newPattern = BULL_TYPE; newPatternName = WRB_; startBar = index + 2; } if(IsBearWRBPattern(index)) { newPattern = BEAR_TYPE; newPatternName = WRB_; startBar = index + 2; } } if(IsShowPPRPattern) { if(IsBullsPPRPattern(index)) { newPattern = BULL_TYPE; newPatternName = PPR_; startBar = index + 2; } if(IsBearsPPRPattern(index)) { newPattern = BEAR_TYPE; newPatternName = PPR_; startBar = index + 2; } } double lowPrice = Low[iLowest(NULL,0,MODE_LOW,// Нижняя граница паттерна startBar-endBar+1,endBar)]; double highPrice = High[iHighest(NULL,0,MODE_HIGH,// Верхняя граница паттерна startBar-endBar+1,endBar)]; double patternHeight = highPrice - lowPrice; double BuyTP = lowPrice + patternHeight * FiboTarget / 100.0; double SellTP = highPrice - patternHeight * FiboTarget / 100.0; static datetime lastAlert = 0; if(newPattern != 0) { int patternArray=ArraySize(g_patterns); // внесем его в Базу паттернов if(ArrayResize(g_patterns,patternArray + 1, ARRAY_RESERVE_SIZE) < 0) Alert(g_isRussianLang? ": Недостаточно памяти для продолжения работы программы. Индикатор отключен.": ": Not enough memory to continue work the program. Indicator is turned off."); //запишем в базе.. g_patterns[patternArray].patternType = newPattern; //.. тип паттерна g_patterns[patternArray].patternName = newPatternName; //.. название паттерна g_patterns[patternArray].leftBarIndex = startBar; //.. левая граница g_patterns[patternArray].rightBarIndex = endBar; //.. правая граница g_patterns[patternArray].patternHighPrice = highPrice; //.. верхняя граница g_patterns[patternArray].patternLowPrice = lowPrice; //.. нижняя граница g_patterns[patternArray].patternTarget = (newPattern == BULL_TYPE)? BuyTP : SellTP; g_patterns[patternArray].getTarget = (IsPatternWorked(g_patterns[patternArray]) == WORKED)? WORKED : ACTUAL; SignalOnPattern(g_patterns[patternArray], isAlert,index,lastAlert,soundpattern); } } Сделать везде одинаковый порядок вызова функций, определяющих наличие паттерна. Паттерн, обрабатываемый первым, получит наивысший приоритет. И с порядком теперь получается порядок )) По поводу перекрытости паттернов ломаю голову дальше в плане установления приоритетности паттернов... Ведь нигде в коде не обозначено, что последовательность имен паттернов в enum ENUM_PATTEN_NAME enum ENUM_PATTEN_NAME { NONE_INDEX =-1, RAILS_, OVB_, WRB_, PPR_ }; задает приоритет PPR над всеми остальными. Или только в совокупности расположения в ENUM_PATTEN_NAME и такой же последовательности вызова функций определяет приоритет? Этот момент не укладывается в голове )) Еще такой момент: необходимо снизить нагрузку на компьютер. Найденное большое количество паттернов записанное в массив нагружает систему... а если много пар в работе - зависон полный будет. Решение проблемы пока такое вижу - запись параметров найденных и неперекрытых паттернов в файл, откуда функция ShowPatterns будет считывать исторические данные по символу и отрисовывать, а массив g_patterns - либо обнулять, либо пусть помнит не более 20-30 последних найденных паттернов, при деинициализации индикатора скидывал бы их в этот файл. Как по вашему рациональный подход или есть более оптимальный вариант, который мне пока в голову не приходит? PS. Еще раз почитав код индикатора "Всплеск и полка" пришел к окончательному выводу - держать в памяти отработанные паттерны в принципе нет - они только нагружают ПК.. поэтому концовку представленной выше функции будет выглядеть так //== и подадим сигнал SignalOnPattern(g_patterns[patternArray], isAlert,index,lastAlert,soundpattern); } //== Если включен флаг "Не показывать перекрытые паттерны удалим лишние if(!OverLaidPattern) { ProcessPatterns(index); } // == Раскрасим патерны и удалим отработанные из массива for(int j = ArraySize(g_patterns)-1; j >= 0; j--) { ReDrawPattern(g_patterns[j]); if(g_patterns[j].getTarget == WORKED) DeleteElementFromArray(g_patterns, j); } } А запись в файл полезно будет лишь в случае исследования паттернов на предмет факта отработки по имени паттерна, его направлению и сроку отработки (сколько времени прошло с момента формирования до момента отработки).

Scriptong: evbut пишет: Не знаю насколько оптимальное решение, но все эти функции вывел в FillPatternsDB (переименовал ее трохи) Не самое плохое решение Можно и так. В итоге приоритет поиска паттернов в данном случае получается следующий: 1. PPR (т. к. его поиск идет самым последним, а, значит, паттерн при нахождении затрет любой другой паттерн) 2. WRB 3. OVB 4. Рельсы Сразу возникает вопрос: если на одном баре было зарегистрировано сразу четыре разных паттерна (гипотетически), и нам заранее известно, что будет принят только PPR, то зачем производился поиск всех остальных паттернов? Ответ на этот вопрос: не нужно так делать. Паттерн с наивысшим приоритетом должен разыскиваться первым. Если же этот паттерн найден, то к поиску других паттернов даже приступать не стоит: if(IsShowPPRPattern) { if(IsBullsPPRPattern(index)) { newPattern = BULL_TYPE; newPatternName = PPR_; startBar = index + 2; } if(IsBearsPPRPattern(index)) { newPattern = BEAR_TYPE; newPatternName = PPR_; startBar = index + 2; } } if(IsShowSourcePattern && newPatternName == NONE_INDEX) { if(IsBullsWRBPattern(index)) { newPattern = BULL_TYPE; newPatternName = WRB_; startBar = index + 2; } if(IsBearWRBPattern(index)) { newPattern = BEAR_TYPE; newPatternName = WRB_; startBar = index + 2; } } if(IsShowOVBPattern && newPatternName == NONE_INDEX) { if(IsBUOVBPattern(index)) { newPattern = BULL_TYPE; newPatternName = OVB_; startBar = index + 1; } if(IsBEOVBPattern(index)) { newPattern = BEAR_TYPE; newPatternName = OVB_; startBar = index + 1; } } if(IsShowRailsPattern && newPatternName == NONE_INDEX) { if(IsBullsRailsPattern(index)) { newPattern = BULL_TYPE; newPatternName = RAILS_; startBar = index + 1; } if(IsBearsRailsPattern(index)) { newPattern = BEAR_TYPE; newPatternName = RAILS_; startBar = index + 1; } }

Scriptong: evbut пишет: И с порядком теперь получается порядок )) По поводу перекрытости паттернов ломаю голову дальше в плане установления приоритетности паттернов... Ведь нигде в коде не обозначено, что последовательность имен паттернов в enum ENUM_PATTEN_NAME Приоритеты поиска паттернов не зависят от последовательности объявления паттернов в перечислении. Приоритет назначается программно. Как именно - показал постом выше.

Scriptong: evbut пишет: Еще такой момент: необходимо снизить нагрузку на компьютер. Найденное большое количество паттернов записанное в массив нагружает систему... а если много пар в работе - зависон полный будет. Решение проблемы пока такое вижу - запись параметров найденных и неперекрытых паттернов в файл, откуда функция ShowPatterns будет считывать исторические данные по символу и отрисовывать, а массив g_patterns - либо обнулять, либо пусть помнит не более 20-30 последних найденных паттернов, при деинициализации индикатора скидывал бы их в этот файл. Как по вашему рациональный подход или есть более оптимальный вариант, который мне пока в голову не приходит? Так, для справки: файловые операции, даже на SSD-диске многократно уступают по скорости в сравнении с оперативной памятью. Именно поэтому все программы для совей работы записывают данные в оперативную память, а не в файл. В файлы данные пишутся для хранения, пока программа не работает. Проблема большой нагрузки в данном случае не в том, что происходит работа с памятью, а в том, что программа занимается лишней работой. Так, посмотрев работу программы в профилировщике, сразу видим корень зла: Это функция IsPatternWorked(). В ней каждый паттерн на каждом новом баре проверяется на предмет отработки (достижения цели). Более того, на каждом баре функция вызывается дважды: в FindPatternsAndFillDB() и в ReDrawPattern(). Лишняя работа заключается в том, что сразу при обнаружении паттерна производится проход по все истории от момента возникновения паттерна до текущего момента времени. Зачем? Ведь у нас уже имеется цикл, идущий по истории (в ShowIndicatorData()). Пусть он и задает текущий бар, на котором нужно проверять отработку паттерна. При таком подходе в IsPatternWorked исчезнет цикл, что сразу решит проблему быстродействия.

Genry: Встретился мне на забугорном форуме http://www.for-exe.com/mt4-free-indicators--scripts.html индикатор snorm_multibar_pinbar с подобной реализацией идеи отображением паттернов, но только для Пин-бара.

evbut: Так, развейте не стыковку по вашим высказываниям. Порядок приоритетности я брал из статьи по индикатору "Простые паттерны" (и в нем же порядок поиска паттернов располагается по возрастающему, с ваших слов в статье, приоритету - от "Inside Bar" до Island Reversal) и здесь Scriptong пишет: 1. PPR (т. к. его поиск идет самым последним, а, значит, паттерн при нахождении затрет любой другой паттерн) И далее по тексту читаю Scriptong пишет: Паттерн с наивысшим приоритетом должен разыскиваться первым.. Так как же на самом деле правильно? Лирическое отступление ))) Логически как бы понятно, что чем реже встречается паттерн, тем сильнее он. Среди двух баровых - "Поглащение" будет сильней Рельс. Среди трех баровых из моего списка наверно предпочтение нужно отдать WRB... Но тот же PPR чаще встречается, чем теже Рельсы или Поглащение... И думается мне, что приоритетность на одном баре нужно определять как в поговорке "Кто первый встал, того и тапки" Использование такого подхода получается частично избавляет от необходимости удалять перекрытые паттерны. А пока что не могу избавиться от функции ENUM_PATTEN_NAME NamePattern(int index) { if(IsBullsPPRPattern(index) || IsBearsPPRPattern(index)) return PPR_; if(IsBullsWRBPattern(index) || IsBearWRBPattern(index)) return WRB_; if(IsBUOVBPattern(index) || IsBEOVBPattern(index)) return OVB_; if(IsBullsRailsPattern(index) || IsBearsRailsPattern(index)) return RAILS_; return NONE_INDEX; } Чтобы реализовать удаление перекрытых... Как говориться: "в голове вертится, а на язык не идет"... т.е. понимаю, что функционал удаления, можно воткнуть также в функцию FindPatternsAndFillDB на этапе нахождения минимум первых 3ёх любых паттернов, чтобы просто не давать накладывающимся паттернам записываться в БД согласно их приоритету. Спасибо за наводку с профилированием - теперь знаю для чего нужна эта кнопочка )))

Scriptong: evbut пишет: Так, развейте не стыковку по вашим высказываниям. Порядок приоритетности я брал из статьи по индикатору "Простые паттерны" (и в нем же порядок поиска паттернов располагается по возрастающему, с ваших слов в статье, приоритету - от "Inside Bar" до Island Reversal) и здесь Все зависит от логики программы. Можно построить логику так, что, найдя паттерн, будет произведен выход из функции поиска. На мой взгляд, это наиболее приемлемый вариант, т. к. отсекаются лишние действия. В предложенном Вами варианте структура функции создана иначе (наоборот): так, что происходит поиск всех паттернов подряд и запись результата поиска в одну и ту же переменную. Поэтому логично, что паттерн, поиск которого следует последним, затрет информацию о всех ранее найденных паттернах. Таким образом, по хорошему, функцию FindPatternsAndFillDB нужно разбить на несколько более мелких функций, сделав поиск паттерна с наивысшим приоритетом первым. Если паттерн найден, то остальные даже не разыскиваются. А вот если паттерн не найден, то происходит переход к поиску следующего паттерна.

evbut: Scriptong пишет: Таким образом, по хорошему, функцию FindPatternsAndFillDB нужно разбить на несколько более мелких функций, сделав поиск паттерна с наивысшим приоритетом первым. Если паттерн найден, то остальные даже не разыскиваются. А вот если паттерн не найден, то происходит переход к поиску следующего паттерна. Функцию на мелкие не стал разбивать - но предложенный вами вариант f(IsShowPPRPattern && newPatternName == NONE_INDEX) позволил сократить число обращение функций ккаждому бару, Так теперь поиск самого важного паттерна WRB происходит на 1000 барах, поиск PPR происходит уже на 949 барах, а паттерн рельсы вообще ищется только 783 барах. И кстати говоря, функцию IsPatternWorked маленько модифицировал, но суть осталась прежней и она таки не тормазит индикатор теперь, а число обращений к ней составляет общему числу найденных паттернов, в текущем случае - 303 раза.

Scriptong: evbut пишет: И кстати говоря, функцию IsPatternWorked маленько модифицировал, но суть осталась прежней и она таки не тормазит индикатор теперь, а число обращений к ней составляет общему числу найденных паттернов, в текущем случае - 303 раза. Вы убрали цикл из этой функции? Если цикл убрать, то индикатор будет "летать"

evbut: Это функция IsPatternWorked(). Познакомился с профилированием..Двойной вызов этой функции убрал. Вызовов самой функции сейчас на 1000 баров истории составляет 278, что соответствует количеству найденных паттернов. Однако вызовов iLow в ней 20650, хотя iHigh из нее же - 4951. Откуда такая разница в вызове этих строк, ведь они выполняют похожие действия и баров одинаковое количество проверяют? По логике их должно быть максимум 278 каждая...



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