Новый подход к интерпретации классической и обратной дивергенции. Часть 2

Alexander Lasygin | 9 августа, 2019

Введение

В предыдущей статье мы рассмотрели нестандартный подход к интерпретации дивергенции, а если быть точным, то связанных с ней построений, и только вскользь коснулись самой дивергенции, качества ее выявления и классификации. А также совсем не затронули тему возможной фильтрации совершаемых сделок, связанных с этим паттерном. А ведь на самом деле то, что мы привыкли воспринимать как данность, не совсем так однозначно. И вообще, дивергенция в своем классическом виде имеет право на жизнь? Возможно, рынок изменился настолько, что данный подход уже неактуален? В этой части мы ставим перед собой задачу более глубоко рассмотреть тему классического варианта и его нестандартной интерпретации, а также постараемся вынести вердикт для данной стратегии, и, в случае положительного результат, постараемся поднять ее эффективность.

Термины и понятия

Прежде чем приступить к основной части хотелось бы внести небольшую ясность в то, что послужило основой для создания данного материала и в чем его “нестандартность”. В своем желании создать торгового робота, основанного на принципах расхождения, была организована группа единомышленников, в которой мне отводилась роль технического аналитика. Передо мной стояла задача собрать максимум того, что есть по этой теме, и проанализировать большинство инструментов теханализа с целью выявления оптимального варианта.

Также я должен был рассмотреть возможные варианты развития событий после формирования сигнала. Все мои поиски и анализ были простой тратой времени и сил. Для того чтобы что-то найти, надо было просто подумать, а не тратить процессорное время и человеческие ресурсы. В этой работе были и свои достоинства. Был создан индикатор, отличный от того, что уже есть, изменены или исключен ряд понятий, которые только усложняли теханализ. Дивергенция как паттерн “омолодилась” и была упрощена до результата  "или она есть или ее нет", а всякие там классы "А, Б, С" прекратили свое существование.

Дивергенция как сигнал получила новую жизнь. В процессе данной работы стало понятно, что “уравниловка” в любом ее проявлении, всякие там сглаживания и пересчет, не имеют ничего общего с поведением рынка. Это подгонка факта под наше восприятие. Перед нами не стоит цель написать диссертацию на эту тему. Нам надо понять, насколько данный паттерн подходит для торговли или это очередной фейк. Но об этом дальше. Поиск информации по данной теме результата не дал. Складывалось впечатление, что авторы, если и не переписывали друг у друга, то точно получили базовую информацию из одного источника.

Наиболее подробное описание стратегии, основанной на этом принципе, было получено из книги Александра Элдера “Самый сильный сигнал в техническом анализе: Расхождения и развороты трендов”. После прочтения этого труда вопросов стало еще больше. Категоричность автора в вопросе необходимости пересечения линией индикатора нулевого значения соседствует в главе “Расхождения без правого плеча”, хоть и с кратким, но все же описанием моментов, когда это необязательное условие.

В терминале MetaStock линейный MACD в том виде, что мы привыкли, вообще на тот момент отсутствует, это просто две МА в подокне терминала, и он не имеет никакой привязки к “нулю” — как следствие, он неспособен быть использован в том аспекте, в котором предполагает автор. Элдер использует разновидность MACD, которая в  терминале MetaTrader 4/5 имеет имя OsMA, но при этом имя классического MACD проходит через весь материал, что вносит некоторую неразбериху. Описание конвергенции (обратной дивергенции ) вообще отсутствует. Хоть и переводится это с английского как схождение, на самом деле и есть то самое расхождение между поведением цены и индикатора. Также он полностью отвергает анализ с использованием других индикаторов, не имеющих линии баланса (пересечение с нулем). В частности упоминается Stoсhastiс.

В своем желании более глубокого анализа другими авторами было добавлено деление основной фигуры на три подгруппы A,B и C. В совокупности с существующим мнением, что чем больше расхождение, тем сильнее сигнал и в рамках консолидации мы его вообще не рассматриваем, заставило меня задуматься в справедливости тех знаний, которые я получил ранее. Как пример? я привел данное распределение в предыдущем материале. Описание того, почему я не согласен с данной градацией, выходило за рамки первой части, поэтому было принято решение, как и в дальнейшем, оставить все как есть.

Большую часть этих терминов мы использовать не будем, а оставшуюся редко и только для описания общей картины происходящего. Прочтение данного материала, возможно, склонит вас к моей точке зрения, где расхождение существует как факт, а распределение на дивергенцию-конвергенцию рассматривается только в аспекте правил дополнительных графических построений, описанных в предыдущем материале, а сама она условно может делиться только на “останавливающую” и “разворотную”. Почему условно? Дело в том, что по своей сути сигнал является останавливающим, а вот развернет он рынок или нет, мы сможем понять только после получения соответствующего сигнала подтверждения.

Чтобы не быть голословными, несколько примеров сказанного выше.

Дивергенция класса «А»

Считается самой сильной.

Медвежья — новый максимум цены выше предыдущего, а новый максимум индикатора ниже предыдущего.

Бычья — новый минимум цены ниже предыдущего, новый минимум индикатора выше.


Рис.1

Подобное расхождение мы наблюдаем после сильного ценового движения (импульса). Чаще всего подобный импульс является сигналом к зарождению нового тренда, а это значит, что дивергенция класса «А» своей “силой” отменяет это правило, а также инертность поведения рынка и вообще всю волновую теорию. Если правая половина верхнего рисунка может вызвать спор о правильности определения паттерна, то рисунки ниже, скорее всего, не вызовут сомнений.


Рис.2

Также подобное начало развития событий может вызвать не два, и даже не три расхождения, и чем мощнее импульс, тем дольше наш тренд может продолжаться. Это к слову о том, что чем больше расхождение, тем сигнал якобы сильнее.

Дивергенция класса «В»

Менее значимый сигнал на рынке.

Медвежья — максимумы графика находятся на одном уровне, а правый максимум осциллятора ниже левого.

Бычья — минимумы цены на одном уровне, а правое плечо индикатора выше левого.

Это вам ничего не напоминает? Да — классические фигуры технического анализа “Двойная вершина” и “Двойное дно”. Открываем первоисточник и читаем “Сильная модель разворота рынка ”. Даже не остановки, а именно разворота. Она входит в пятерку основных фигур.


Рис.3

Последний подвид из этой троицы.

Дивергенция класса «С»

Считается самой слабой. Есть мнение, что ее лучше вообще игнорировать.

Медвежья — здесь на графике цены наблюдается новый максимум и, несмотря на это, вершины индикатора на одном уровне.

Бычья — цена делает новый минимум, а минимумы осциллятора равны.


Рис.4

Подобное поведение цены характерно на сильных уровнях поддержки и сопротивления, во время так называемого “ложного пробоя” или активных действий маркетмейкеров. Связан он с инертностью индикатора. И если данный сигнал нельзя назвать однозначной точкой входа, то игнорировать уж точно не следует.

И это далеко неполный перечень рассогласований и нестыковок, которые побудили самостоятельно более детально подвергнуть изучению данную тему. Как уже говорилось, мы не будем глобально менять термины и понятия для того, чтобы не вводить в заблуждение  тех, кто уже занимался изучением данного вопроса, и тех, кому еще предстоит это сделать в дальнейшем, не ограничиваясь данным материалом.

Проанализируем наши индикаторы.

MACD

Был создан Джеральдом Аппелем (Gerald Appel) для торговли на фондовом рынке. Данный индикатор очень популярен среди трейдеров. Это обусловлено проверенной годами его эффективностью и, как следствие, множества материалов, описывающих работу с ним, что позволяет ему занять лидирующее положение в нашем условном рейтинге. Само его имя “Moving Average Convergence/Divergence — схождение/расхождение скользящих средних” как будто говорит, что он создан для этой цели. Реально существует две его разновидности, линейный MACD и MACD — гистограмма. 

MACD — линейный:

где:

P — цена, обычно это цена закрытия периода Close, но возможны и другие варианты (Open, High, Low, Close, Median Price, Typical Price и т. д.)

По умолчанию используют следующие настройки MACD:

В MetaTrader 5 представлены обе версии, но имеют разные имена — MACD и OsMA. Нужно помнить, что MACD в терминале это — не что иное как линейный MACD, а MACD-гистограмма — это OsMA.

  

Рис.5

Мы рассмотрим оба варианта.

Он (MACD MetaTrader 5) позиционируется как трендовый? и по этой причине может показаться, что классическое расхождение должно максимально точно отражать окончание того самого тренда. На самом деле не все так просто. Это вытекает не только из расхождений во мнениях о правилах интерпретации его показаний при выявлении дивергенции, но и разнообразия подвидов самого паттерна. В первой части я был категоричен, говоря о том, что пересечение нулевой линии однозначно значит окончание общей тенденции. Это не совсем верно. Существует и другое мнение, где незначительный выход за ноль дает более сильный сигнал к развороту.


Рис.6

А также где переход через «0»является обязательным. В частности, такого мнения придерживается упомянутый ранее Александр Элдер. И это не единственное и не самое глобальное из разногласий. Оба правила имеют право на существование, и каждый случай надо рассматривать в рамках конкретной рыночной ситуации.

Одна из существенных, на мой взгляд, проблем кроется в определение самого паттерна. Наш осциллятор строится по ценам закрытия свечи, так почему мы на ценовом графике ищем максимумы и минимумы?

  

Рис.7

  

Рис.8

  

Рис.9

Так как будет правильно? Что важнее — цена или показания индикатора? Еще к одному недостатку данного индикатора можно отнести длинный период расчета 26-12, что делает его непригодным для выявления незначительных ценовых движений. Классический вариант определения дивергенции подразумевает нахождение пары фракталов в показаниях индикатора и сравнение их с движением цены. Но при незначительных движениях фрактал не формируется. Для большей наглядности усовершенствуем стандартную версию. Раскрасим бары в разные цвета, в зависимости от направления движения. Сделать это не сложно. Для этого немного изменим стандартный код. В строке

#property indicator_buffers 4

4 на 5

#property indicator_buffers 5

строка

#property indicator_type1   DRAW_HISTOGRAM

примет вид

#property indicator_type1   DRAW_COLOR_HISTOGRAM

и

#property indicator_color1  Silver

соответственно

#property indicator_color1  Green,Red,Gold

К переменным добавится еще один буфер

double                   Color_buff[];

и теперь блок инициализации примет вид

   SetIndexBuffer(0,ExtMacdBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,Color_buff,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2,ExtSignalBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,ExtFastMaBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,ExtSlowMaBuffer,INDICATOR_CALCULATIONS);

Здесь 

   SetIndexBuffer(1,Color_buff,INDICATOR_COLOR_INDEX);

нельзя просто вписать последним, он должен быть с индексом «1» иначе работать не будет.

Теперь для выявления фрактала нам необходимо минимум 3 свечи, поэтомув блок, где задается количество расчетных баров, надо внести изменения в ту его часть, где задается значение для первого расчета.

if(prev_calculated==0)
      limit=2;
   else limit=prev_calculated-1;

В основном блоке добавим пару строк

//--- calculate MACD
   for(i=limit;i<rates_total && !IsStopped();i++)
     {
      ExtMacdBuffer[i]=ExtFastMaBuffer[i]-ExtSlowMaBuffer[i];
      //--- calculate Color Macd
      if(ExtMacdBuffer[i]>ExtMacdBuffer[i-1])
         Color_buff[i]=0.0; // set color Green
      else
         Color_buff[i]=1.0; // set color Red
     }
//---

И последнее, что нам надо сделать, это добавить блок, в котором мы будем определять экстремум MACD. Чтобы исключить перерисовку мы будем это делать после закрытия текущего бара. Для этого расчет будем вести со сдвигом на один бар.

for(i=limit;i<rates_total-1 && !IsStopped();i++)
     {
      if((ExtMacdBuffer[i-1]<0 && ExtMacdBuffer[i]>ExtMacdBuffer[i-1] && ExtMacdBuffer[i-1]<ExtMacdBuffer[i-2]) || 
         (ExtMacdBuffer[i-1]>0 && ExtMacdBuffer[i]<ExtMacdBuffer[i-1] && ExtMacdBuffer[i-1]>ExtMacdBuffer[i-2]))
         Color_buff[i-1]=2.0; // set color Gold
     }

Этот вариант подразумевает, что когда линия MACD выше — нуля мы выявляем только UP-фракталы, а когда ниже нуля только DN. Это неверно. В дальнейшем мы будем использовать вариант, где тип фрактала (UP или DN) не будет зависеть от положения основной линии индикатора относительно нуля.

Мы видим, что некоторые моменты, когда паттерн существует, автоматизировать если не невозможно, то достаточно сложно, и только визуальное наблюдение дает положительный результат.

  

Рис.10

Попытка компенсировать этот недостаток была реализована в классе Expert/Signal/SignalMACD. В справочнике это звучит так:


 Рис.11

И опять же, описание “первая анализируемая впадина осциллятора мельче предыдущей, а соответствующая ей впадина цены глубже предыдущей”  возвращает нас к вопросу “Что первично — Яйцо или Курица”? Поведение цены или показания индикатора? Как может быть, что показания индикатора, которые складываются из значений цены важнее самого ценового ряда? Да и конкретики никакой. Сколько баров брать в расчет — три, пять (как на рисунке) или на протяжении всей истории? Данный метод можно отнести к нестандартным, но его реализация в классическом варианте файла имеет больше недостатков, чем достоинств. Нет, полностью отвергать его не надо. Есть случаи когда он единственный может справится с поставленной задачей.

Для автоматизации, как один из вариантов, можно рассматривать одновременное использование MACD+ OsMA. Индикатор OsMA мы доработали аналогично MACD.


Рис.12

Как нам уже известно, OsMA — это MACD с той лишь разницей, что в виде гистограммы отображается разность между сигнальной и основной линиями MACD.  OsMA обладает большей чувствительностью, чем MACD, но и ее не всегда достаточно, и пропускаются сигналы или обратный процесс, когда ее в избытке и требуется дополнительное подтверждение.

  

Рис.13

Используя подобный тандем, встает вопрос — какой из индикаторов считать ведущим, а какой ведомым, то есть дивергенция на каком из них считается неотъемлемой частью формирования сигнала, а на каком необязательным условием. 

Также лично я считаю, что возможность подбора параметров индикатора  — тоже недостаток. Если период расчета RSI влияет только на амплитуду линии, то в MACD, OsMA, Stochastic серьезно меняет ее вид. Кто-то скажет “ рыночные условия меняются и данная возможность необходима, и сам индикатор был создан для фондового рынка и его параметры были подобраны для периода в один час”, но я возражу, что подобная возможность — это не адаптация, а подгонка желаемого под действительность.

Конечно, подбор параметров под конкретный инструмент и период графика на начальном этапе, возможно, потребуются, но если индикатор в дальнейшем перестал работать, то лучше вообще отказаться от его “услуг”. Но это сугубо мое личное мнение. Отсутствие возможности “подгонки” и стал одним из критериев выбора индикатора АС (Accelerator/Decelerator) для первой части материала. И этот индикатор не одинок. При этом никто не оспаривает их достоинств. Все правила, описанные ранее для него, справедливы и для всех других. Все вышесказанное было только в отношении классической дивергенции, но это справедливо и для правил построения обратной/скрытой. Как мы видим, не все так просто и однозначно в том, что мы знали о ней и принимали как должное. И вообще, возможно ли использование данного инструмента как качественный сигнал в том виде, что мы привыкли?

Не будем забегать вперед и рассмотрим особенности работы с другими индикаторами, которые как считается, являются классическими для решения поставленной задачи.

Stoсhastiс

Stoсhastiс Oscillator – индикатор теханализа измеряет импульсы цены в процентах. “Фактически, индикатор демонстрирует расхождение цены закрытия текущего периода относительно цен предыдущих периодов в рамках заданного временного промежутка”. Создан Джорджем Лайном (George Lane) в марте 2007 года.

Индикатор строится из двух линий:

где:

В определении опять звучит слово "расхождение". Если с MACD хоть как-то все понятно, то с нормированными осцилляторами, к которым он относится, еще сложнее. Само понятие “нормированный осциллятор” можно определить как изменяющий свои показания в жестких рамках. В нашем случае это от 0 до 100. Данная особенность вносит свои коррективы. На самой шкале показаний выделены три зоны. Это зоны перекупленности (80%), перепроданности (20%) и основного движения. Особенности расчета создают условия, при которых линия индикатора может долгое время как не покидать крайние зоны, так и не заходить в них.


Рис.14

Может показаться, что возможность использовать два различных ценовых ряда снимает вопросы, возникшие с MACD о том, какой использовать. Здесь возникает другая проблема. Мы видим из рис.14, что стохастик, построенный по Close, чаще занимает крайние положения «100 - 0», чем построенный по High/Low. Это связанно с формулой расчета самого индикатора. Также мы наблюдаем обилие пиков и впадин.


Рис.15 

Какого-либо четкого правила для данных случаев мы не имеем, и, как следствие, такие дивергенции, как между точками 100-100 и 92,31-92, 22 , сложно поддаются автоматизации. В типовом варианте расчета используются два ближайших фрактала. В данном случае это далеко не фракталы, ну и конечно, они далеко не ближайшие. И вот здесь появляется то самое знаменитое  «НО», то есть “В КАЖДОМ ПРАВИЛЕ ЕСТЬ ИСКЛЮЧЕНИЕ”. В нашем случае мы можем “недостаток” превратить в достоинство. Изменяя настройки пропорционально расчетному периоду, мы можем получить на графике М5 показания с графика М15.


Рис.16

Достоинство данного варианта заключается в том, что мы легко можем автоматизировать распознание дивергенции на глобальных (протяженных) участках рынка и получаем ранний сигнал на вход без задержки, связанной с необходимостью ожидания закрытия свечи старшего TF. На рис.16-17 эти участки определены красными линиями. В ряде случаев это может иметь решающее значение.


Рис.17

Из рисунка выше хорошо видно, что если бы мы вошли по показаниям MTF индикатора, то наша сделка ушла бы в убыток, а альтернативный вариант позволил бы заработать. Подобный подход справедлив и для MACD.


Рис.18

Такое решение при кажущемся сокращении количества сигналов, что опровергает правая часть рис.18, позволяет нам не только значительно повысить вероятность совершения прибыльной сделки, но и существенно поднять доходность. И здесь мы рассмотрели вариант М5-М15, а если это будет М5-Н1?


Рис.19

Применение быстрого и медленного стохастика решает только часть проблем. При создании  советников на таких принципах опять же возникает тот же вопрос, что и при использовании быстрого и медленного MACD (MACD+OsMA). Как расставлять приоритеты? И это не решает основной проблемы, как отфильтровать обилие переломов на линии стохастика при создании индикатора дивергенции. Мы не можем позволить себе перебирать все переломы линии в наших поисках. Это создаст массу “шума” и мы вынуждены ограничиваться максимум двумя, в редких случаях тремя, последовательностями.

Более глобально к вопросу фильтрации сигналов мы вернемся ниже, а сейчас сфокусируем свое внимание на правилах, соблюдение которых (не будем категоричны), желательно при поиски дивергенции. Почему мы не ставим однозначное «НЕТ» также станет ясно немного позже.

1) Логически мы понимаем, что прежде чем мы получим расхождение (схождение), цена должна достигнуть критического значения, соответственно — линия индикатора тоже. В нашем случае войти в зону перекупленности/перепроданности. А вот когда рынок обновит максимум/минимум — это условие для индикатора необязательно. То есть в нашем случае вторая точка (слева) от текущего бара, при поиске классического расхождения должна находится в этой зоне. Для скрытой (обратной) дивергенции наоборот первая точка должна быть на критическом уровне.


Рис.20

2) При поиске сигнала (вручную или при создании алгоритма) не надо пытаться выдать желаемое за действительное. Ищем его на ближайших экстремумах, используя последовательности исключающие случаи рис.20 и не более трех.

Рис.21

Если даже кажется, что рис.15 соответствует правилу «1», где левая вершина в зоне перекупленности, то присутствие более трех точек на линии индикатора его отменяет.

 

RSI 

Это еще один из индикаторов, который можно отнести к классике жанра. Но как вы уже поняли, мы с вами двигаемся в сторону повышения уровня сложности задачи.

RSI (Relative Strength Index ) — индекс относительной силы. Уайлдер Дж. Уэллес (J. Welles Wilder Jr. ) представил его в июне 1978.

RSI=100-100/(1+U/D)

где: 

Справедливости ради надо сказать, что данная формула это то, что мы имеем, а вот оригинальная выглядела иначе:

Он тоже является нормированным в приделах «0-100», но в отличие от Stoсhastiс, как мы видим из формулы, уже нет возможности сглаживания линии. Это многократно все затрудняет. Связанная с этим “избыточная ” чувствительность создает много переломов. Из рисунка ниже хорошо видно, что он сохраняет более или менее прямолинейное движении только при последовательном однонаправленном движении цены. В остальных случаях линия индикатора напоминает пилу.

  

Рис.22

Как следствие, в нем еще более остро стоит вопрос фильтрации показаний индикатора. Сейчас предлагаю рассмотреть один из вариантов решения данной проблемы.

Перед нами уже стоял вопрос о первичности ценового ряда или показаний индикатора. В данном случае нам его никак не обойти. Для анализа поведения цены инструментов, которые могут нам помочь, не так много. Это МА во всем своем разнообразии, Fractals и ZigZag.

Fractals (Билла Вильямса)

В стандартном варианте заложен алгоритм фрактала из пяти баров. Все же это не решает вопрос фильтрации, а иногда вносит даже “шум” и неразбериху в общую картину из-за несовпадения в показаниях с основным индикатором.


Рис.23

Он так же, как и RSI на флетовых участках, дает массу сигналов, которые, между прочим, нам и надо отфильтровывать. Еще один недостаток  это запаздывание в формировании структуры из пяти баров. Это как минимум на свечу, что в нашем случае совсем нежелательно.

МА — прекрасный образец сглаживающего инструмента. Но как уже было сказано выше, имеет массу интерпретаций. Начиная от вариантов сглаживания SMA (простое усреднение), EMA (экспоненциальное усреднение), SMMA (сглаженное усреднение), LWMA(линейно-взвешенное усреднение), цены Close, Open, High, low, Median (Медианная цена, (high+low)/2), Typical (типичная цена, (high+low+close)/3), Weighted (средневзвешенная цена, (high+low+close+close)/4), есть еще и период расчета, который можно варьировать от «1» до «∞». И это всё для классического варианта MA (Moving Average). А есть еще и Double Exponential Moving Average,  Double Exponential Moving Average. И это только те, которые входят в стандартный комплект MetaTrader 5. Столь глобальную задачу "проанализировать все возможные варианты и при этом, меняя алгоритм поиска дивергенции и настройки базового индикатора, чтобы выбрать оптимальный вариант" мы не ставим. 

ZigZag  — “Индикатор для определения ценовых экстремумов колебаний котировок с амплитудой и периодом, настроенных по условию отклонения фильтров”.

Судя из определения это то, что нам нужно. И здесь опять те же “грабли”. RSI строится по Close, а ZZ по High/Low.


Рис.24

Частично компенсировать этот недостаток возможно, построив RSI по  Median (Медианная цена — (high+low)/2).


Рис.25

Но из рис.24 видно, что отклонение в положении фракталов на индикаторе и цене не превышает двух баров и, значит, легко компенсируется программным путем. Небольшое отступление: в нашем случае нас интересует только форма сигнала, а никак не значение его показаний. То есть базовый индикатор используется только для выявления расхождений и не используется для частных сигналов торговли по RSI.

Отличие в принципах построения и расчета и то, что никто из авторов точно не создавал свой шедевр применительно к данному тандему, дает нам право сделать исключение из правил и “поиграть” с настройками. Зная, что период расчета RSI не влияет на форму сигнала, а только на его амплитуду и настройки ZigZag также не изменят положение экстремумов, мы подобными “играми” можем добиться поразительного результата.

Если следовать правилу, которое мы применили к Stoсhastiс “прежде чем сформировать паттерн дивергенция, показания индикатора должны достичь критических значений перекупленности/перепроданности”, в нашем случае зон выше «30» и ниже «70», и изменяя настройки ZZ  чтобы получать как краткосрочные сигналы, так и их глобальные значения. При всем при этом эти параметры взаимно компенсирующиеся, что позволяет в комбинации 2+1 (два фильтра + один базовый) отслеживать всю картину. Количество фильтров, конечно, не ограничивается двумя, их может быть и три и даже больше. В дальнейшем, когда мы рассмотрим тему целевых уровней, будет понятно, что разбив сигналы на группы, возможно брать большую часть движения рынка, следуя конкретным сигналам.


Рис.26

Пусть вас не смущает в данном примере (рис.26), что в первом сигнале RSI не зашел в зону перепроданности. Мы помним, что достаточно изменить период расчета тем самым увеличить амплитуду и он туда попадет, что будет соответствовать нашим требованиям.

CCI

Относится к классу осцилляторов (Commodity Channel Index, Индекс торгового канала) был разработан в 1980 году Дональдом Ламбертом (Donald Lambert).  

CCIn=(1/0.015)*((TypicalPrise-SMA)/MedianDeviation)

К достоинствам данного индикатора можно отнести импульсный характер работы. То есть по нему можно определить не только перекупленности/перепроданности рынка, но и начальный импульс на рынке. Это достоинство, для нашего случая, можно считать недостатком. Несмотря на то, что в классическом варианте он рассчитывается по Typical Prise, все равно форма линии пилообразная, как и у RSI. Поэтому все, что было сказано выше для RSI, подходит и к нему. То есть требуется фильтрация ценового ряда не только по типу (High,Low,Close, и т. д.) но и выявлению экстремумов цены.


Рис.27

Подобное его поведение также потребует внесения изменений в алгоритм в случае использования более одного “перелома” линии индикатора в поиске расхождений.


Рис.28

Если на других индикаторах данная ситуация возникает достаточно редко, то CCI — неприятное исключение.

Характер поведения этого индикатора делает его одним из лучших для работы по принципу, описанному в первой статье данной серии. Если коротко, то он звучит так — “Линии, продленные от последних обратных дивергенций (последняя Bullish и Bearish), построенные на графике цены, становятся линиями поддержки/сопротивления для цены (рис.29), а в классических индикаторах в окне осциллятора —  для его линии (рис.30)”.


Рис.29


Рис.30

Momentum 

Momentum — темп изменения цены. Другое имя — RoC (Rate of Change). Отличие в том, что в RoC линией баланса является «0», а в Momentum «100». Индикатор был описан Джономом Мэрфи в книге «Технический анализ фьючерсных рынков».

Momentum=Pn-Pn-1

где Momentumn — момент за n периодов на момент t (текущий момент)

Подобный вариант не совсем удобен, так как сообщает данные в цене актива. Поэтому формула была дополнена.

Сейчас штатный Momentum и есть RoC, а вот RoC — это обычный Momentum-100. Принцип расчета индикатора в оценке импульсных движений. По этой причине те же проблемы, что у CCI и RSI — пилообразная линия. Но здесь подобное движение порождает еще больше сигналов.


Рис.31

Что делать с этим изобилием не понятно. Также из рис.31 видно, что возможна некорректная работа автоматики. По информации, которую мне удалось найти по этому индикатору, он нигде не позиционировался применительно к выявлению дивергенции. Существует мнение, что он, в зависимости от периода расчета, способен отвечать требованиям как краткосрочной торговли (period 6-14) , так и при периодах свыше «20» становится практически трендовым, что позволяет с его помощью достаточно четко выявлять окончание того самого тренда. Если предположение, что тренд состоит из трех последовательных импульсов, считать верным, (Волновая теория рынка) и здесь ключевым словом будет “импульс», тогда принципы, заложенные в Momentum, действительно могут нам помочь выявить его окончание. Возможно, надо провести более глобальный анализ его работы. 

ADX

Идея “Индекс направленного движения DMI (directional movement index )” была предложена Уэллсом Уайлдером в 1978 году в книге «Новые концепции в технических торговых системах» (New Concepts in Technical Trading Systems). Она в дальнейшем и легла в основу данного инструмента.

Индекс ADX (индекс среднего направленного движения) рассчитывается на основе данных двух других, положительной (+DI) и отрицательной направленности (− DI) с учетом   истинного торгового диапазона (ATR).

ADX=(MAn(+DI--DI)/(+DI+-DI))*100

где: 

Формула представлена в упрощенном виде. Более подробно с ней можно ознакомиться здесь.

Взглянув на сам индикатор (множество линий) и понимая принцип передаваемой им информации (основная линия ADX не указывает на направление тренда, а сообщает об активности рынка), может показаться, что он нам не подходит.

  

Рис.32

На самом деле это не так. Подобное разнообразие позволяет нам использовать его несколькими способами. Первый из них заключается в том, чтобы определить расхождение между направлением движения цены и активностью на рынке. То есть если цена продолжает снижаться (повышаться), а индекс ADX снижается, это и будет тем самым расхождением.


Рис.33

Ранее нами уже было предложено добавить этот метод в наш арсенал. Сложность этого варианта заключается в том, как понять направление движения цены. Решением может стать первичная оценка движения самого ценового ряда. То есть последовательность из понижающихся впадин или растущих пиков. Проблема может возникнуть, когда ближайший пик ниже предыдущего, а ближайшая впадина выше предыдущей или наоборот, так называемые "Внутренний " и "Внешний" бар (термин из Price Action).

  

Рис.34

Второй способ — это использование самих линий +DI и -DI. Не забываем, что пик –DI всегда соответствует впадине на графике цены. Здесь на восходящем тренде (+DI выше -DI) по линии +DI мы исследуем пики для нахождения классических медвежьих расхождений, а по -DI пики для поиска обратных бычьих расхождений. На нисходящем рынке (+DI ниже -DI) мы рассматриваем на -DI пики для поиска бычьих классических и по пикам +DI медвежьих обратных расхождений.


Рис.35

Третий, и по моему мнению наиболее эффективный, это применение в совокупности обоих способов. Подобный вариант решает массу проблем. Он позволяет нам видеть расхождение по линии ADX без запаздывания в ожидании разворота. Фильтровать сигналы по типу в зависимости от общей тенденции без применения дополнительных инструментов.

На этом хотелось бы закончить то, что касается классических осцилляторов. Почему сюда не вошли такие как АО, АС, TRIX, WPR и так далее и им подобные?

Инструменты для анализа отбирались по принципу оригинальности формулы расчета.

WPR(10) — это тот же Stochastic(10.1.1 (Low/High)) только с перевернутой шкалой.  Stochastic работает в диапазоне 0-100, а WPR в 100-0.


Рис.36

Awesome Oscillator (AO) — MACD(5.35.1 Median) с той лишь разницей, что AO сглаживается по SMA (простое усреднение), а в MACD используется EMA(экспоненциальное усреднение), по этой причине последний немного “шустрее”. Из рисунка ниже видно, что кардинального изменения в форму сигнала это не вносит.


Рис.37

Accelerator ни что иное как OsMA (5.34.5  Median) с теме же отличиями, что и у MACD c АО.


Рис.38

TRIX тоже в основе своей состоит из скользящих средних, и подбором параметров MACD можно добиться того же результата.

  

Рис.39

 

Объемы 

Мы видим огромное разнообразие стратегий с применением тех анализа. Отдельно можно выделить группу с применением объемов. Она очень незначительна, но все же имеет место быть. По моему мнению, объемы на форекс несправедливо обделены. И даже то, что их реальных на этом рынке мы не получаем (только тиковые), никаким образом не умаляет задумок авторов. Этой теме обязательно будет посвящен отдельный материал, а сейчас рассмотрим то, что касается дивергенции.

Список индикаторов, использующих в своем алгоритме объем и входящих в обязательный комплект терминала MetaTrader 5, весьма ограничен. Это Accumulation/Distribution (Марк Чайкин), Money Flow Index (схожесть формул расчета дает право назвать его RSI объема), On Balance Volume (Джозефом Гранвиллем), Market Facilitation Index (Билл Вильямс) и сам Volume. А также почему-то выбившейся из этой группы и попавший в раздел «Осцилляторы» Force Index (Александр Элдер). Подобная скудность торговых инструментов порождает предвзятое отношение к ним. По этой причине в материалах, касающихся вопроса дивергенции объемов, мы чаще всего наблюдаем вот такую картину

  

Рис.40

Из рисунка видно, что подобный способ определения расхождения хорош при анализе рынка на исторических данных и сложен при создании инструментов автоматизации. Недостатков у него много. Это различие в объемах торгов в зависимости от сессии и вносимые этим искажения. Мы же понимаем, что на Азиатской они будут меньше, чем на Европейской и Американской. Также всплеском сопровождается не только начало тренда, но и закрытие сделок трейдерами, и этот объем может быть выше, чем при старте.

  

Рис.41

Подобными всплесками также сопровождают новостные движения.

  

Рис.42

Частично эту задачу можно решить, используя вместо стандартного Volume другие индикатора, в которых есть линия баланса. Это обычная SMA (простое усреднение) от объемов за определенный период. Это позволяет отфильтровать незначительные значения. К таким относится завоевавший популярность «BetterVolume».


Рис.43

Еще одним способом решения проблемы можно считать совмещение ценового ряда и индикатора Volume. Мы будем определять объем на тех свечах, где был сформирован новый High (Low) и сравнивать их. Для наглядности внесем некоторые изменения в классический вариант в соответствии с нашим алгоритмом.

Естественно гистограмма теперь будет иметь не два цвета, а пять.

#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  Green,Red,Blue,Magenta,Gray
  1. Green - если low[i]>low[i-1] и high[i]>high[i-1].
  2. Red     - если low[i]<low[i-1] и high[i]<high[i-1].
  3. Blue   - это внешний up bar
  4. Magenta - это внешний dn bar
  5. Gray - не отвечает ни одному из выше перечисленных 

Основной блок расчета от стандартного "Volumes" не отличается. Только в функцию "CalculateVolume" добавлена раскраска столбиков гистограммы

void CalculateVolume(const int nPosition,
                     const int nRatesCount,
                     const long &SrcBuffer[],
                     const double &h[],
                     const double &l[],
                     const double &o[],
                     const double &c[])
  {
   ExtVolumesBuffer[0]=(double)SrcBuffer[0];
   ExtColorsBuffer[0]=0.0;
//---
   for(int i=nPosition;i<nRatesCount && !IsStopped();i++)
     {
      //--- calculate indicator color
      ExtVolumesBuffer[i]=(double)SrcBuffer[i];
      ExtColorsBuffer[i]=4.0;
      //--- тренд вверх UP бар----
      if(h[i]>h[i-1] && l[i]>l[i-1]&& o[i]<c[i])ExtColorsBuffer[i]=0.0;
      //--- тренд вверх DN бар ----
      if(h[i]>h[i-1] && l[i]>l[i-1]&& o[i]>c[i])ExtColorsBuffer[i]=3.0;
      //--- тренд вниз DN бар ----
      if(h[i]<h[i-1] && l[i]<l[i-1]&& o[i]>c[i])ExtColorsBuffer[i]=1.0;
      //--- тренд вниз UP бар ----
      if(h[i]<h[i-1] && l[i]<l[i-1]&& o[i]<c[i])ExtColorsBuffer[i]=2.0;
      //--- внешний UP бар ----
      if(h[i]>h[i-1] && l[i]<l[i-1] && o[i]<c[i])ExtColorsBuffer[i]=2.0;
      //--- внешний DN бар ----
      if(h[i]>h[i-1] && l[i]<l[i-1] && o[i]>c[i])ExtColorsBuffer[i]=3.0;
      //--- внутренний бар ----
      if(h[i]<h[i-1] && l[i]>l[i-1])ExtColorsBuffer[i]=4.0;
     }
//---
  }
//+------------------------------------------------------------------+


Рис.44 

Данный вариант хоть и не является идеальным, все же упрощает анализ. Можно предложить еще несколько вариантов вплоть до глобального изменения самого принципа расчетов, но надо помнить, что “всё новое — это хорошо забытое старое”. До нас уже кто-то рассматривал подобные идеи, и если они не получили широкого распространения, то и нам они ни к чему. И я сильно сомневаюсь, что все это нам поможет в автоматизации поиска дивергенции с применением данного индикатора. Мы сконцентрируем свое внимание на том, что “пошло в массы”.

Money Flow Index 

Как уже говорилось выше, его формула расчета очень схожа с RSI.

Prise=(high+low+close)/3

MF=Prise*Volume

MR=positiveMF/negativeMF

MFI=100-100/(1+MR)

Мое личное мнение, что он больше подходит для выявления зон перекупленности перепроданности чем RSI, так как само понятие перекупленности/перепроданности подразумевает не то, насколько изменилась цена за расчетный период, а сколько “игроков” участвовало в данном процессе, что и делает MFI. Как следствие, он лучше отражает причинно-следственную связь. Ему присущи те же недостатки, что и его “брату”.


Рис.45

  On Balance Volume

(Джозефом Гранвиллем)

Если текущая цена закрытия выше предыдущей:

OBVn=OBVn-1-Volumen

Если текущая цена закрытия ниже предыдущей:

OBVn=OBVn-1-Volumen

Если текущая цена закрытия равна предыдущей:

OBVn=OBVn-1

Где:

Обратившись к справочникам, мы о нем получим достаточно скудную информацию. Но в ней есть ключевая фраза “изменения OBV опережают ценовые” То есть в нем есть расхождение между ценовым движением и объемами, инвестированными в данное движение, что дает нам полное право его использовать.


Рис.46

На рисунке выше мы одно из расхождений отметили вопросительным знаком. Да действительно движение рынка было незначительным и здесь основной фактор то, что это был переход через сутки и от Азиатского рынка ожидать ощутимой волатильности неразумно. В дальнейшем, когда мы будем рассматривать целевые уровни, будет понятно, что она отработала свое и поэтому вполне допустима.

Force Index

(Александр Элдер).

Force Index=Volume*(CLOSEn-CLOSEn-1)

Формула оригинала отличается от той, которая реализована в терминале.

Force Index=Volume*(MAn-MAn-1)

Причина этого мне не совсем понятна, но существенного изменения в форму сигнала это не вносит, что вполне допустимо при решении нашей задачи.


Рис.47 

Аспекты остальных сигналов, подаваемых данным инструментом, и их различия выходят за рамки данного материала.

Как мы уже говорили,  этот индикатор был отнесен к классу осцилляторов, хотя Александр Элдер в упомянутой выше книге пишет “Я считаю его лучшим инструментом для измерения объема на рынках”

Он же рассматривает его для поиска дивергенции.


Рис.48

Вход и цели

В классическом варианте его придерживаются многие авторы, вход в сделку звучит так:

После того как расхождение было выявлено, мы размещаем STOP приказ на покупку на максимуме свечи, на которой закончилось формирование паттерна для Бычьей дивергенции или STOP приказ на продажу на минимум свечи для Медвежьей.


Рис.49

Этот вариант можно считать оптимальным и позволяющим взять максимум возможной прибыли. Для данного способа входа в сделку первой целью можно рекомендовать границы конверта “Envelopes (26)” (отклонение подбирается в зависимости от волатильности рынка).


Рис.50

Либо это может быть граница равноудаленного канала построенного по точкам формирования дивергенции, где третьей точкой будет максимум(минимум) между первой и второй.


Рис.51

Stop Loss ставим по классике жанра под минимум для Buy сделок и выше максимума для Sell сделок. Этот подход, при кажущейся своей «идеальности», подходит к тем случаям, когда и наш паттерн тоже «идеальный» — то есть сформирован с учетом всех правил и дополнительно подтвержден. Также его можно использовать на больших временных интервалах, где за счет большей волатильности и возможности, опять же из за наличия времени, проанализировать дополнительно состояние рынка и выйти вовремя из сделки хоть и с небольшой, но прибылью.


Рис.52

Такой "TP" является плавающим и определить его до открытия сделки сложно. Также он будет меняться по истечению времени. Из недостатков — для коротких временных интервалов надо успеть проанализировать возможную рентабельность совершаемой сделки. Для этих случаев можно рекомендовать другой, более надежный вариант. Построим трендовою линию и входить будем только после ее пробития, что само по себе является сигналом для перелома тренда, а в нашем случае его подтверждением. В большинстве случаев он будет совпадать или почти совпадать с уровнем классического варианта, но при этом придаст нам большей уверенности.


Рис.53

Мы можем использовать правила из первой части с поправкой на правильность построения линий. Иногда эти линии созданные индикатором приходится скорректировать.

Для таких сделок целями выбираются уровни поддержки/сопротивления.


Рис.54

Также хотелось сказать несколько слов о двойных, тройных дивергенциях. Целью для них можно считать конец формирования первого сигнала (очень часто). Реже это фрактал между точками формирования первой дивергенции или ее начало.


Рис.55

Встает вопрос о целесообразности выставления стопов. Нет, я не учу плохому. Стиль торговли и правила манименеджмента каждый выбирает сам. Способ торговли вообще без стопов или при значительном их удалении можно рекомендовать только опытному трейдеру. Он должен быть уверен в правильности своих построений или индикаторе. Уметь скорректировать свои действия по ходу сделки или закрыть убыточную сделку вручную , не дожидаясь момента, когда ситуация выйдет из под контроля.

Создание торгового инструмента

Из содержания статьи не следует, что мы займемся банальной критикой уже имеющихся правил. Наша цель взглянуть на этот вопрос по-новому и возможно почерпнуть в этом рациональное зерно, которое мы можем использовать. Авторы, создающие торговые инструменты , вкладывают в него какую-то свою концепцию в желании получить результат. Индикатор делается под конкретный рынок и с целью облегчить задачу определения того или иного параметра. Иногда сам смысл, заложенный в нем, нам не совсем понятен. Или интерпретация показаний так и остается известна до конца только автору.

В дальнейшем трейдеры в своем порыве добиться положительного результата пытаются применить их для других условий и в процессе чего общий смысл теряется, как и возможная результативность. Все это похоже на желание, наверняка посещавшее, трейдеров хотя бы единожды тестировавших робота который уверенно “сливает” или получали подобный результат при его создании. А что если поменять направление сделок? Будет ли он столь же уверенно зарабатывать?

Наша цель схожа и тоже звучит как “А что если”. Часть результата подобного подхода уже было опубликовано в первой части. Сейчас нам предстоит реализовать его в другом аспекте. Мы возьмем инструмент, который при всех своих недостатках в одной из своих частей дает результат, повторить который другие не могут. Речь идет об индикаторе ADX. Его недостатки хорошо всем известны. Это сильное запаздывание из-за двойного сглаживания. Также направление движения основной, да и остальных линей тоже, не совпадает с направлением движения рынка. Из-за этого возникают сложности при интерпретации его самого. Автор закладывал мысль показать силу, а не направление.


Рис.56


Рис.57

По этой причине если с линией «DI+»  все в порядке, то линия «DI-», при кажущейся направленности, на самом деле перевернута с ног на голову. Здесь пики линии на самом деле являются впадинами ценового движения.


Рис.58

Причины, побудившие Дж. Уэллса Уайлдера в рамках «Параболической системы» создать подобный индикатор мне неизвестны, так как я только поверхностно знаком с его трудами. Логически могу предложит, что он создавался для рынка акций, где понятие торговли, в том виде, котором мы привыкли на Форекс, искажено. Акции чаще покупаются на длительный срок для получения дивидендов или капитализации.

Вот здесь и наступает наша очередь. Надо взять из него то лучшее, что в нем есть и использовать максимально эффективно. Лучшее — это то, что он прекрасно выявляет те самые пики и впадины с учетом рыночной тенденции (силы рынка) за счет разделения на положительную и отрицательную составляющие. Подобное решение также позволяет более детально понять, что происходит на рынке. Давление ли это покупателей на продавцов на падающем рынке и продавцов на покупателей на растущем, снижение общей активности из-за уменьшения желающих в этом участвовать или вообще просто трейдеры решили передохнуть, чтобы осмыслить происходящие. Но на этом мы не остановимся. Беглый взгляд на формулу дает нам понять, что из параболического движения основной линии индикатора мы с легкостью можем превратить его в привычный для нас вид осциллятора с балансным нулем. Для этого достаточно исключить приведение к абсолютному значению основной линии ( ADX), исключив из строки

         dTmp=100.0*MathAbs((ExtPDIBuffer[i]-ExtNDIBuffer[i])/dTmp);

функцию MathAbs.

Мы получим индикатор вот такого вида.


Рис.59


рис.60

Из рисунка выше хорошо видно, что наш ADX (назовем его ADX_Osc) очень неплохо справляется с задачей направленности рынка и существенно облегчает нам задачу поиска дивергенции в “глобальном” масштабе. Некоторая заторможенность главной линии, о которой мы говорили ранее, не исчезла. Этот недостаток с лихвой компенсируется за счёт “предварительных” сигналов разворота рынка. Их мы определяем по "DI-" и "DI+".


Рис.61

Те, кому непонятно почему так определено расхождение между «DI-» (красная линия) и ценой, пусть еще раз перечитают все, что касается индикатора ADX. На рисунке хорошо видно — начато давления покупателей на продавцов на нисходящем тренде, что и приводит в дальнейшем к консолидации, и даже вроде как есть подтверждение основной линией индикатора, но спешить нельзя. Требуется более серьезное основание для входа в BUY сделку. Из рис.60 видно, что наши сомнения были небезосновательны. Рынок продолжил свое движение вниз.

Из того, что нам может понадобиться, можно выделить “однонаправленное” движение линий «DI-» и «DI+». Однонаправленное не зря взято в кавычки. На самом деле цена вроде как одновременно и растет и падает. Мы понимаем, что такого не может быть. Это и есть то самое расхождение. Такие моменты возникают, когда появляется так называемый "внутренний бар".

Открываем букварь. Глава Price Action: “Внутренний бар (IB, inside bar) — это набор свечей, что расположены в диапазоне предыдущей свечи, у которой верхний минимум и нижний максимум больше, чем у свечи сразу за ней. На небольшом таймфрейме такой сетап выглядит, в основном, как треугольник. Внутренний бар указывает на неопределенность и консолидацию рынка. Он часто встречается на трендовом рынке, где указывает на продолжение тренда после пробоя материнской свечи. Встречаются на вершине дне рынка, основных уровнях поддержки-сопротивления и в боковых каналах.”

Наш случай не совсем корректен для данного определение. Как вы помните, мы определяем силу, а не направление. Поэтому оно будет звучать как-то так: “На текущем баре сила Быков меньше чем на предыдущем, а сила Медведей больше чем на предыдущем. Форма бара не имеет значение .


Рис.62

При всем при этом основной смысл в том, что бар служит сигналом к остановке или развороту рынка сохраняется. При оценке его “качества” мы будим учитывать направление (силу) основного тренда (линия ADX_Osc ). Если тренд развивается, значение линии ADX выше предыдущего для восходящего тренда и ниже для нисходящего — это просто консолидация (Stop Price). Если тренд слабеет, основная линия снижается во время восходящего и повышается во время снижающегося тренда (дивергенция), то мы можем ожидать разворот рынка. На этом и ограничимся в том, что нам будет необходимо для создания индикатора.

Это конечно не все, на что он способен. Но перед нами не стоит задача выжать из него максимум и сделать единственным для нашей стратегии в торговли.

Прежде чем продолжить, небольшое лирическое отступление. На заре своей “писательской карьеры” в попытке опубликовать свой первый труд, мне было отказано. Посоветовали просто создать свой блог. Только вот работа, прежде чем предать ее в публикацию, была проделана немалая. Статья содержала только выдержки, которые мне казались существенными, но это не снижало ее значимости, как мне казалось. Нет, просто тогда никто не объяснил, что статьей считается только тот материал, который содержит программный код. И все же это надолго отбило у меня охоту к ”бумагомарательству”. В дальнейшем я вернулся к мысли, что кое-чем поделиться стоит. И опять не так. Простое изложение сути раскрываемой темы, что существенно сокращала объем материала, не устраивало модераторов. Теперь решил писать все то, что привело меня к тому самому ИТОГО. Как вы, наверное, догадываетесь, и здесь не весь материал, который мог бы быть, и даже в таком варианте, надеюсь, что вы будете приятно удивлены, как будет краток сам результат. Прежде чем перейти к конечной стадии нашего обзора темы, вкратце о том, что побудило сделать его таким, как кому-то может показаться, совершенно не стоящим затраченного времени.

В предыдущем материале мы вкратце коснулись проблем, возникающих с индикаторами, основанных на графических построениях. Напомню, что подобные инструменты с трудом поддаются дальнейшему анализу из-за невозможности это проделать в режиме адаптации. Только визуальном, что очень затратно по времени. Сами сигналы от индикатора передать если не невозможно, то достаточно сложно, и это обязывает вводить его в программный код советника. Также возникают проблемы, связанные с правильностью построения тех самых линий, и, как следствие, ложных сигналов входа в рынок. Решить эту задачу можно, но это тема совсем другого плана.

Скорее не тема, а вопрос к создателям языка программирования MQL — почему нельзя создать графические объекты в виде библиотеки машинного кода, которыми они по существу и являются? В чем проблема сделать так, чтобы буфер, сведения из которого надо передать, (в виде построения или информации) мог относиться раздельно к основному окну графика и его под окну? Возможно, кто-то напишет материал на эту тему или мне надоест обходить ее стороной и я сделаю это сам. Опять отвлекся. Из всего вышесказанного подводим предварительный итог. Нами выбран, на мой взгляд, индикатор наиболее подходящий к теме нестандартного подхода и способный справиться с поставленной задачей. Путем анализа в нем определены моменты поведения, которые оптимальны для реализации и не будут перегружать экран. Полностью отказываться от графических построений в нашем индикаторе мы не будем, так как основной задачей все же стоит не автоматизация процесса торговли, а возможность его применения в ней. 

Давайте сразу определимся. Данный инструмент не будет являться конкретной законченной концепцией. Это «испытательный полигон» для дальнейшей работы. Каждый может, проанализировав его работу, определиться, что он хочет получить в конечном результате и соответственно его доработать. По этой причине мы реализуем «нестандартный подход» только для краткосрочной тенденции, а для глобальных сигналов оставляем классическое решение.  

Как уже говорилось ранее, основной код индикатора ADX остаётся без существенных изменений.  Несколько изменений, чтобы привести его к виду осциллятора, о которых говорилось ранее, все же необходимы. Из-за этого мы не можем просто вызвать ADX через Handle. 

#property indicator_separate_window
#property indicator_buffers 8
#property indicator_plots   3
#property indicator_type1   DRAW_LINE
#property indicator_color1  LightSeaGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
#property indicator_type2   DRAW_LINE
#property indicator_color2  Green
#property indicator_style2  STYLE_DOT
#property indicator_width2  1
#property indicator_type3   DRAW_LINE
#property indicator_color3  Red
#property indicator_style3  STYLE_DOT
#property indicator_width3  1
#property indicator_label1  "ADX"
#property indicator_label2  "+DI"
#property indicator_label3  "-DI"
//--- input parameters
input int InpPeriodADX=14; // Period
input int extremum=100; // Extremum (<1 Div= OFF)
input int Gep=4; // Point to Gep
input int Bars_Calculated=300;
//--- global variables
input bool   allLine=false;// All Line
int    ExtADXPeriod;
double PDI,NDI,pDI,nDI;
string short_name="";
int    wid=-1;
//---- buffers
double    ExtADXBuffer[];
double    ExtPDIBuffer[];
double    ExtNDIBuffer[];
double    ExtPDBuffer[];
double    ExtNDBuffer[];
double    ExtTmpBuffer[];
double    ExtUpBuffer[];
double    ExtDnBuffer[];

Некоторые входные параметры требуют пояснения.

input int extremum=100; // Extremum (<1 Div= OFF)

Это количество экстремумов линии индикатора, которые мы будем перебирать для поиска дивергенции. Минимальное число "1". Если меньше, то расчета производится не будет. В дальнейшем после определения оптимального количества лучше переместить этот параметр в глобальные.

input bool   allLine=false;// All Line

Данный параметр позволяет увидеть на экране линии всех дивергенций, выявленных в процессе работы индикатора и определенных параметром «extremum». Установлен специально для облегчения анализа работы индикатора и определения значения вышеупомянутого параметра.


Рис.63


Рис.64

input int Gep=4; // Point to Gep

Имеет эстетическое значение. Точки с разбросом в значении, определенные этим параметром, будут выстраиваться в одну линию. Для себя я определил его как полтора-два спреда. На отступ не влияет, и если есть такая необходимость, его значение надо указать дополнительно. О каких точках идет речь будет понятно далее. Для сокращения функции  OnDeinit мы будем использовать команду удаления всех с данным префиксом, которым в нашем случае является имя индикатора. В терминале MetaTrader 5 замечено некоторое "подвисание" при удалении с основного экрана большого числа объектов. Чтобы этого избежать, добавим принудительную перерисовку экрана.

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0,short_name);
   ChartRedraw(0);
  }
//+------------------------------------------------------------------+

Также  было замечено, что если терминал был отключен  длительное время, графические объекты в подокне сохраняют привязку не по координатам цена/время, а в пикселях своего последнего положения. Поэтому в блоке, где определяется количество баров для первого расчета, была добавлена команда их удаления. Возможно, кто-то знает более оригинальное решение или причину этого, но я решил этот вопрос так.

   if(prev_calculated>1) start=prev_calculated-1;
   else
     {
      OnDeinit(9);
      start=1;
      ExtPDIBuffer[0]=0.0;
      ExtNDIBuffer[0]=0.0;
      ExtADXBuffer[0]=0.0;
     }

В основную функцию расчета индикатора также добавлен блок определения "однонаправленного" движения линий "DI+" и "DI-".

//+------------------------------------------------------------------+
//|           Fast divergence calculation                            |
//+------------------------------------------------------------------+
   int bar=start;
   if(prev_calculated<2) bar=start+2;
   if(Bars_Calculated>0)bar=fmax(rates_total-Bars_Calculated,start);
//---
   for(int i=bar;i<rates_total-1 && !IsStopped();i++)
     {
      ExtUpBuffer[i-1]=EMPTY_VALUE;
      ExtDnBuffer[i-1]=EMPTY_VALUE;
      //---
      color clrUp=clrLime;
      color clrDn=clrDarkViolet;
      //---
      if((ExtPDIBuffer[i-1]<ExtPDIBuffer[i-2] && ExtNDIBuffer[i-1]<ExtNDIBuffer[i-2]) || 
         (ExtPDIBuffer[i-1]>ExtPDIBuffer[i-2] && ExtNDIBuffer[i-1]>ExtNDIBuffer[i-2]))
        {
         if(ExtPDIBuffer[i-1]>ExtNDIBuffer[i-1])
           {
            if(ExtADXBuffer[i-1]>ExtADXBuffer[i-2])
               ExtUpBuffer[i-1]=high[i-1];
            else
              {
               ExtUpBuffer[i-1]=EMPTY_VALUE;
               ExtDnBuffer[i-1]=low[i-1];
               clrDn=clrGold;
              }

            //---
            if(MathAbs(ExtUpBuffer[i-1]-ExtUpBuffer[i-2])<Gep*_Point)
               ExtUpBuffer[i-1]=ExtUpBuffer[i-2];
            if(MathAbs(ExtDnBuffer[i-1]-ExtDnBuffer[i-2])<Gep*_Point)
               ExtDnBuffer[i-1]=ExtDnBuffer[i-2];
            //---
           }
         if(ExtPDIBuffer[i-1]<ExtNDIBuffer[i-1])
           {
            if(ExtADXBuffer[i-1]<ExtADXBuffer[i-2])
               ExtDnBuffer[i-1]=low[i-1];
            else
              {
               ExtDnBuffer[i-1]=EMPTY_VALUE;
               ExtUpBuffer[i-1]=high[i-1];
               clrUp=clrBlue;
              }

            //---
            if(MathAbs(ExtDnBuffer[i-1]-ExtDnBuffer[i-2])<Gep*_Point)
               ExtDnBuffer[i-1]=ExtDnBuffer[i-2];
            if(MathAbs(ExtUpBuffer[i-1]-ExtUpBuffer[i-2])<Gep*_Point)
               ExtUpBuffer[i-1]=ExtUpBuffer[i-2];
            //---
           }
        }
      //---
      if(ExtUpBuffer[i-1]==EMPTY_VALUE)
         ExtUpBuffer[i-1]=ExtUpBuffer[i-2];
      if(ExtDnBuffer[i-1]==EMPTY_VALUE)
         ExtDnBuffer[i-1]=ExtDnBuffer[i-2];
      //---
      if(ExtUpBuffer[i-1]!=EMPTY_VALUE)
        {
         ArrowCreate(short_name+(string)time[i]+(string)Lime,time[i],ExtUpBuffer[i-1],ANCHOR_BOTTOM,clrUp);
         if(ExtUpBuffer[i-1]!=ExtUpBuffer[i-2])
            ArrowCreate(short_name+(string)time[i-1]+(string)Lime,time[i-1],ExtUpBuffer[i-1],ANCHOR_BOTTOM,clrUp);
        }
      else
         ArrowCreate(short_name+(string)time[i]+(string)Lime,time[i],ExtUpBuffer[i-2],ANCHOR_BOTTOM,clrUp);
      //---
      if(ExtDnBuffer[i-1]!=EMPTY_VALUE)
        {
         ArrowCreate(short_name+(string)time[i]+(string)Red,time[i],ExtDnBuffer[i-1],ANCHOR_TOP,clrDn);
         if(ExtDnBuffer[i-1]!=ExtDnBuffer[i-2])
            ArrowCreate(short_name+(string)time[i-1]+(string)Red,time[i-1],ExtDnBuffer[i-1],ANCHOR_TOP,clrDn);
        }
      else
         ArrowCreate(short_name+(string)time[i]+(string)Red,time[i],ExtDnBuffer[i-2],ANCHOR_TOP,clrDn);
     }

и модуль запуска функций расчета "глобальной" дивергенции.

//+----------- Finding a discrepancy Выявляем расхождения ----------+
   bar=start;
   if(bar>rates_total-2)bar=rates_total-2;
   if(Bars_Calculated>0)bar=fmax(rates_total-Bars_Calculated,bar);
   for(int i=bar;i<rates_total-2 && !IsStopped() && extremum>0;i++)
     {
      UP(i,ExtADXBuffer,high,time);
      DN(i,ExtADXBuffer,low,time);
     }

Индикатор из первой части был переделан с MQL4. Эта версия изначально писалась в MQL5, поэтому, хоть и незначительно, но блоки поиска расхождений претерпели изменения.

Функция поиска Медвежьих расхождений.

//+----------- Выявляем UP расхождения -------------------------------+
void UP(int l,const double &buf[],const double &high[],const datetime &time[])
  {
   if(Extremum(buf[l+1],buf[l],buf[l-1])<0)
     {
      int i=l;
      for(int j=0;j<extremum;j++)
        {
         int counted=LastPeak(i,buf);
         if(counted!=-1)
           {
            if(buf[l]<buf[counted] && high[l]>high[counted])
              {
               double k=fabs(buf[l]-buf[counted])/(l-counted);
               int z=1;
               bool yes=true;
               for(i=l-1;i>counted;z++,i--)
                     if(buf[i]>buf[l]+k*z){yes=false;break;}
               if(yes)
                 {
                  DrawPriceTrendLine(time[l],time[counted],high[l],high[counted],Red,STYLE_SOLID);
                  DrawIndicatorTrendLine(time[l],time[counted],buf[l],buf[counted],Red,STYLE_SOLID);
                  break;
                 }
              }

            if(buf[l]>buf[counted] && high[l]<high[counted])
              {
               double k=fabs(buf[l]-buf[counted])/(l-counted);
               int z=1;
               bool yes=true;
               for(i=l-1;i>counted;z++,i--)
                     if(buf[i]>buf[l]-k*z){yes=false;break;}
               if(yes)
                 {
                  DrawPriceTrendLine(time[l],time[counted],high[l],high[counted],Red,STYLE_DOT);
                  DrawIndicatorTrendLine(time[l],time[counted],buf[l],buf[counted],Red,STYLE_DOT);
                  break;
                 }
              }
           }
         i=counted;
        }
      //---
     }
  }

Функция поиска Бычьих расхождений.

//+----------- Выявляем DN расхождения -------------------------------+
void DN(int l,const double &buf[],const double &low[],const datetime &time[])
  {
   if(Extremum(buf[l+1],buf[l],buf[l-1])>0)
     {
      int i=l;
      //---
      for(int j=0;j<extremum;j++)
        {
         int counted=LastTrough(i,buf);
         if(counted!=-1)
           {
            if(buf[l]>buf[counted] && low[l]<low[counted])
              {
               double k=fabs(buf[l]-buf[counted])/(l-counted);
               int z=1;
               bool yes=true;
               for(i=l-1;i>counted;z++,i--)
                     if(buf[i]<buf[l]-k*z){yes=false;break;}
               if(yes)
                 {
                  DrawPriceTrendLine(time[l],time[counted],low[l],low[counted],Green,STYLE_SOLID);
                  DrawIndicatorTrendLine(time[l],time[counted],buf[l],buf[counted],Green,STYLE_SOLID);
                  break;
                 }
              }
            if(buf[l]<buf[counted] && low[l]>low[counted])
              {
               double k=fabs(buf[l]-buf[counted])/(l-counted);
               int z=1;
               bool yes=true;
               for(i=l-1;i>counted;z++,i--)
                     if(buf[i]<buf[l]+k*z){yes=false;break;}
               if(yes)
                 {
                  DrawPriceTrendLine(time[l],time[counted],low[l],low[counted],Green,STYLE_DOT);
                  DrawIndicatorTrendLine(time[l],time[counted],buf[l],buf[counted],Green,STYLE_DOT);
                  break;
                 }
              }
           }
         i=counted;
        }
      //---
     }
  }

Основное отличие в том, что в него добавлен фильтр. Опытным путем было установлено, что для случаев рис.20 и рис.28 сигнал имеет положительную тенденцию менее 30%. Поэтому они были исключены. Код фильтра выделен цветом. Функция поиска самих экстремумов также претерпела изменения. В ней исключена возможность фильтрации по положительному и отрицательному значению положения линии индикатора. В нашем случае в этом не только нет необходимости, но и мешает. Так как линия может принимать равные значения на текущем и предыдущем баре, основное определение делаем возможным равным нулю. 

В дальнейшем, если кто-то захочет внести изменения в правила поиска, это очень легко будет здесь сделать.

//+-- поиск  экстремумов/search for extrema -------------------------+
int Extremum(double a,double b,double c)
  {
   if((a-b)*(b-c)<=0)
     {
      if(c>b) return(1); //DN экстремум 
      if(c<b) return(-1);//UP экстремум 
     }
   return(0);
  }

Поиск точки левого плеча почти не изменился.

//+--- поиск второго UP экстремума/search for the second UP extreme -+
int LastPeak(int l,const double &buf[])
  {
   for(int i=l-2; i>4; i--)
     {
      int ext=Extremum(buf[i+1],buf[i],buf[i-1]);
      if(ext < 0)return (i);
     }
   return (-1);
  }
//+--- поиск второго DN экстремума/search for the second DN extreme -+
int LastTrough(int l,const double &buf[])
  {
   for(int i=l-2; i>4; i--)
     {
      int ext=Extremum(buf[i+1],buf[i],buf[i-1]);
      if(ext > 0)return (i);

     }
   return (-1);
  }

Добавлена функция построения тех самых точек, о которых мы говорили ранее. Ими мы выделяем краткосрочные расхождения.

//+------------ Создает стрелку   Creates an arrow -------------------+ 
bool ArrowCreate(string                  name,
                 datetime                time,
                 double                  price,
                 ENUM_ARROW_ANCHOR       anchor,
                 color                   clr)
  {
//--- сбросим значение ошибки 
   ResetLastError();
//--- создадим стрелку 
   if(!ObjectCreate(0,name,OBJ_ARROW,0,time,price))
     {
      Print(__FUNCTION__,
            ": не удалось создать стрелку! Код ошибки = ",GetLastError());
      return(false);
     }
   ObjectSetInteger(0,name,OBJPROP_ARROWCODE,167);
//--- установим способ привязки 
   ObjectSetInteger(0,name,OBJPROP_ANCHOR,anchor);
   ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
   ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
   ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
   ObjectSetInteger(0,name,OBJPROP_BACK,false);
   ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
   ObjectSetInteger(0,name,OBJPROP_SELECTED,false);
   ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
//--- успешное выполнение 
   return(true);
  }
//+------------------------------------------------------------------+ 

Также изменены основные блоки построения для возможности отображать все линии дивергенций или только последней на участке определенном параметром " extremum".

Для основного окна графика

//+------ создаем объекты на графике цены ---------------------------+
void DrawPriceTrendLine(datetime T_0,datetime T_1,double P_0,double P_1,color color_0,int style)
  {
   string name_0=short_name+"Line_Sn"+ColorToString(color_0);
   string name_1="";
   if(allLine)
      name_1=short_name+DoubleToString(T_0,0);
   else
      name_1=short_name+DoubleToString(T_1,0);
//--- 
   ObjectDelete(0,name_1);
   drawLineS(name_1,T_0,T_1,P_0,P_1,color_0,style,0,true,false,0);
//+-----------+
   if(style==STYLE_DOT)
     {
      ObjectDelete(0,name_0);
      drawLineS(name_0,T_1,T_0,P_1,P_0,clrAqua,0,3,true,true,0);
     }
  }

и в окне индикатора

//+------ создаем объекты в окне индикатора -------------------------+
void DrawIndicatorTrendLine(datetime T_0,datetime T_1,double P_0,double P_1,color color_0,int style)
  {

   int window=wid;
   string name_0=short_name+"Line_Pn"+ColorToString(color_0);
   string name_1="";
   if(allLine)
      name_1=short_name+DoubleToString(T_0+wid,0);
   else
      name_1=short_name+DoubleToString(T_1+wid,0);
//---
   ObjectDelete(0,name_1);
   drawLineS(name_1,T_0,T_1,P_0,P_1,color_0,style,0,false,false,window);
//---
   if(style==STYLE_SOLID)
     {
      ObjectDelete(0,name_0);
      drawLineS(name_0,T_1,T_0,P_1,P_0,clrMagenta,style,2,true,true,window);
     }
  }

По этой же причине из функции построения трендовых линий команда удаления переместилась в основной блок.

//+------------------------------------------------------------------+
void drawLineS(string name,datetime T_0,datetime T_1,double P_0,double P_1,color clr,
               int style,int width,bool back,bool ray,int window)
  {
   ObjectCreate(0,name,OBJ_TREND,window,T_0,P_0,T_1,P_1,0,0);
   ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,ray);
   ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
   ObjectSetInteger(0,name,OBJPROP_STYLE,style);
   ObjectSetInteger(0,name,OBJPROP_WIDTH,width);
   ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
   ObjectSetInteger(0,name,OBJPROP_BACK,back);
  }

Наш индикатор принял вот такой вид.


Рис.65

Здесь мы наблюдаем помимо привычных для нас линий дивергенции множество тех самых точек, определяющих зоны консолидации и являющихся уровнями входа в Sell и Buy сделки. Эти сигналы определяются выявленными нами закономерностями (однонаправленное движение линий “DI+”,”DI-“). Зеленые точки — это уровни входа в Buy, а фиолетовые — в Sell. Появление синих точек на фоне зеленых и желтых на фоне фиолетовых предупреждает трейдера о неуверенном тренде и возможном его смене. После открытия сделки они могут служить уровнями для передвижения стопов. Скажу сразу, что вход в сделки по ним отложенными ордерами нежелателен. И это не только по тому, что они определяют краткосрочную тенденцию рынка , но из-за ложных срабатываний по причине тестирования хвостами. Сигналом для совершения сделки является закрытие свечи выше (ниже) этого уровня. В построении участвует переменная “Gep”. Алгоритм таков: после появления сигнала Sell точка ставится ниже Low бара, на котором сформировался сигнал, а при появления сигнала Buy ставим выше High. С отступом от High\low прекрасно справляются функции, определяющие точки привязки ANCHOR_BOTTOM и ANCHOR_TOP. В дальнейшем все сигналы в радиусе «+\- Gep» будут строиться по первой точке.

В дальнейшем каждый из вас сможет доработать эту версию, допустим, уменьшением запаздывания основной линии индикатора. Самый простой способ — это уменьшить период второго сглаживания, переместив его в переменные, и тем самым позволить себе поэкспериментировать. Также удалить все, что касается классического определения сигнала, и добавить алгоритм, о котором мы говорили при обсуждении MACD. При этом оставить только отрисовку уровней входа в сделку. Это значительно уменьшит количество построений.

Проверить правильность наших умозаключений можно создав небольшого робота. Классический вариант и, как следствие, направление основной линии нас не интересует. Это позволяет нам воспользоваться штатным ADX из терминала. Из фильтров добавим только случаи, когда пробойная свеча очень велика. Для случаев, когда по какой-то причине нет линии противоположного условного канала, на которую выставляются стопы, введем дистанцию Stop Loss. В советнике также придется самостоятельно определить дистанцию отступа от High/Low. Ниже приведены результаты тестирования по основным валютным парам EUR/USD,GBP/USD,USD/JPY за период с 01.01.2016 по 01.06.2019 на временном интервале Н1,Н4.

EURUSD Н1


EURUSD Н4


GBPUSD H1


GBPUSD H4


JPYUSD H1


JPYUSD H4


Результаты могли бы быть и получше. Но это не цель. Самое главное — есть положительная тенденция.

Заключение

Так что же такое новый подход к хорошо известным, как нам кажется, вещам? Это пустая трата времени или прогресс? Вы — успешный трейдер. У вас прекрасная работающая стратегия. Может посмотреть на эту стратегию под другим углом и это поможет вам добиться более высокого результата? Или пускай все будет как есть? На эти вопросы каждый для себя ответит сам. Возможно, результаты моей работы кого-то подтолкнут по-другому взглянуть на результаты своего труда или даже создать совершенно новые инструменты технического анализа.

Я самоучка, поэтому всегда критически относился к тому, что публикуется в широком доступе. Мой мозг не был замутнен авторитетами, что давало широкое поле для деятельности. Посещая различные форумы, видел, как авторы стратегий долгое время рассказывают своим ученикам все ее нюансы. Все это толкает меня, в рамках концепции получение максимальной прибыли, продолжать поиски наиболее эффективных  решений. Если это кому-то поможет в его стремлении вперед, значит, мое время потрачено не зря. Конечно в данный материал вошла малая часть того, что было проделано во время изучения дивергенции. Так получалось, что возникающие в процессе вопросы требовали решения и, как следствие, опять же нестандартного. Описать все в рамках одной темы сложно. По этой причине, возможно, увидят свет материалы, в которых будут рассмотрены другие нестандартные решения.

И еще господа. С просьбами усовершенствовать опубликованные вещи, тем более совместного создания торговых роботов, прошу не обращаться. Для этого существует раздел сайта Фриланс. Программирование для меня скорее вынужденная необходимость. Писать программы я стал только для того чтобы знать возможности языка и по незнанию не ставить перед специалистами невыполнимых задач, а также для оперативной проверки своих идей.

     Имя         Тип                           Описание                      
1 ADX_Osc.mq5 Indicators  Индикатор для анализа дивергенции. 
2 TestADX.mql5 Experts  Эксперт для тестирования выявленных закономерностей.