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

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

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

evbut: evbut пишет: Посмотрю уже в следующем году С Новым Годом, Игорь! Спасибо Вам за неизменную поддержку и Ваш профессионализм в прошлом году! В новом году желаю успеха в реализации Ваших задумок, благополучия и мирного неба Вам и вашей семье!

Scriptong: evbut пишет: Тынц Ссыль действительна 6 дней Посмотрел. Не увидел в коде участка, отвечающего за перерисовку паттерна. Так, функция ProcessBar обслуживает только новые бары. Она никогда не повторяет расчет одного и того же бара. Поэтому паттерн может быть только найден. Его дополнительная проверка не производится. Возможно проверка задумывалась в функции IsActualPattern(), но эта функция нигде в коде не вызывается. Даже, если она будет вызвана, то это ни к чему не приведет, т. к. функция меняет лишь статус паттерна, но не производит его перерисовку.

evbut: Scriptong пишет: Возможно проверка задумывалась в функции IsActualPattern(), но эта функция нигде в коде не вызывается. Даже, если она будет вызвана, то это ни к чему не приведет, т. к. функция меняет лишь статус паттерна, но не производит его перерисовку. Собственно да, один из вариантов реализации отображения отработки паттернов было как раз через эту функцию, что-то в этом духе void ReDrawPattern(Pattern &pattern) { IsActualPattern(pattern); if(ShowWorkedPattern && pattern.getTarget == WORKED && (pattern.patternType == BEAR_TYPE || pattern.patternType == BULL_TYPE)) { pattern.patternColor = WorkColor; } else { if(pattern.patternType == BEAR_TYPE) pattern.patternColor = RegcolorBears; else pattern.patternColor = RegcolorBulls; } ShowPatterns(pattern); Далее в OnCalculate так прописал int limit=GetRecalcIndex(total); // Определим первый расчетный бар for (int i = limit; i > 0; i--) { FillPatternsDB(i); //функция наполнения базы паттернов типа void for(int k = ArraySize(g_patterns)-1; k>=0; k--) ReDrawPattern(g_patterns[k]); //собственно отрисовка } WindowRedraw(); От вашего варианта как во Всплеск и Полка пока отошел... и по сему понимаю, что кривая конструкция, но с праздниками этими все в голове перемешалось... В тестере вроде рисуется с использованием этой функции... Новый паттерн отрисовывает в сине-красных цветах, и даже отработанные показывает, только не на том месте где он действительно есть, а со смещением к нулевому бару, а точней к тому бару на котором была зафиксирована его отработка паттерна (ВИДЕОзаписал ). Решение кажется нашлось... в функции GetUniqueID было внесено отображение факта отработки паттерна. ТАк вот получалось, что индикатор не находил прямоугольник патерна с подписью ACTUAL, потому что он уже был WORKED, поэтому рисовал его поновой в другом месте..


Scriptong: evbut пишет: Собственно да, один из вариантов реализации отображения отработки паттернов было как раз через эту функцию, что-то в этом духе  цитата: void ReDrawPattern(Pattern &pattern) { IsActualPattern(pattern); if(ShowWorkedPattern && pattern.getTarget == WORKED && (pattern.patternType == BEAR_TYPE || pattern.patternType == BULL_TYPE)) { pattern.patternColor = WorkColor; } else { if(pattern.patternType == BEAR_TYPE) pattern.patternColor = RegcolorBears; else pattern.patternColor = RegcolorBulls; } ShowPatterns(pattern); Далее в OnCalculate так прописал Ну это уж совсем никудышное решение. Во-первых, производится повторение одних и тех же действий (вызов функции FillDBPatterns() теперь будет дважды на одном и том же баре и, приводит к дублированию паттернов в массиве - см. журнал). Во-вторых, дважды производится определение отработки паттерна (логика размазана по двум функциям RecolorPattern() и ReDrawPattern()), что затрудняет понимание кода. Также в процессе просмотра кода увидел основную проблему: при нахождении паттерна запонимаются номера баров, где он найден (члены leftBarIndex и rightBarIndex структуры Pattern). При таком подходе требуется поддерживать номера баров в дальнейшем, т. к. номер бара - не уникальный идентификатор. Номера баров изменяются в момент прихода нового бара. В итоге тот бар, который сохранен для паттерна оказывается невалидным. Поэтому нужна поддержка индексов. Или же, лучший подход, запоминать не индекс бара, в время открытия баров. Это уже уникальные данные, которые никогда не изменяться.

evbut: Игорь, подскажите, достаточно ли будет на этом этапе в функции наполнения БД паттернов int patternArray=ArraySize(g_patterns); for (int i = patternArray - 1; i >= 0; i--) if (g_patterns.patternType == newPattern && g_patterns.patternName == newPatternName && g_patterns.leftBarIndex == startBar && g_patterns.rightBarIndex == endBar ) return FUNCTION_RESULT_ALRIGHT; прописать для проверки только эти характеристики паттерна или же нужно проверить все согласно прописанного в структуре (за исключением patternTarget, getTarget и patternColor? ENUM_PATTERN_TYPE patternType; // Тип паттерна (бычий, медвежий) ENUM_PATTEN_NAME patternName; // Индекс имени паттерна ENUM_GET_TARGET getTarget; // Отработан ли патерна int leftBarIndex; // Индекс левого бара паттерна int rightBarIndex; // Индекс правого бара паттерна double patternLowPrice; // Нижняя цена паттерна double patternHighPrice; // Верхняя цена паттерна double patternHeight; // Высота паттерна double patternTarget; // Уровень цели бычьего паттерна color patternColor; // ЦВет паттерна И еще несколько вопросов по коду функции из инидкатора Всплеск и полка ShowIndicatorData(int limit, int total) { if (limit > 1) { ArrayResize(g_patterns, 0, ARRAY_RESERVE_SIZE); g_lastBuyPatternRegFractalTime = 0; g_lastSellPatternRegFractalTime = 0; } if (limit == 1) for (int i = ArraySize(g_patterns) - 1; i >= 0; i--) { g_patterns.leftBarIndex++; g_patterns.rightBarIndex++; } for (int i = limit; i >= 0; i--) if (!ProcessBar(i)) return false; Под limit подразумевается количество баров или собственно ограничение в барах? Да и в целом я правильно понимаю результат этой функции: при limit > 1 задаем новый размер массива паттернов, при limit == 1 - изменяем номера баров границы паттернов, и в последнем случае отрисовываем что желаем?

Scriptong: evbut пишет: Игорь, подскажите, достаточно ли будет на этом этапе в функции наполнения БД паттернов прописать для проверки только эти характеристики паттерна или же нужно проверить все согласно прописанного в структуре (за исключением patternTarget, getTarget и patternColor? Пока суть вопроса неясна. Конкретизируйте, пожалуйста.

Scriptong: evbut пишет: Под limit подразумевается количество баров или собственно ограничение в барах? В данном случае то, что представляет собой переменная limit, описано в функции OnCalculate: int total; int limit = GetRecalcIndex(total, rates_total, prev_calculated); if (!ShowIndicatorData(limit, total)) g_activate = false; В свою очередь, GetRecalcIndex прокомментирована: Determination of bar index which needed to recalculate. Это означает, что переменная limit получает индекс бара, с которого на текущем тике необходимо вычислять значения индикатора. Так, при первом запуске индикатора limit получит индекс самого левого бара в истории минус 2 (ratesTotal - 3), если значение параметра "Количество баров отображения" равно 0. В пртивном случае переменная limit будет равна значению этого параметра. При повторном вызове функции OnCalculate индикатора значение limit будет равно 0, если на текущем баре уже были вычисления, и 1, если образовался новый бар. Больше 1 при повторном вызове OnCalculate переменная limit будет только в случае подкачки истории котировок. Такой подход позволяет оптимизировать работу индикатора: с каждым новым тиком производится перерасчет только вновь поступивших данных. В противном случае индикатор на каждом тике производил бы перерасчет всей имеющейся истории.

evbut: Scriptong пишет: Такой подход позволяет оптимизировать работу индикатора: с каждым новым тиком производится перерасчет только вновь поступивших данных. В противном случае индикатор на каждом тике производил бы перерасчет всей имеющейся истории. Выходит проблема не перекрашивания отработанных паттернов зарыта в этой области. Значит саму функцию пересчета баров необходимо сделать так, чтобы на каждом новом баре индикатор в массиве паттернов искал все ACTUAL и от самого левого из них перепроверил их актуальность.

evbut: Игорь, не подскажите, почему при смене тайм-фрейма остаются элементы с которого ушел?

Scriptong: evbut пишет: Игорь, не подскажите, почему при смене тайм-фрейма остаются элементы с которого ушел? У меня такое не наблюдается. Проверил на последней версии (со вставкой приведенного Вами кода).

evbut: Scriptong пишет: У меня такое не наблюдается. Странно очень... Такое отмечается, когда переключаешься с меньшего фрейма на больший. Однако в функцию ShowIndicatorData прописал if(limit > 1) ArrayResize(g_patterns,0); и кажется перестало такое безобразие мельтешить... Не критично конечно, но мешает. Такой еще момент. Решил добавить опционально удаление перекрытых паттернов. Код такой //+-----------------------------------------------------------------------------+ //| Process specify pattern | //+-----------------------------------------------------------------------------+ bool IsNeedToDeletePattern(const Pattern &pattern, int index) { if(OverLaidPattern) return false; for (int i = index; i < pattern.leftBarIndex; i++) { if(NamePattern(i) < 0) { return false; i--; } } return true; } //+-----------------------------------------------------------------------------+ //| Delete specify element from array | //+-----------------------------------------------------------------------------+ template<typename T> void DeleteElementFromArray(T &array[], int elementToDelete) { int arraySize = ArraySize(array); if (arraySize == 0) return; array[elementToDelete] = array[arraySize - 1]; ArrayResize(array, arraySize - 1, ARRAY_RESERVE_SIZE); } //+-----------------------------------------------------------------------------+ //| Process on overlaid pattern | //+-----------------------------------------------------------------------------+ void ProcessPatterns(int index) { for (int i = ArraySize(g_patterns) - 1; i >= 0; i--) if (IsNeedToDeletePattern(g_patterns, index-1)) DeleteElementFromArray(g_patterns, i); } Судя по картинкам - удаляет те двухсвечные, паттерны, которые находятся как бы внутри трехсвечного паттерна. Однако "чистка" среди трехсвечных не происходит (подчеркнул на картинке явное наложение. По идее синий паттерн должен быть удален). Каким образом заставить и такие участки удалять или где-то в коде косякнул?

Scriptong: evbut пишет: Странно очень... Такое отмечается, когда переключаешься с меньшего фрейма на больший. Однако в функцию ShowIndicatorData прописал Проверил, переключившись а М1 на Н1. Все ОК. evbut пишет: и кажется перестало такое безобразие мельтешить... Не критично конечно, но мешает. Это, кстати, правильный ход. Только лучше такой код разместить в GetRecalcIndex() после строки ObjectsDeleteAll(). Ведь объекты удаляются, а массив g_patterns в итоге будет содержать паттерны-дубликаты. evbut пишет: Такой еще момент. Решил добавить опционально удаление перекрытых паттернов. Код такой Нужно знать, откуда вызывается этот код. В самом же коде есть логическое упущение - в функции IsNeedToDeletePattern() проверяется только совпадение правых краев паттернов, а далее - нет. Кстати, в чем смысл такой конструкции? if(NamePattern(i) < 0) { return false; i--; } Во-первых, после return ничего не может выполняться. Во-вторых, если допустить, что требуется декремент значения i при выполнении условия NamePattern, то все равно смысла нет - происходит выход из функции, значение переменной i теряется. Или же декремент должен был быть за фигурной скобкой? Но тогда получим бесконечный цикл...

evbut: Scriptong пишет: Кстати, в чем смысл такой конструкции? В нее заложен смысл, что если нет именованного паттерна, то и проверять не имеет смысла.

Scriptong: evbut пишет: В нее заложен смысл, что если нет именованного паттерна, то и проверять не имеет смысла. Так а зачем после return происходит декремент? Ведь после return ничего не может выполняться в том же блоке. Возможно, скобкой ошиблись. Но тогда, когда исправите положения скобок, получите зависание индикатора.

evbut: И снова здрасьте... С удалением перекрытых паттернов еще однако разгребать и разгребать... Но вот решил сделать выбор отображения паттернов по отдельности, а не кучей... Уже и не помню ту версию что высылал вам... В общем функция ShowIndicatorData выглядит теперь так void ShowIndicatorData(int limit, int total) { if(limit > 1) ArrayResize(g_patterns,0); for (int i = limit; i > 0; i--) { FillPatternsDB(i); ProcessPatterns(i); for(int j = ArraySize(g_patterns)-1; j >= 0; j--) { if((IsShowOVBPattern && g_patterns[j].patternName == OVB_) || (IsShowPPRPattern && g_patterns[j].patternName == PPR_) || (IsShowRailsPattern && g_patterns[j].patternName == RAILS_)) ReDrawPattern(g_patterns[j]); } } } Включаю по отдельности отображение то рельс, то ППР... И вот при отображении только паттерна Рельсы на некоторых участках встречается вот такое как для бычьих так и для медвежьих направлений (см рис), что совсем не понятно откуда всплывает - Прямоугольник показывает ППР да и выглядит это комбинация свечей как ППР, а в подписи Рельсы (( В настройках параметры Рельс стоят 20 и 10



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