Форум » Индикаторы » Простые паттерны Price Action » Ответить

Простые паттерны Price Action

evbut: Добрый день! Уж простите коль не в нужном месте тему создал. Хотел выразить большое спасибо автору советника и индикатора по прайсэкшен, которые обнаружил ЗДЕСЬ. Поиск самого автора привел меня сюда. Мне интересна тема прайсэкшен и торгую по ней, в основном рельсы, поглощение, PPR. Но использую другой подход - ТП рассчитываю через фибо от величины паттерна. Хотелось бы расположенный по ссылке советник адаптировать под свою стратегию, т.е. убрать из него автооптимизацию и автоподстановку СЛ и ТП, а ввентить установку ТП через фибо (параметр настраиваемый) и СЛ, который устанавливается на вершине (для продаж) или дне паттерна (для покупок). Буду премного благодарен, если отзовется автор или кто другой кто сможет переделать советник

Ответов - 35 новых, стр: 1 2 3 All

Scriptong: Добрый день. Это сделать достаточно легко: 1. Строки: extern string A2 = "Профит в пунктах от цены открытия позиции"; extern int defaultTP = 50; заменить на: extern string A2 = "Профит в % от высоты паттерна"; extern double percentTP = 131.8; 2. Функцию GetTP заменить на такую: double GetTP(int patternDir, int patternStart) { RefreshRates(); double patternHigh = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, patternStart, 1)); double patternLow = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, patternStart, 1)); double patternHeight = patternHigh - patternLow; if (patternDir == PATTERN_BEAR) return (patternHigh - patternHeight * percentTP / 100.0); return (patternLow + patternHeight * percentTP / 100.0); } 3. Запускать с отключенной автооптимизацией.

evbut: Scriptong пишет: 2. Функцию GetTP заменить на такую: Спасибо большое за оперативность. Ваше предложение работает! Если не затруднит Вас, хотел бы еще попросить Вас подправить или дайть совет-наводку как самому подправить вот такой момент. Если отключаю закрытие по противоположному сигналу, советник открывает ордера и в бай и селл - в принципе так и надо для меня, но хотелось бы, чтоб в рынке могло быть только 1 ордер бай и один ордер селл (одновременно), каждый из которых при появлении паттерна в соответствующую сторону модифицировался, т.е. ТП и СЛ переносился бы при условии, что уровень ТП нового паттерна ваше/ниже предыдущего (см. картинку), а СЛ под/над новый паттерн. Сейчас если убираю из кода if (g_type == OP_BUY) if (!CloseDeal(g_ticket)) return(false); он открывает несколько ордеров бай и селл, а как модификация происходит не пойму что-то.

Scriptong: evbut пишет: Если не затруднит Вас, хотел бы еще попросить Вас подправить или дайть совет-наводку как самому подправить вот такой момент. Если отключаю закрытие по противоположному сигналу, советник открывает ордера и в бай и селл - в принципе так и надо для меня, но хотелось бы, чтоб в рынке могло быть только 1 ордер бай и один ордер селл (одновременно), каждый из которых при появлении паттерна в соответствующую сторону модифицировался, т.е. ТП и СЛ переносился бы при условии, что уровень ТП нового паттерна ваше/ниже предыдущего (см. картинку), а СЛ под/над новый паттерн. Для этого советник нужно переписывать полностью. Он станет несколько сложнее. Ведь в текущем представлении он потому и является таким простым, что работает с одним ордером. evbut пишет: Сейчас если убираю из кода  цитата: if (g_type == OP_BUY) if (!CloseDeal(g_ticket)) return(false); он открывает несколько ордеров бай и селл, а как модификация происходит не пойму что-то. Конечно. Ведь в таком случае советник попросту теряет свои ордера. Вы убрали из кода контроль за тем, что в рынке всегда присутствует только один ордер советника. В итоге советник на каждом тике случайным образом получает информацию только об одном из своих открытых ордеров. Остальные "теряются".


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

Scriptong: evbut пишет: Попробую самостоятельно подогнать имеющийся код под свою идею. Примеров полно здесь и учебник по MQL мне в помощь В учебнике есть для этого специальная глава Учет ордеров. Что-то вроде этого нужно будет организовать в собственном советнике, чтобы работать со множеством ордеров.

evbut: Еще раз здравствуйте! Для ручной торговли немного урезал и модифицировал индикатор PriceAction, добавив в него отображение уровне целей по фибо. На картинке в предыдущем посте их видно. Есть желание еще маленько подправить отображение как самих паттернов, так и их уровней целей. А именно, чтобы при заданном количестве используемых баров истории ( indBarsCount = 500) была возможность выбрать отображать либо все имеющиеся графические объекты (паттерны и их цели), либо только те, которые еще, так скажем не отработаны. Под "не отработанными паттернами" подразумевается, что цена не была на уровне цели (черточка на картинке предыдущего поста). Как это реализовать - затруднительно для меня, т.к. далеко начинающий программист ) Для реализации этой задачи, мне видится, необходимо выполнить следующее: 1. Произвести поиск бара, с которого ведется отсчет для построений. 2. На этом участке найти максимальную и минимальную цену - этим мы определим диапазон цен 3. Сравнить была ли черточка (линия цели) в этом диапазоне или находится за его пределами 3.1. если была - удалить (или не отображать) объекты иначе оставить до тех пор пока цена не побывает на это уровне С первым пунктом понятно он есть в индикаторе в функции int GetRecalcIndex(int& total). //+-------------------------------------------------------------------------------------+ //| Определение индекса бара, с которого необходимо производить перерасчет | //+-------------------------------------------------------------------------------------+ int GetRecalcIndex(int& total) { int counted_bars = IndicatorCounted(); // Сколько баров уже посчитано total = Bars - 1; // Определение первого бара истории if (indBarsCount > 0 && indBarsCount < total) // Если не нужно рассчитывать всю.. total = indBarsCount; // ..историю, то начнем с указанного.. // ..бара - indBarsCount if (counted_bars == 0) // Кол-во посчитанных баров - 0. { DeleteAllObjects(); // Не забудем удалить все созданные.. // ..объекты return(total); // Нужно пересчитать всю историю } return(Bars - counted_bars - 1); // Начинаем с первого непосчитанного.. // ..бара } Функция удаления объектов тоже есть //+-------------------------------------------------------------------------------------+ //| Удаление всех объектов, созданных индикатором | //+-------------------------------------------------------------------------------------+ void DeleteAllObjects() { for (int i = ObjectsTotal()-1; i >= 0; i--) if (StringSubstr(ObjectName(i), 0, StringLen(PREFIX)) == PREFIX) ObjectDelete(ObjectName(i)); } Подскажите в какую сторону капать? Функцию удаления нужно будет править, добавив в нее поиск объекта в диапазоне цен или же создать отдельную функцию типа DelObjectAfterGetTarget? Прикрутил файл индикатора на всякий случай https://yadi.sk/d/nZxAAhreqwjwD

Scriptong: evbut пишет: Под "не отработанными паттернами" подразумевается, что цена не была на уровне цели (черточка на картинке предыдущего поста). Как это реализовать - затруднительно для меня, т.к. далеко начинающий программист ) Для реализации этой задачи, мне видится, необходимо выполнить следующее: 1. Произвести поиск бара, с которого ведется отсчет для построений. 2. На этом участке найти максимальную и минимальную цену - этим мы определим диапазон цен 3. Сравнить была ли черточка (линия цели) в этом диапазоне или находится за его пределами 3.1. если была - удалить (или не отображать) объекты иначе оставить до тех пор пока цена не побывает на это уровне Да, рассуждения верные. После нахождения паттерна нужно произвести сканирование истории в будущее (вправо по графику) до бара, на котором будет найден следующий паттерн. На этом участке найти границы минимума и максимума и сравнить их с заданной ценой. То есть внутри цикла перебора баров нужно организовать еще один цикл. По самой же сути новшества. Такие индикаторы называются перерисовывающимися. К ним отношение у всех отрицательное, т. к. они вводят трейдеров в заблуждение - на истории выглядят отлично, а в реальности ни на что не годятся. Поэтому при разработке любого индикатора нужно всегда проверять, не заглядывает ли он в будущее.

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

Scriptong: evbut пишет: Вы хотите сказать, что идея не отображения "неотработавших" паттернов приведет к перерисовыванию индикатора? но он же не будет таковым, т.к. шарить он будет только по истории слева направо до 1 бара или до поледнего сформировавшегося паттерна, который уж точно не будет отработанным. Дело вот в чем. Представим, что индикатор запущен и ищет новые паттерны. Как только слева от текущего бара образовался паттерн, его нужно отобразить. Но если у нас имеется дополнительное условие "не отображать паттерн, после которого цена не достигла цели", то такой паттерн отображен не будет. Причем, если индикатор не будет переинициализирован (переключен таймфрейм, изменены значени настроечных параметров и т. д.), то паттерн вообще никогда не будет виден трейдеру, даже если после этого паттерна цена достигнет цели. Если же в процессе работы индикатора цена все же достигнет цели и после этого трейдер переинициализирует индикатор, то такой паттерн появится, хотя до этого его не было на графике. Трейдер хватается за голову "такой сигнал пропустил!" Это как раз и есть перерисовка, у которой два варианта: показывать то, что ранее не показывали, или стирать то, что показали ранее, но потом что-то пошло не так.

evbut: Scriptong пишет: Если же в процессе работы индикатора цена все же достигнет цели и после этого трейдер переинициализирует индикатор, то такой паттерн появится, хотя до этого его не было на графике. Трейдер хватается за голову "такой сигнал пропустил!" Это как раз и есть перерисовка, у которой два варианта: показывать то, что ранее не показывали, или стирать то, что показали ранее, но потом что-то пошло не так. Ситуация как раз таки противоположная - стиреть то, что прошло так как надо. Но этот вопрос не принципиален. Вполне удобно видеть все, что было ) По поводу советника, думал-гадал и кажется мне, что оптимальным будет использовать имеющиеся функции получения сигнала, но их разбить на PATTERN_BULL и PATTERN_BEAR, каждый из которых будет выводиться в свою соответствующую его направлению функцию. Функция работы с бычьими сигналами и функция для работы с медвежьими. Каждая из них будет открывать и модифицировать только свои ордера. Как вы оцените такой подход к решению моей задачи?

Scriptong: evbut пишет: Ситуация как раз таки противоположная - стиреть то, что прошло так как надо. То есть нужно видеть только те сигналы, которые привели к убытку? Достаточно странная постановка задачи На мой взгляд, лучше сделать следующим образом: показывать все, но ввести дополнительный функционал. Он будет заключаться как раз в оценке качества того или иного паттерна. Тот, который не привел к достижению цели, показать одним цветом, а тот, который привел - другим цветом. evbut пишет: По поводу советника, думал-гадал и кажется мне, что оптимальным будет использовать имеющиеся функции получения сигнала, но их разбить на PATTERN_BULL и PATTERN_BEAR, каждый из которых будет выводиться в свою соответствующую его направлению функцию. Функция работы с бычьими сигналами и функция для работы с медвежьими. Каждая из них будет открывать и модифицировать только свои ордера. Как вы оцените такой подход к решению моей задачи? Такой вариант подойдет только в том случае, если по одному направлению планируется не более одного ордера. Но в принципе любую стратегию стоит разбивать на задачи по-другому: есть сигнальный модуль и есть модуль, обрабатывающий имеющиеся ордера. Сигнальный модуль, как и положено, только генерирует сигналы. А вот модуль работы с ордерами должен реагировать на сигналы и, в зависимости от сигнала, открывать или закрывать ордера. В принципе, именно так и сделано в исходном советнике. Просто модуль обработки ордеров не рассчитан на работу с двумя и более ордерами. Вот этот модуль и нужно дорабатывать, составляя список своих ордеров с записью в массив, а уже этот массив обрабатывать.

evbut: Scriptong пишет: Да, рассуждения верные. После нахождения паттерна нужно произвести сканирование истории в будущее (вправо по графику) до бара, на котором будет найден следующий паттерн. На этом участке найти границы минимума и максимума и сравнить их с заданной ценой. То есть внутри цикла перебора баров нужно организовать еще один цикл. День добрый! Хочется всё же реализовать такую возможность. Только вот запутался и кажется прилично. Используя код вашего индикатора со статистикой нашел такой кусок кода, где как раз производится поиск паттернов на истории. Напомню его вам, только маленько я его уже подправил (надеюсь верно) для своих целей: //+-------------------------------------------------------------------------------------+ //| Поиск паттернов указанного типа в истории | //+-------------------------------------------------------------------------------------+ void FindPatterns(int patternType, int total, int& patternCnt, int& patternIndex[], int& patternDir[], double& BullsTargets[], double& BearsTargets[]) { int patternStart; for (int i = 2; i < total; i++) // Идем справа налево по графику,.. { // ..проверяя наличие паттерна на.. int direction = GetPatternDirection(i, total, // .. каждом баре patternType, patternStart); if (direction == PATTERN_NO) // Паттерна нет - идем дальше continue; //найдем переменные для расчетов уровней ТП для бычьих и медвежьих паттернов double lowprice = Low[iLowest(NULL,0,MODE_LOW,patternStart - i + 1, i)]; double highprice = High[iHighest(NULL,0,MODE_HIGH,patternStart - i + 1, i)]; double patternHeight = highprice - lowprice; // ------- нашли --------------------------------------------------------------------------- patternIndex[patternCnt] = i; // Паттерн есть - запишем номер бара, patternDir[patternCnt] = direction; // ..направление паттерна,.. if (direction == PATTERN_BULL) // ..и рассчитаем уровень ТП BullsTargets[patternCnt] = lowprice + patternHeight * FiboTarget / 100.0; else BearsTargets[patternCnt] = highprice - patternHeight * FiboTarget / 100.0; patternCnt++; // Количество паттернов увеличилось } } Если я правильно понимаю логику этого куска, то по запросу он должен выдать общее количество всех паттернов в виде массива, их направление, а также выдать массивы целей бычьих и медвежьих паттернов. Теперь получается мне необходимо на участке истории for (int i = limit; i > 0; i--) сравнивать массивы целей с хай и лоу каждой свечи. В этом же месте это делать или в отдельной функции? И еще такой момент. Представленный выше кусок подходит для нахождения непосредственно паттернов, поскольку отрисованные паттерны на графике на сколько я понимаю лишь прямоугольники. Они не находятся в виде массива? Подправленная версия с таргетами как показывал на картинке здесь отображает эти самые таргеты которые хранятся в виде переменной BuyTP и SellTP, которые можно прописать в массив. Во всяком случае когда я принтую одну из этих переменных, то отображаются действительные ценовые уровни, те что расчитываются и наносятся на график. Кусок кода где рассчитываются чтобы потом отобразиться - для бычьих паттернов: void ShowBullPattern(int startIndex, int endIndex, color clr, int patternType, string description) { // - 1 - == Поиск верхней и нижней границ паттерна ====================================== double lowPrice = Low[iLowest(NULL, 0, MODE_LOW,// Нижняя граница паттерна startIndex - endIndex + 1, endIndex)]; double highPrice = High[iHighest(NULL, 0, // Верхняя граница паттерна MODE_HIGH, startIndex - endIndex + 1, endIndex)]; double patternHeight; // - 1 - == Окончание блока ============================================================= // - 2 - == Отображение прямоугольника ================================================== datetime leftTime = Time[startIndex]; // Начальное время паттерна datetime rightTime = Time[endIndex]; // Конечное время паттерна string name = GetObjectName(endIndex, patternType, FIRST_PART);// Имя объекта паттерна ShowRectangle(name, leftTime, lowPrice, // Отображение объекта rightTime, highPrice, description, clr); // - 2 - == Окончание блока ============================================================= // - 3 - == Расчет ТП ================================================================== patternHeight = highPrice - lowPrice; BuyTP = lowPrice + patternHeight * FiboTarget / 100.0; name = GetObjectName(endIndex, patternType, SECOND_PART); //имя объекта ТП ShowBullTarget(name, leftTime, BuyTP, rightTime, BuyTP, description, clr); } Может имеет смысл по этому пути пойти. Взять все эти BuyTP и SellTP в виде массива, и прогнать по истории for (int i = limit; i > 0; i--) сравнивая с хай и лоу каждой последующей свечи, чтобы потом перекрасить прямоугольник паттрена? Вот только я, как абсолютный новичок в кодировании не совсем соображаю как мне сравнивать две группы массивов - массивы таргетов и массивы хай и лоу. Просто по ценам сравнить наверно будет не правильно... нужно же еще привязку по свечам делать или нет? В общем в замешательстве и путанице. Помогите распутаться, пожалуйста! С уважением Евгений.

Scriptong: evbut пишет: Если я правильно понимаю логику этого куска, то по запросу он должен выдать общее количество всех паттернов в виде массива, их направление, а также выдать массивы целей бычьих и медвежьих паттернов. Такой подход даст лишь сами уровни целей для каждого паттерна. Но ведь нужно еще проверить, были ли достигнуты эти уровни на участке истории между одним паттерном и другим. Поэтому делать отдельную функцию после вызова FindPatterns - это выполнение одной и той же работы дважды. Недостающий функционал нужно располагать именно в FindPatterns. evbut пишет: Может имеет смысл по этому пути пойти. Взять все эти BuyTP и SellTP в виде массива, и прогнать по истории for (int i = limit; i > 0; i--) сравнивая с хай и лоу каждой последующей свечи, чтобы потом перекрасить прямоугольник паттрена? Это то же самое, о чем я говорил выше - двойной труд. Следует расширять обязанности FindPatterns, дробя ее на вызовы других функций.

evbut: Scriptong пишет: Но ведь нужно еще проверить, были ли достигнуты эти уровни на участке истории между одним паттерном и другим. Проверить необходимо не между паттернами, а от момента формирования паттерна до первой свечи. И так с каждым паттерном в истории и тем что сформировался на на предыдущей свече. Буду копать дальше. Еще маленькая просьба поправьте если я не прав. Вот чтобы сравнить уровень цели, допустим BuyTP, c хаями каждой последующей свечи после формирования паттерна я должен прописать так? for(int i = endIndex - 1; i > 0; i--) { if(BuyTP > High[endIndex -1 - i]) то выполнить то-то

Scriptong: evbut пишет: Проверить необходимо не между паттернами, а от момента формирования паттерна до первой свечи. И так с каждым паттерном в истории и тем что сформировался на на предыдущей свече. Тогда подход должен быть совершенно другой, сложнее. Почему сложнее? Потому что нужно "помнить" информацию о каждом паттерне (месте формирования, его параметрах, целях), а с появлением каждой новой свечи (даже каждой новой цены, т. е. на каждом тике) проверять, не была ли достигнута заданная цель по каждому из несработавших паттернов. Как только достигнута цель, то паттерн удаляется (или отображается, смотря, что нужно). Таким образом, алгоритм будет примерно такой: 1. Поиск паттерна. 2. Запись паттерна в базу данных паттернов. 3. Проверка "срабатывания" паттерна. 4. Если паттерн "сработал", он удаляется из базы данных и происходит коррекция его отображения (удаление или отображение на графике). Это далеко не три-четыре строки кода. Сложность чуть ниже среднего уровня программирования.



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