Построение системы обнаружения дивергенций: Создание пользовательского индикатора MPO4
Содержание
- Введение
- Представляем MPO4 — количественная оценка рыночного усилия
- Математическое построение MPO4
- Нормирование и сглаживание с помощью EMA
- Создание каркаса индикатора
- Реализация расчета исходных значений MPO4
- Теория дивергенции и создание механизма обнаружения опорных точек
- Управление состоянием и архитектура без перерисовки
- Практическая интерпретация осциллятора MPO4
- Ограничения и компромиссы при проектировании
- Заключение
ВВЕДЕНИЕ
Большинство трейдеров знакомы с такими осцилляторами, как индекс относительной силы (RSI) или стохастик (Stochastic Oscillator). Они отвечают на вопрос: "Где находится цена относительно ее недавнего диапазона?" Они эффективны, но могут лишь реагировать на уже произошедшие изменения, часто запаздывая именно тогда, когда нужны больше всего. Кроме того, они рассматривают все ценовые бары как равнозначные, будь то крошечный доджи или крупная волатильная свеча. Именно здесь MPO4 принципиально расходится с ними — не только по сигналам, но и по своей базовой философии.
Представляем MPO4 — количественная оценка рыночного усилия
Исходная концепция MPO4
Важно понять, чем MPO4 принципиально отличается от большинства традиционных осцилляторов. Многие популярные осцилляторы построены на измерении движения цены. Например, индекс относительной силы (RSI) сравнивает недавние приросты цены с недавними снижениями. Стохастические осцилляторы определяют положение цены относительно ее недавнего торгового диапазона. Хотя эти подходы годами подтверждали свою полезность, их объединяет общая черта: основное внимание уделяется итоговому положению цены. Подход MPO4 к моментуму иной.
Вместо того чтобы задаваться вопросом, где закрылась цена, MPO4 пытается оценить, какое усилие потребовалось, чтобы сдвинуть цену. Индикатор анализирует тело каждой свечи и оценивает как его размер, так и направление. Это создает представление о рыночном давлении, а не просто о положении цены.
Чтобы понять эту концепцию, рассмотрим две бычьи свечи. Обе свечи могут закрыться выше уровня открытия, но это не обязательно означает, что они несут одинаковую информацию. Небольшая бычья свеча с узким телом может свидетельствовать лишь о незначительном давлении со стороны покупателей. Крупная бычья свеча, тело которой в несколько раз больше среднего, может свидетельствовать о значительно более активном участии покупателей.
Традиционные осцилляторы часто рассматривают эти две свечи сходным образом, поскольку обе способствуют восходящему движению цены. Однако MPO4 учитывает, что более крупная свеча отражает большее направленное усилие, и потому увеличивает ее вклад в итоговое значение осциллятора.
Эта идея лежит в основе всего индикатора.
Измерение направленного давления
По сути, MPO4 оценивает три характеристики каждой свечи:
- размер тела свечи;
- направление свечи;
- значимость размера тела относительно недавней рыночной активности.
Размер тела рассчитывается как абсолютная разница между ценами открытия и закрытия. Более крупные тела свечей отражают более сильную выраженность направленного движения, а меньшие — более слабую.
Направление свечи определяет, будет ли ее вклад бычьим или медвежьим. Бычьи свечи вносят положительный вклад в рыночное давление, медвежьи — отрицательный, а нейтральные свечи дают мало направленной информации или не дают ее вовсе. Однако одного только размера тела недостаточно. Волатильность рынка постоянно меняется. Свеча, выглядящая крупной в спокойную сессию, может оказаться совершенно обычной при высокой волатильности рынка.
Для этого MPO4 сравнивает размер тела каждой свечи со средним размером тела за недавний период анализа. Этот процесс преобразует исходный размер свечи в относительную меру рыночного усилия.
В результате индикатор не просто выявляет крупные свечи. Вместо этого он выявляет необычно большие или маленькие свечи относительно текущих рыночных условий.
Логика расчета рыночного давления
После оценки направленного вклада каждой свечи индикатор суммирует вклады в скользящем периоде анализа. Такое агрегирование позволяет MPO4 ответить на вопрос: "Преобладало ли на рынке в последнее время бычье или медвежье давление?"
Если бычьи свечи стабильно преобладают над медвежьими, осциллятор растет. Если преобладают медвежьи свечи, осциллятор снижается. Когда давление покупателей и продавцов остается относительно сбалансированным, осциллятор стремится к своему центру. Полученное значение представляет собой меру направленного давления, а не простую меру движения цены.
Это различие тонкое, но важное. На двух рынках изменения цен могут быть схожими, а значения MPO4 — совершенно разными. Постепенное движение вверх, состоящее из множества небольших свечей, может создавать меньшее давление, чем более короткое движение, вызванное серией исключительно крупных бычьих свечей.
Почему этот подход имеет значение
Основная цель MPO4 — сделать оценку моментума более чувствительной к качеству движения цены, а не только к его направлению. Учитывая размер тела свечи в расчете, индикатор пытается различать слабую и сильную активность участников рынка. Крупные свечи с четко выраженным направлением сильнее влияют на осциллятор, а более мелкие и менее значимые вносят меньший вклад.
Это позволяет MPO4 реагировать не только на направление цены, но и на то, насколько агрессивно участники рынка формируют это движение.
Модуль дивергенций, который далее добавляется в индикатор, опирается на эту основу. Поскольку осциллятор предназначен для измерения направленного давления, дивергенции могут указывать на ситуации, когда цена продолжает обновлять максимумы или минимумы, а давление покупателей или продавцов начинает ослабевать.
Поэтому перед реализацией математических расчетов полезно рассматривать MPO4 не как очередную вариацию RSI или стохастического осциллятора, а как осциллятор на основе рыночного давления, основная цель которого — количественно оценить силу участия покупателей и продавцов на рынке.
Математическое построение MPO4
Теперь, когда мы разобрались с концепцией MPO4, можно рассмотреть, как индикатор преобразует информацию о свечах в числовые значения осциллятора.
В отличие от многих осцилляторов, основанных на изменениях цены, MPO4 использует в качестве исходных данных тела свечей. Каждый расчет в индикаторе основан на соотношении размера тела свечи и среднего размера тела за недавний период анализа.
Весь процесс можно разделить на четыре этапа:
- измерить размер тела свечи;
- определить направление свечи;
- взвесить каждую свечу относительно среднего размера тела;
- суммировать взвешенные вклады, чтобы получить нормированное значение осциллятора.
Индикатор непрерывно выполняет эти вычисления для каждого нового бара, формируя скользящий показатель направленного рыночного давления.
Этап 1 — измерение размера тела свечи
Первый шаг — расчет размера тела каждой свечи. Тело свечи отражает расстояние между ценами открытия и закрытия.
Для любой свечи: размер тела = |цена закрытия - цена открытия|
Бычья и медвежья свечи могут иметь одинаковый размер тела, несмотря на то что их направления противоположны. На этом этапе в MPO4 учитывается только величина движения.
На приведенной ниже иллюстрации показан размер тела свечи, то есть разница между ценами закрытия и открытия свечи независимо от направления движения.

В коде MQL5 размер тела рассчитывается следующим образом:
double body = MathAbs(close[i] - open[i]);
Этап 2 — определение направления
Когда размер тела известен, MPO4 определяет, вносит ли свеча вклад в бычье или медвежье давление.
Логика здесь проста:
int direction = (close[i] > open[i]) ? 1 : (close[i] < open[i]) ? -1 : 0;
В результате возникают три возможных состояния:
| Тип свечи | Значение направления |
|---|---|
| Бычья | +1 |
| Медвежья | -1 |
| Доджи/нейтральная | 0 |
Направление служит знаковым множителем, определяющим, будет ли вклад свечи в давление осциллятора положительным или отрицательным.
Этап 3 — относительное взвешивание тела свечи
Именно эта особенность принципиально отличает MPO4 от многих традиционных осцилляторов. Крупная свеча должна оказывать большее влияние, чем маленькая. Однако понятие "крупная" всегда зависит от текущих рыночных условий.
Чтобы определить значимость свечи, MPO4 сначала рассчитывает средний размер тела за выбранный период анализа.
Для периода анализа в шесть баров:
Bodies: 4, 5, 6, 5, 4, 6 Average Body: (4 + 5 + 6 + 5 + 4 + 6) / 6 = 5
Затем текущая свеча сравнивается с этим средним значением.
Вес = размер тела / средний размер тела
Предположим, что размер тела текущей свечи равен 10.
Вес = 10 / 5 = 2
Это означает, что вклад свечи в давление вдвое больше обычного.
Если размер тела свечи составляет всего 2,5:
Вес = 2,5 / 5 = 0,5
Это означает, что вклад свечи в давление составляет лишь половину обычного. Взвешивание позволяет MPO4 автоматически адаптироваться к изменению волатильности. Ниже показан относительный вклад в зависимости от размера тела при среднем размере тела 5:
| Тело | Вес |
|---|---|
| 2,5 | 0,5 |
| 5 | 1 |
| 10 | 2 |
| 15 | 3 (и так далее) |
Вес рассчитывается следующим образом:
double weight = body / avgBody; Это один из важнейших расчетов во всем индикаторе, поскольку он преобразует исходный размер свечи в относительный показатель рыночного усилия.
Этап 4 — расчет показателя давления
После вычисления направления и веса MPO4 объединяет их в одно значение вклада.
Вклад = направление × вес
Рассмотрим следующие примеры:
| Свеча | Направление | Вес | Вклад |
|---|---|---|---|
| Крупная свеча | 1 | 2,0 | +2,0 |
| Свеча среднего размера | 1 | 1,0 | +1,0 |
| Крупная медвежья свеча | -1 | 2,0 | -2,0 |
| Небольшая медвежья свеча | -1 | 0,5 | -0,5 |
Затем индикатор суммирует все вклады в пределах периода анализа.
rawSum += direction * weight;
- Если в последовательности преобладают сильные бычьи свечи, значение показателя будет положительным.
- Если в последовательности преобладают сильные медвежьи свечи, значение показателя будет отрицательным.
- При равновесии на рынке положительные и отрицательные вклады будут компенсировать друг друга, а осциллятор останется вблизи середины диапазона.
На этом этапе мы преобразовали данные отдельных свечей в единый показатель направленного рыночного давления. Однако полученные значения по-прежнему не ограничены заданным диапазоном, и их сложно единообразно интерпретировать в разных рыночных условиях. Далее нормируем и сгладим эти значения давления, чтобы получить итоговые значения осциллятора MPO4.
Нормирование и сглаживание с помощью EMA
В конце предыдущего раздела мы преобразовали данные набора свечей в показатель направленного давления. Проблема в том, что исходное значение давления само по себе малоинформативно. При периоде анализа в шесть свечей исходные значения, естественно, будут отличаться от значений для периода в двенадцать свечей. Аналогичным образом, на рынках с высокой волатильностью значения давления могут быть значительно больше по модулю, чем на более спокойных рынках.
Чтобы показания осциллятора можно было интерпретировать в разных рыночных условиях, в MPO4 выполняются две дополнительные операции:
- нормирование;
- экспоненциальное сглаживание.
На этих заключительных этапах исходный показатель давления преобразуется в устойчивый осциллятор, который можно анализировать визуально и использовать для выявления дивергенций.
Почему необходимо нормирование
Рассмотрим период анализа длительностью шесть баров. Предположим, что каждая свеча в периоде анализа — сильная бычья свеча с весом 2.
Тогда исходный показатель давления равен:
Raw Sum = 2 + 2 + 2 + 2 + 2 + 2 Raw Sum = 12
Теперь рассмотрим другую рыночную ситуацию, в которой каждой свече присвоен вес 1.
Raw Sum = 1 + 1 + 1 + 1 + 1 + 1 Raw Sum = 6
Обе ситуации свидетельствуют об устойчивом давлении покупателей, однако числовые значения значительно различаются. Без нормирования интерпретировать показания осциллятора сложно, поскольку шкала постоянно меняется.
Чтобы решить эту проблему, в MPO4 исходный показатель давления приводится к ограниченному диапазону значений.
Теоретический максимум давления
Сначала индикатор оценивает максимально возможное значение показателя направленного давления в выбранном периоде анализа. Если каждой свече присвоен максимально допустимый вес: максимально возможная сумма = период анализа × максимальный вес.
Например:
Период анализа = 6.
Максимальный вес = 3.
Максимально возможная сумма = 18.
Этот теоретический максимум служит опорным значением при масштабировании осциллятора.
Масштабирование показателя давления
Нормированное значение получают путем деления исходного показателя давления на теоретический максимум давления.
В общем виде:
Нормированное значение = \frac{RawSum}{MaximumPossible}
Затем результат масштабируется так, чтобы он соответствовал диапазону значений осциллятора. В нашей реализации:
double maxPossible = MPOLength * 3.0; double normalized = (rawSum / maxPossible) * 30.0;
В результате исходный показатель давления преобразуется в осциллятор, значения которого колеблются в ограниченном диапазоне примерно от -100 до +100.
Для обеспечения численной устойчивости на последнем этапе значения индикатора дополнительно ограничиваются допустимым диапазоном:
normalized = MathMax(-30.0, MathMin(30.0, normalized));
Это гарантирует, что даже в непредвиденных рыночных условиях значения осциллятора не выйдут за пределы заданного диапазона. Зависимость линейная. По мере усиления давления покупателей осциллятор поднимается к отметке +30. По мере усиления давления продавцов осциллятор опускается к отметке -30.
На этом этапе мы преобразовали направленное рыночное давление в осциллятор с ограниченным диапазоном значений. Однако остается еще одна проблема.
Осциллятор получается шумным. Крупные свечи могут вызывать резкие скачки показателя давления, из-за чего значения сильно колеблются от бара к бару. Здесь и требуется сглаживание.
Применение экспоненциального сглаживания
Вместо того чтобы выводить нормированное значение без сглаживания, применим экспоненциальную скользящую среднюю (EMA).
В отличие от простой скользящей средней (SMA), при расчете EMA последнему значению придается больший вес, но учитываются и предыдущие значения.
Коэффициент сглаживания рассчитывается следующим образом:

В коде:
SmoothAlpha = 2.0 / (SmoothPeriod + 1.0);
Для периода сглаживания 7:
Alpha = 2 / (7 + 1)
Alpha = 0.25
Это означает, что вес нового значения в расчете составляет 25%, а остальные 75% приходятся на предыдущие значения осциллятора.
Рекурсивный расчет EMA
После вычисления коэффициента сглаживания каждое новое значение осциллятора объединяется с предыдущим путем взвешенного усреднения.
Рекурсивная формула EMA имеет следующий вид:

В коде эта формула реализуется следующим образом:
SmoothedBuffer[i] = RawBuffer[i] * SmoothAlpha + SmoothedBuffer[i - 1] * (1.0 - SmoothAlpha);
Этот расчет повторяется для каждого бара. В результате колебания осциллятора становятся более плавными, при этом он реагирует на изменения давления без чрезмерных скачков.
Итоговый осциллятор MPO4
После сглаживания получается итоговое значение индикатора, которое отображается на графике. Итоговый осциллятор служит основой для всех последующих возможностей, включая оценку тренда, генерацию сигналов и механизм обнаружения дивергенций, который мы реализуем далее в статье.
Теперь, когда мы разобрали математическую основу, можно приступить к созданию самого индикатора и реализовать эти расчеты в структурированном коде на языке MQL5.
Создание каркаса индикатора
Чтобы создать высокопроизводительный пользовательский индикатор на языке MQL5, измеряющий рыночное усилие и направленное давление, начнем с надежного каркаса кода. Производительность индикатора на языке MQL5 зависит от правильного задания директив препроцессора, свойств и входных параметров, а также инициализации буферов. Четкое разделение компонентов позволяет снизить вычислительные затраты при обновлении графика в реальном времени и быстром тестировании на исторических данных.
Рассмотрим архитектуру каркаса индикатора, уделив внимание настройке параметров компиляции, заданию директив отображения, определению необходимых перечислений и безопасному выделению памяти для потоков данных.
Разбор архитектуры — директивы препроцессора и управление памятью
Раздел с директивами препроцессора определяет, как клиентский терминал взаимодействует с потоком выполнения нашей программы. Мы будем использовать:
#property indicator_separate_window
Чтобы отобразить MPO4 как осциллятор с ограниченным диапазоном значений, его следует разместить в отдельном окне под основным графиком. Настроим буферы и графические построения индикатора, чтобы результаты расчетов отображались в терминале.
-
Indicator_buffers 9 — эта директива предписывает распределителю памяти терминала использовать ровно девять последовательных блоков данных. На графике отображаются данные только трех массивов, а остальные шесть используются для внутренних расчетов. Эти вспомогательные буферы предотвращают перерисовку, сохраняя промежуточные результаты расчетов и исторические ценовые показатели, а также обеспечивая отслеживание пиков осциллятора.
-
Indicator_plots 3 — этот параметр гарантирует, что с памятью визуализации индикатора будут связаны только заданные графические элементы, а именно основная сглаженная линия давления, стрелки бычьей дивергенции и стрелки медвежьей дивергенции.
Разделение расчетных буферов и буферов отображения повышает читаемость кода и снижает нагрузку при обработке поступающих тиков. Код приведен ниже:
//+------------------------------------------------------------------+ //| MPO4_Oscillator System.mq5 | //| Copyright 2026, soloharbinger | //| https://www.mql5.com/ru/users/soloharbinger | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, soloharbinger" #property link "https://www.mql5.com/ru/users/soloharbinger" #property version "1.00" #property indicator_separate_window // We need 9 buffers total: 3 for plotting, 6 for state tracking/calculations #property indicator_buffers 9 #property indicator_plots 3 //--- Plot 1: The Oscillator Line #property indicator_label1 "Oscillator" #property indicator_type1 DRAW_LINE #property indicator_color1 clrDodgerBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 2 //--- Plot 2: Bullish Divergence Arrow #property indicator_label2 "Bull Div" #property indicator_type2 DRAW_ARROW #property indicator_color2 clrLimeGreen #property indicator_width2 2 //--- Plot 3: Bearish Divergence Arrow #property indicator_label3 "Bear Div" #property indicator_type3 DRAW_ARROW #property indicator_color3 clrRed #property indicator_width3 2
Настройка глобальных входных параметров и значений перечислений
Чтобы механизм можно было гибко настраивать для разных условий применения, добавим входные параметры, сгруппированные в наглядные блоки интерфейса: выбор режимов, настройка переменных и ограничения вычислений алгоритма.
//--- Enumerations enum ENUM_DIV_SOURCE { DIV_SRC_MPO = 0, // Custom MPO4 Modal Engine Oscillator DIV_SRC_RSI = 1 // Standard Relative Strength Index (RSI) }; //--- Input Parameters input group "=== Oscillator Selection ===" input ENUM_DIV_SOURCE InpSource = DIV_SRC_MPO; // Oscillator Source input group "=== MPO4 Settings ===" input int InpMpoLen = 6; // MPO4 Lookback Period input int InpSmooth = 7; // Oscillator Smoothing (EMA) input double InpMpoOB = 30.0; // MPO4 Overbought Level input double InpMpoOS = -30.0; // MPO4 Oversold Level input group "=== RSI Settings ===" input int InpRsiPeriod = 14; // RSI Period input double InpRsiOB = 70.0; // RSI Overbought Level input double InpRsiOS = 30.0; // RSI Oversold Level input group "=== Divergence ===" input int InpPivotLen = 2; // Pivot Lookback Length for Divergence Confirmation
Описание входных параметров
Разделение входных параметров на четкие группы упрощает настройку индикатора на графиках в реальном времени. У каждой переменной свое техническое назначение. Ниже приведены основные входные параметры, на которые следует обратить внимание:
- ENUM_DIV_SOURCE — это перечисление позволяет пользователю выбирать способ оценки исходных изменений моментума: с помощью пользовательского алгоритма MPO4 или стандартного индекса относительной силы (RSI). Это перечисление также используется для перекрестной проверки наблюдений, полученных с помощью RSI и MPO4.
- InpMpoLen — этот параметр определяет размер скользящего периода анализа, используемого для оценки текущей рыночной волатильности. При значении 6 алгоритм сравнивает текущую интенсивность рыночного давления со скользящим средним по шести свечам.
- InpSmooth — этот параметр регулирует чувствительность итоговой линии осциллятора. Для фильтрации локального рыночного шума используется экспоненциальная скользящая средняя (EMA).
- InpPivotLen — это значение используется для фильтрации при обнаружении дивергенций. При значении 2 локальный максимум подтверждается, если по обе стороны от него есть по две свечи с более низкими максимумами, а локальный минимум — если по обе стороны есть по две свечи с более высокими минимумами. Это гарантирует, что расчеты будут опираться на неизменные точки разворота рынка.
Глобальные массивы, структура памяти и отслеживание переменных
После определения свойств данных объявим динамические массивы для отображения результатов, кэширования внутренних расчетов, проверки состояния и обеспечения отсутствия перерисовки.
//--- Visual Indicator Buffers double OscBuffer[]; // Smoothed Final Line double BullDivBuffer[]; // Plotted Arrows double BearDivBuffer[]; // Plotted Arrows // Hidden Calculation Buffers double RawBuffer[]; // Pre-smoothing data double RsiBuffer[]; // Holds raw iRSI data (if selected) // State Management Buffers (Prevents repainting on live ticks) double LastPivLowPriceBuffer[]; double LastPivLowOscBuffer[]; double LastPivHighPriceBuffer[]; double LastPivHighOscBuffer[]; //--- Handles and variables int RsiHandle = INVALID_HANDLE; double SmoothAlpha;
Рассмотрим разделение этих динамических буферов по назначению:
- Буферы отображения (OscBuffer, BullDivBuffer, BearDivBuffer) — эти массивы напрямую связаны со слоями отрисовки графика. Изменения значений элементов массивов отображаются непосредственно в интерфейсе терминала с помощью стандартных линий или символов.
- Расчетные буферы (RawBuffer, RsiBuffer) — эти буферы будут помечены как предназначенные только для вычислений. В них хранятся промежуточные результаты преобразований, например исходные ненормированные показатели рыночного давления, без лишних затрат ресурсов на отрисовку.
- Массивы управления состоянием (LastPivLowPriceBuffer, LastPivLowOscBuffer, LastPivHighPriceBuffer, LastPivHighOscBuffer) — эти буферы сохраняют исторические показатели точек разворота между поступлениями тиков. В этих массивах параметры предыдущих экстремумов сохраняются в хронологическом порядке, чтобы при поступлении новых тиков не изменялись уже рассчитанные исторические значения.
Эта структура служит основой для индикатора на языке MQL5. Мы задали директивы препроцессора, группы входных параметров и массивы для отслеживания данных.
Подготовка функции инициализации
После объявления буферов остается последний шаг — настроить их внутри функции OnInit(). Каждый буфер привязывается с помощью соответствующих функций:
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Map buffers SetIndexBuffer(0, OscBuffer, INDICATOR_DATA); SetIndexBuffer(1, BullDivBuffer, INDICATOR_DATA); SetIndexBuffer(2, BearDivBuffer, INDICATOR_DATA); SetIndexBuffer(3, RawBuffer, INDICATOR_CALCULATIONS); SetIndexBuffer(4, RsiBuffer, INDICATOR_CALCULATIONS); SetIndexBuffer(5, LastPivLowPriceBuffer, INDICATOR_CALCULATIONS); SetIndexBuffer(6, LastPivLowOscBuffer, INDICATOR_CALCULATIONS); SetIndexBuffer(7, LastPivHighPriceBuffer, INDICATOR_CALCULATIONS); SetIndexBuffer(8, LastPivHighOscBuffer, INDICATOR_CALCULATIONS); //--- Set Arrow Codes PlotIndexSetInteger(1, PLOT_ARROW, 233); // Up arrow PlotIndexSetInteger(2, PLOT_ARROW, 234); // Down arrow //--- Setup Dynamic OB/OS Levels Based on Source if(InpSource == DIV_SRC_MPO) { IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, InpMpoOB); IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, 0.0); IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, InpMpoOS); IndicatorSetString(INDICATOR_SHORTNAME, "MPO4 Div Engine"); } else { IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, InpRsiOB); IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, 50.0); IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, InpRsiOS); IndicatorSetString(INDICATOR_SHORTNAME, "RSI Div Engine"); // Initialize RSI handle RsiHandle = iRSI(_Symbol, _Period, InpRsiPeriod, PRICE_CLOSE); if(RsiHandle == INVALID_HANDLE) { Print("Failed to load RSI Handle"); return(INIT_FAILED); } } //--- Set Level Styles IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, clrDarkGray); IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, STYLE_DOT); //--- Calculate Alpha for Smoothing SmoothAlpha = 2.0 / (InpSmooth + 1.0); return(INIT_SUCCEEDED); }
Важно различать INDICATOR_DATA и INDICATOR_CALCULATIONS.
- Данные буферов INDICATOR_DATA отображаются на графике.
- Буферы INDICATOR_CALCULATIONS используются исключительно для внутренних расчетов.
Символы стрелок задаются с помощью кодов шрифта Wingdings, которые определяют вид маркеров бычьей и медвежьей дивергенции в окне индикатора. В зависимости от источника данных индикатора, выбранного в перечислении, настраиваются динамические уровни перекупленности и перепроданности (OB/OS) и задаются их названия. Затем инициализируется хэндл стандартного индикатора RSI и предварительно вычисляется коэффициент сглаживания EMA. Предварительный расчет значения альфа при инициализации повышает производительность во время выполнения, поскольку расчет не нужно повторять на каждом тике.
На этом этапе каркас индикатора MPO4 полностью готов.
Расчеты осциллятора пока не реализованы, но уже создана вся инфраструктура для отрисовки, сглаживания, обнаружения дивергенций и управления состоянием. Далее реализуем расчет исходного показателя рыночного давления MPO4.
Реализация расчета исходного значения MPO4
Теперь, когда каркас индикатора полностью подготовлен и все буферы правильно привязаны в функции OnInit(), можно перейти к основной вычислительной части — функции OnCalculate. Именно здесь исходные свечные данные фактически преобразуются в итоговое значение осциллятора.
Функция OnCalculate в MQL5 вызывается на каждом тике, в том числе при формировании нового бара. В нее передаются массивы с полной историей цен, а ее основная задача — определить, сколько баров необходимо пересчитать. Чтобы создавать эффективные индикаторы, необходимо понимать назначение параметра prev_calculated. При первом вызове функции значение prev_calculated равно нулю, поэтому необходимо обработать каждый бар. При последующих вызовах параметр prev_calculated содержит количество баров, уже обработанных при предыдущем вызове. Это позволяет пропускать исторические бары и обрабатывать только новые данные.
Для начала зададим минимально необходимое количество баров и границу расчета:
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- Minimum bars check if(rates_total < MathMax(InpMpoLen, InpRsiPeriod) + InpPivotLen + 5) return 0; int limit = prev_calculated == 0 ? 0 : prev_calculated - 1; //--- Clear State Arrays on First Run if(prev_calculated == 0) { ArrayInitialize(BullDivBuffer, EMPTY_VALUE); ArrayInitialize(BearDivBuffer, EMPTY_VALUE); ArrayInitialize(LastPivLowPriceBuffer, DBL_MAX); ArrayInitialize(LastPivLowOscBuffer, -99999); ArrayInitialize(LastPivHighPriceBuffer, 0); ArrayInitialize(LastPivHighOscBuffer, 99999); }
Проверка минимального количества баров гарантирует наличие достаточного объема исторических данных до начала любых вычислений. Переменная limit определяет начальный индекс цикла вычислений. Присвоив ей значение prev_calculated - 1, мы избегаем повторной обработки уже обработанных баров, что значительно повышает производительность при торговле в реальном времени.
Обработка выбора RSI в качестве источника
Наш индикатор позволяет выбрать между пользовательским осциллятором MPO4 и стандартным RSI. Когда пользователь выбирает RSI в качестве источника, необходимо скопировать значения RSI в буфер RawBuffer для дальнейшей обработки. Это выполняется до начала основного цикла вычислений:
// Handle RSI buffering to match the loop direction if(InpSource == DIV_SRC_RSI) { int to_copy = rates_total - limit; double tempRsi[]; if(CopyBuffer(RsiHandle, 0, 0, to_copy, tempRsi) <= 0) return 0; for(int i = 0; i < to_copy; i++) { RawBuffer[limit + i] = tempRsi[i]; } }
Обратите внимание: индексы массивов согласованы намеренно. Функция CopyBuffer копирует значения RSI, начиная с последнего бара, а мы помещаем их непосредственно в соответствующие элементы буфера RawBuffer. При такой организации механизм обнаружения дивергенций, который мы рассмотрим далее, работает одинаково независимо от источника входных данных — MPO4 или RSI.
Расчет рыночного давления в MPO4
Когда пользователь выбирает режим MPO4, выполняются основные математические расчеты, описанные ранее в статье. Цикл выполняется от индекса limit до rates_total - 1. Для каждого бара рассчитывается показатель направленного давления на основе InpMpoLen предшествующих свечей:
else // MPO4 Calculation { for(int i = limit; i < rates_total; i++) { double sumBodies = 0; int count = 0; for(int j = 0; j < InpMpoLen; j++) { int idx = i - j; if(idx < 0) break; sumBodies += MathAbs(close[idx] - open[idx]); count++; } double avgBody = (count > 0 && sumBodies > 0) ? (sumBodies / count) : SymbolInfoDouble(_Symbol, SYMBOL_POINT); double rollingSum = 0; for(int j = 0; j < InpMpoLen; j++) { int idx = i - j; if(idx < 0) break; double body = MathAbs(close[idx] - open[idx]); double dir = (close[idx] > open[idx]) ? 1.0 : (close[idx] < open[idx]) ? -1.0 : 0.0; double weight = body / avgBody; rollingSum += (dir * weight); } RawBuffer[i] = (rollingSum / (InpMpoLen * 2.0)) * 100.0; } }
Давайте шаг за шагом разберем, что происходит внутри этого цикла.
Первый проход — расчет среднего размера тела свечи. Для каждого индекса бара i индикатор рассматривает период анализа из InpMpoLen баров (включая текущий бар) и суммирует абсолютные размеры тел свечей. Затем средний размер тела свечи вычисляется путем деления этой суммы на количество найденных допустимых баров. Защитная проверка гарантирует, что avgBody никогда не будет равен нулю. Если не найдено ни одного допустимого тела свечи, в качестве минимального опорного значения используется значение пункта символа.
Второй проход — вычисление взвешенных вкладов с учетом направления. После определения среднего размера тела свечи цикл повторно выполняется для того же периода анализа. Для каждой свечи определяются три величины:
- body — абсолютный размер тела свечи;
- dir — знак направления: +1 для бычьей свечи, -1 для медвежьей свечи, 0 для доджи;
- weight — отношение размера тела свечи к среднему размеру тела свечи.
Вклад каждой свечи равен dir * weight. Сильные бычьи свечи дают значительный положительный вклад; сильные медвежьи свечи — значительный отрицательный вклад. Слабые свечи вносят пропорционально меньший вклад.
Окончательное нормирование. Сумма всех вкладов делится на InpMpoLen * 2 и умножается на 100. Знаменатель соответствует максимально возможной сумме вкладов с учетом направления в нормальных условиях. Это позволяет привести результат к диапазону примерно от -100 до +100. Однако это исходное значение пока не подходит для непосредственного отображения. В нем много шума, и иногда оно может выходить за допустимые границы.
Сглаживание с помощью EMA и перенос состояния
После сохранения исходного значения MPO4 в буфере RawBuffer выполняется экспоненциальное сглаживание и подготавливаются буферы управления состоянием для обнаружения дивергенций. Это выполняется в едином цикле сразу после расчета исходного значения:
//--- Smoothing and Divergence Detection for(int i = limit; i < rates_total; i++) { // Apply EMA Smoothing if(i == 0) OscBuffer[i] = RawBuffer[i]; else OscBuffer[i] = (RawBuffer[i] * SmoothAlpha) + (OscBuffer[i-1] * (1.0 - SmoothAlpha)); // Inherit state from previous bar if(i > 0) { LastPivLowPriceBuffer[i] = LastPivLowPriceBuffer[i-1]; LastPivLowOscBuffer[i] = LastPivLowOscBuffer[i-1]; LastPivHighPriceBuffer[i]= LastPivHighPriceBuffer[i-1]; LastPivHighOscBuffer[i] = LastPivHighOscBuffer[i-1]; BullDivBuffer[i] = EMPTY_VALUE; BearDivBuffer[i] = EMPTY_VALUE; }
При сглаживании с помощью EMA используется значение SmoothAlpha, заранее вычисленное в OnInit(). Для первого бара берется исходное значение без сглаживания; для каждого последующего бара текущее исходное значение сочетается с предыдущим сглаженным значением. В результате формируются итоговые значения в буфере OscBuffer, которые будут отображаться в виде сплошной линии в окне индикатора.
Перенос состояния имеет не меньшее значение. Четыре буфера состояния — LastPivLowPriceBuffer, LastPivLowOscBuffer, LastPivHighPriceBuffer и LastPivHighOscBuffer — хранят значения цены и осциллятора в последних опорных точках. Копируя эти значения с предыдущего бара на следующий, мы обеспечиваем возможность выполнять сравнения для обнаружения дивергенций при любом индексе без просмотра истории в обратном направлении. Именно эта методика не дает индикатору перерисовываться и обеспечивает его стабильность от тика к тику.
Наконец, для каждого бара элементам буферов стрелок присваивается значение EMPTY_VALUE. Это гарантирует, что сигналы дивергенции будут появляться только на тех барах, где они обнаружены, и не будут ошибочно сохраняться.
На этом реализация расчета исходного значения MPO4 и сглаживания завершена. Линия осциллятора теперь готова к отображению, однако механизм обнаружения дивергенций — пожалуй, самая ценная функция индикатора — требует отдельной реализации. В следующем разделе мы рассмотрим теоретические основы обнаружения дивергенций, а затем реализуем лежащую в его основе логику обнаружения опорных точек.
Теория дивергенции и создание механизма обнаружения опорных точек
После успешного построения сглаженной линии осциллятора перейдем к важной области применения любого индикатора моментума — обнаружению дивергенций. Дивергенция возникает, когда цена достигает нового экстремума — более высокого максимума или более низкого минимума, — но осциллятор не подтверждает этот экстремум, формируя вместо этого менее выраженный пик или впадину. Такое отсутствие подтверждения часто свидетельствует об ослаблении моментума и возможном развороте.
Сначала необходимо разобраться в двух основных типах дивергенции, которые будет выявлять наш индикатор:
- Бычья дивергенция возникает, когда цена формирует более низкий минимум, а осциллятор — более высокий минимум. Это позволяет предположить, что давление продавцов ослабевает, несмотря на то что цена продолжает падать. Нисходящий моментум может иссякать, и вероятность разворота вверх становится все выше.
- Медвежья дивергенция возникает, когда цена формирует более высокий максимум, а осциллятор — более низкий максимум. Это указывает на то, что давление покупателей ослабевает, хотя цена продолжает расти. Восходящее движение может терять силу, и вслед за этим возможен разворот вниз.
Залог надежного обнаружения дивергенций — выявление достоверных опорных точек: значимых максимумов и минимумов как цены, так и осциллятора. Без надежного механизма обнаружения опорных точек индикатор будет выдавать ложные сигналы при каждом незначительном колебании.
Логика обнаружения опорных точек
Наш индикатор использует простой, но эффективный метод для выявления локальных экстремумов. Бар считается опорным минимумом, если значение осциллятора на нем ниже значений осциллятора на InpPivotLen ближайших барах слева и на InpPivotLen ближайших барах справа. Аналогичным образом, бар считается опорным максимумом, если значение осциллятора на нем выше значений на соседних барах.
В коде эта проверка реализована с помощью переменной pIdx, которая содержит индекс бара, проверяемого как потенциальная опорная точка. Обратите внимание: мы проверяем опорные точки на баре с индексом i - InpPivotLen, а не на текущем баре i. Такая задержка гарантирует, что после проверяемого бара будет достаточно баров для подтверждения локального экстремума:
// Check for Pivots (Evaluated at i - InpPivotLen to ensure both sides form completely) int pIdx = i - InpPivotLen; if(pIdx >= InpPivotLen) { bool isPivLow = true; bool isPivHigh = true; // Verify the pivot high/low for(int k = 1; k <= InpPivotLen; k++) { if(OscBuffer[pIdx] > OscBuffer[pIdx - k] || OscBuffer[pIdx] > OscBuffer[pIdx + k]) isPivLow = false; if(OscBuffer[pIdx] < OscBuffer[pIdx - k] || OscBuffer[pIdx] < OscBuffer[pIdx + k]) isPivHigh = false; }
Подробно разберем эту логику. Предположим, что InpPivotLen = 2. Для заданного pIdx цикл выполняет проверки при k = 1 и k = 2, сравнивая OscBuffer[pIdx] со значениями осциллятора на двух предшествующих и двух последующих барах. Если OscBuffer[pIdx] меньше всех этих соседних значений, переменная isPivLow сохраняет значение true, что означает обнаружение опорного минимума. И наоборот, если это значение больше всех соседних значений, переменная isPivHigh сохраняет значение true, что означает обнаружение опорного максимума.
Условие pIdx >= InpPivotLen предотвращает обращение к элементам массива с отрицательными индексами. Кроме того, проверка опорных точек при pIdx = i - InpPivotLen гарантирует, что к моменту обработки бара i после проверяемого бара pIdx будет не менее InpPivotLen баров. Это обеспечивает корректное подтверждение.
Отслеживание значений предыдущих опорных точек
Для обнаружения дивергенции необходимо сравнить текущую опорную точку с предыдущей опорной точкой того же типа. Следовательно, индикатор должен сохранять значения цены и осциллятора для последнего обнаруженного опорного минимума и последнего обнаруженного опорного максимума. Для этого используются четыре буфера состояния:
- LastPivLowPriceBuffer — хранит минимум цены на баре последнего опорного минимума;
- LastPivLowOscBuffer — хранит значение осциллятора на баре последнего опорного минимума;
- LastPivHighPriceBuffer — хранит максимум цены на баре последнего опорного максимума;
- LastPivHighOscBuffer — хранит значение осциллятора на баре последнего опорного максимума.
Значения этих буферов переносятся с бара на бар (как мы видели ранее в блоке наследования состояния), поэтому при любом индексе доступны значения последних достоверных опорных точек без пересчета истории.
Обнаружение бычьей дивергенции
При обнаружении нового опорного минимума индикатор сравнивает его с предыдущим опорным минимумом, сохраненным в буферах состояния. Условия бычьей дивергенции:
- минимум цены в новой опорной точке ниже минимума цены в предыдущей опорной точке (low[pIdx] < prevLowPrice);
- значение осциллятора в новой опорной точке выше значения осциллятора в предыдущем опорном минимуме (OscBuffer[pIdx] > prevLowOsc).
Если выполняются оба условия, то цена достигла более низкого минимума, но осциллятор сформировал более высокий минимум. Затем индикатор выводит стрелку, направленную вверх, чуть ниже линии осциллятора:
// Process Bullish Divergence if(isPivLow) { double prevLowPrice = LastPivLowPriceBuffer[pIdx - 1]; double prevLowOsc = LastPivLowOscBuffer[pIdx - 1]; if(low[pIdx] < prevLowPrice && OscBuffer[pIdx] > prevLowOsc) { BullDivBuffer[pIdx] = OscBuffer[pIdx] - 10.0; // Draw arrow just below the line } // Update state forward to current bar for(int j = pIdx; j <= i; j++) { LastPivLowPriceBuffer[j] = low[pIdx]; LastPivLowOscBuffer[j] = OscBuffer[pIdx]; } }
Как только обнаружен новый опорный минимум (независимо от того, возник ли при этом сигнал дивергенции), в элементы буферов состояния от индекса pIdx до текущего бара i записываются значения новой опорной точки. Это гарантирует, что на последующие бары будут переноситься значения правильной точки отсчета.
Стрелка размещается на уровне OscBuffer[pIdx] - 10.0, чуть ниже линии осциллятора, для большей наглядности. Величину смещения можно настроить с учетом типичного диапазона значений осциллятора (здесь значения MPO4 находятся в диапазоне от -30 до +30, поэтому смещение на 10 единиц обеспечивает достаточное расстояние между стрелкой и линией).
Обнаружение медвежьей дивергенции
Медвежья дивергенция обнаруживается по той же логике, что и бычья, но проверки выполняются для опорных максимумов. Условия следующие:
- максимум цены в новой опорной точке выше максимума цены в предыдущей опорной точке (high[pIdx] > prevHighPrice);
- значение осциллятора в новой опорной точке ниже значения осциллятора в предыдущем опорном максимуме (OscBuffer[pIdx] < prevHighOsc).
Когда эти условия выполняются, формируется сигнал медвежьей дивергенции, а над линией осциллятора размещается стрелка, направленная вниз:
// Process Bearish Divergence if(isPivHigh) { double prevHighPrice = LastPivHighPriceBuffer[pIdx - 1]; double prevHighOsc = LastPivHighOscBuffer[pIdx - 1]; if(high[pIdx] > prevHighPrice && OscBuffer[pIdx] < prevHighOsc) { BearDivBuffer[pIdx] = OscBuffer[pIdx] + 10.0; // Draw arrow just above the line } // Update state forward to current bar for(int j = pIdx; j <= i; j++) { LastPivHighPriceBuffer[j] = high[pIdx]; LastPivHighOscBuffer[j] = OscBuffer[pIdx]; } }
Стрелка размещается на уровне OscBuffer[pIdx] + 10.0, то есть над линией осциллятора. Для сравнения цен намеренно используются high[pIdx] и low[pIdx], а не close или open. Опорные максимумы определяются по самой высокой достигнутой цене, а опорные минимумы — по самой низкой. Для большинства трейдеров это стандартная практика при анализе дивергенций.
Важность задержки при проверке опорных точек
Мы сознательно решили проверять опорные точки при pIdx = i - InpPivotLen. Это создает фиксированную задержку: стрелка дивергенции появится только после того, как сформируется достаточно баров для подтверждения опорной точки. Без этой задержки индикатор перерисовывался бы: отмеченный сигнал мог бы исчезнуть, если новые бары опровергнут опорную точку.
В реальной торговле перерисовывающийся индикатор опасен, поскольку результаты тестирования на исторических данных вводят в заблуждение: при просмотре истории сигналы кажутся идеальными, но в реальном времени их качество ухудшается. Благодаря задержке подтверждения наш индикатор MPO4 выдает стабильные сигналы, которые можно использовать для принятия торговых решений. Трейдер может открыть сделку на баре подтвержденной опорной точки или на следующей свече, зная, что сигнал не исчезнет.
На этом реализация механизма обнаружения дивергенций завершена. Теперь индикатор выполняет полный расчет сглаженных значений осциллятора, определяет достоверные опорные точки и размещает неперерисовывающиеся стрелки бычьих и медвежьих дивергенций. В следующем разделе мы рассмотрим, как буферы управления состоянием обеспечивают согласованность данных на нескольких барах, а затем обсудим практическую интерпретацию сигналов.
Управление состоянием и архитектура без перерисовки
Теперь, когда механизм обнаружения дивергенций полностью реализован, необходимо рассмотреть два аспекта, повышающих эффективность индикатора: управление состоянием на нескольких барах и отсутствие перерисовки. Разобрав эти технические меры защиты, мы перейдем к практической интерпретации: как читать осциллятор, выявлять достоверные дивергенции и избегать типичных ошибок.
Наш индикатор использует четыре буфера, сохраняющих состояние и передающих значения на последующие бары:
LastPivLowPriceBuffer[] LastPivLowOscBuffer[] LastPivHighPriceBuffer[] LastPivHighOscBuffer[]
В этих массивах для каждого индекса бара хранятся данные последнего опорного минимума (цена и значение осциллятора) и последнего опорного максимума. Когда OnCalculate выполняется для нового бара i, сначала (после сглаживания) состояние копируется с бара i - 1 на бар i. Благодаря такому наследованию при анализе любого бара доступны данные последней достоверной опорной точки без просмотра истории в обратном направлении.
Почему бы просто не использовать глобальные переменные?
В режиме реального времени при обновлении тиков OnCalculate может вызываться несколько раз с обработкой одного и того же исторического бара. Если бы мы хранили значения только в одной паре глобальных переменных, при появлении новой опорной точки предыдущие значения терялись бы, что нарушало бы сравнения для обнаружения дивергенций. Благодаря сохранению истории для каждого бара индикатор работает корректно даже при пересчете отдельных диапазонов.
Неперерисовывающиеся сигналы дивергенции
Перерисовка происходит, когда индикатор изменяет сигнал на историческом баре после поступления новых данных. Для стрелок дивергенции это означало бы, что появившаяся стрелка затем исчезает или перемещается на другой бар по мере изменения рыночной ситуации. Перерисовка делает тестирование на исторических данных бесполезным, а реальную торговлю — опасной.
Индикатор предотвращает перерисовку благодаря двум архитектурным решениям:
- Задержка подтверждения опорной точки — мы проверяем опорные точки при pIdx = i - InpPivotLen, но никогда не проверяем текущий бар i. Это означает, что стрелка дивергенции отрисовывается только после появления не менее InpPivotLen баров после потенциальной опорной точки. К моменту появления стрелки соседние бары уже зафиксированы и не могут опровергнуть опорную точку. Платой за надежность становится небольшое запаздывание: сигналы появляются через несколько баров после фактической опорной точки.
- Буферы состояния никогда не обновляются в обратном направлении — при обнаружении новой опорной точки на баре pIdx цикл обновления проходит от pIdx до i по возрастанию индексов:
for(int j = pIdx; j <= i; j++) { LastPivLowPriceBuffer[j] = low[pIdx]; LastPivLowOscBuffer[j] = OscBuffer[pIdx]; }
При этом новое значение опорной точки записывается в элементы буферов для всех баров от индекса опорной точки до текущего бара. Важно, что этот цикл не изменяет данные баров с индексами меньше pIdx. Данные исторических баров до опорной точки остаются неизменными, благодаря чему сохраняются ранее обнаруженные дивергенции.
Практическая интерпретация осциллятора MPO4
Значения осциллятора MPO4 ограничены диапазоном примерно от -30 до +30, а центральная линия находится на уровне 0. Благодаря такому устройству он внешне похож на RSI или стохастический осциллятор, но смысл его показаний иной.
Зоны перекупленности и перепроданности
По умолчанию индикатор проводит горизонтальные линии на уровнях +30 (перекупленность) и -30 (перепроданность). Когда значение осциллятора поднимается выше +30, это означает, что взвешенное направленное давление последних свечей было выраженно бычьим: в периоде анализа преобладали бычьи свечи с большими телами. Это позволяет предположить, что рынок может быть перегрет и готов к коррекции, однако само по себе это не является сигналом к продаже. При сильном бычьем тренде значения осциллятора могут долго оставаться высокими. Напротив, значения ниже -30 свидетельствуют о чрезвычайно сильном давлении продавцов. Ожидание, пока осциллятор снова пересечет уровень -30 снизу вверх, может помочь выбрать подходящий момент для открытия позиций в условиях перепроданности.
Дивергенция как основной сигнал
Само значение осциллятора помогает оценить ситуацию, но наиболее ценным результатом работы индикатора являются стрелки дивергенции. Стрелка бычьей дивергенции, появляющаяся, когда осциллятор уже находится в зоне перепроданности, имеет большее значение, чем стрелка вблизи центральной линии. Аналогичным образом, медвежья дивергенция в зоне перекупленности является более надежным сигналом.
Выявление достоверных дивергенций:
- Контекст тренда — при явно выраженном нисходящем тренде бычья дивергенция может указывать лишь на краткосрочный отскок. На боковом рынке за дивергенциями часто следуют реальные развороты.
- Несколько таймфреймов — дивергенция на часовом графике является более значимым сигналом, если она сопровождается дивергенцией на четырехчасовом графике. Индикатор можно применять на любом таймфрейме.
- Дополнительные фильтры — трейдерам, принимающим решения по собственному усмотрению, подтверждение сигнала всплесками объема или уровнями поддержки и сопротивления помогает повысить уверенность в нем.
Распространенные ложные сигналы и способы их избежать
| Ложный сигнал | Почему это происходит | Как снизить риск |
|---|---|---|
| Дивергенция в период низкой волатильности. | Незначительные опорные экстремумы легко выявить, но они малозначимы. | Увеличьте значение InpPivotLen до 3 или более. |
| Дивергенция, которая сразу не отрабатывает. | Рынок продолжает двигаться в прежнем направлении. | Прежде чем действовать, дождитесь дополнительного подтверждения с помощью других методов технического анализа. |
| Несколько дивергенций подряд. | Значения осциллятора колеблются вблизи зоны опорного экстремума. | Торгуйте только по первой дивергенции; последующие часто не отрабатывают. |
Пример сценария
Рассмотрим пару EURUSD на часовом графике. Цена формирует минимум на уровне 1,0500, а осциллятор MPO4 показывает -28 (близко к зоне перепроданности). В течение следующих нескольких баров цена опускается до нового минимума на уровне 1,0480, но осциллятор достигает минимума на отметке -25 — это более высокий минимум. Стрелка бычьей дивергенции появляется через два бара после второго минимума.
Интерпретация: давление продавцов ослабло, несмотря на незначительное обновление ценового минимума. Трейдер, торгующий против тренда, может открыть длинную позицию со стоп-лоссом ниже 1,0480, рассчитывая на возврат цены в прежний диапазон. Изменение значения осциллятора с -28 до -25, при том что оно все еще остается отрицательным, сигнализирует об этом сдвиге.
Если бы, наоборот, осциллятор сформировал более низкий минимум (например, -32) на втором ценовом минимуме, дивергенции не было бы — давление продавцов по-прежнему усиливалось бы, и продажи могли бы продолжиться.
Пример на изображении

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

При переключении источника на RSI линия в окне индикатора выглядит более сглаженной, поскольку используется другой расчет.
Хотя оба индикатора используют одну и ту же схему обнаружения опорных точек и дивергенций, поведение базового осциллятора влияет на формирование дивергенций и время их появления. Оба индикатора можно использовать как взаимодополняющие инструменты; каждый из них может служить подтверждением на разных таймфреймах. Их эффективность зависит от настроек, и оценивать ее по приведенным выше изображениям нельзя.
Сам механизм обнаружения дивергенций зависит от осциллятора. Такая архитектура позволяет сравнить, как разные осцилляторы интерпретируют одну и ту же рыночную структуру при одинаковых правилах обнаружения дивергенций.
Ограничения и компромиссы при проектировании
Ни один индикатор не идеален, и MPO4 — не исключение. Для ответственного использования индикатора необходимо понимать его ограничения. Ниже приведены основные компромиссы, заложенные в архитектуру индикатора.
- Задержка между опорной точкой и сигналом — как уже объяснялось, индикатор выжидает InpPivotLen баров после появления потенциальной опорной точки, прежде чем отобразить стрелку дивергенции. Это устраняет перерисовку, но приводит к запаздыванию. На пятиминутном графике при InpPivotLen = 2 задержка составляет около 10 минут. На дневном графике задержка составляет два дня. Трейдерам, предпочитающим ранний вход в рынок, это может не понравиться; те же, кто ценит надежность, примут этот компромисс.
- Чувствительность к параметрам — длительность периода анализа (InpMpoLen) существенно меняет поведение осциллятора. При значении 6 MPO4 быстро реагирует на последние свечи, что делает его подходящим для краткосрочной торговли. При значении 14 или 21 линия осциллятора становится более сглаженной, а его реакция — более медленной. Он может пропускать быстро возникающие дивергенции, но при этом отфильтровывать шум. Универсально оптимальной настройки не существует; для каждого рынка и таймфрейма необходимо экспериментально подбирать и оптимизировать параметры.
- Ложная дивергенция на боковом рынке — при боковом движении с частыми колебаниями цена и осциллятор могут формировать множество незначительных опорных экстремумов, которые удовлетворяют математическим условиям дивергенции, но за ними так и не следует реального разворота. Индикатор будет выводить стрелку для каждого такого случая, перегружая график шумом. Использование большего значения InpPivotLen (например, 3 или 4) помогает, но не устраняет проблему. Трейдер может применять дополнительные технические фильтры.
Заключение
В осцилляторе MPO4 используется принципиально иной подход: направленное рыночное давление измеряется путем взвешивания размера тела каждой свечи относительно недавней волатильности. Исходя из основной идеи — крупные свечи, отражающие уверенное движение, должны влиять на осциллятор сильнее, чем мелкие свечи, отражающие нерешительность рынка, — мы вывели математические формулы, реализовали их на языке MQL5 для технического анализа, а затем добавили механизм обнаружения дивергенций для вывода сигналов.
Этот осциллятор относится к тому же семейству, что и RSI, однако его расчет на основе рыночного давления дает уникальное представление о рыночных настроениях. Стрелки дивергенции, выводимые этим индикатором, — это неперерисовывающиеся сигналы для принятия торговых решений, которые можно уверенно тестировать на исторических данных. MPO4 — ценный инструмент как для трейдера, принимающего решения по собственному усмотрению и ищущего ранние признаки разворота, так и для разработчика системных стратегий, которому нужен показатель моментума.
Советы по эффективному использованию MPO4 в торговле
- Применяйте индикатор на любом таймфрейме и для любого символа. Параметры по умолчанию: (MPO4 Len = 6, Smooth = 7 и Pivot Len = 2).
- Следите за стрелками дивергенции вблизи уровней перекупленности (+30) или перепроданности (-30). Бычья стрелка вблизи отметки -30 является более значимым сигналом, чем стрелка вблизи нуля.
- Игнорируйте одиночные стрелки на боковых рынках с низкой волатильностью. Используйте фильтр тренда для подтверждения возможных разворотов.
- Сочетайте индикатор с другими средствами анализа: уровнями поддержки и сопротивления, свечными паттернами или анализом объемов. Дивергенция — это скорее предупреждение, а не гарантия.
- Поэкспериментируйте с параметрами: большее значение InpMpoLen (10-14) — для более сглаженных трендов, меньшее (4-5) — для скальпинга. Увеличьте значение InpPivotLen до 3 или 4, чтобы уменьшить шум на рынках с частыми колебаниями.
- Автоматизируйте торговлю на основе этой идеи и оптимизируйте параметры.
Полный исходный код индикатора прилагается к этой статье. Скопируйте код в новый файл индикатора на языке MQL5, скомпилируйте индикатор и добавьте его на любой график, чтобы начать изучать расхождения между рыночным давлением и ценой. Перед использованием в реальной торговле тщательно протестируйте индикатор на демо-счете.
Если у вас есть вопросы или вы хотите поделиться своими доработками, присоединяйтесь к обсуждению в комментариях сообщества MQL5 под статьей.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/22341
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Нейронная сеть на практике: Вопрос шкалы
Альтернатива временным барам (Часть 1): Построение баров активности и дисбаланса в Python и MQL5
От начального к среднему уровню: Файл шаблона графика (I)
Перекрестный рекуррентный количественный анализ (CRQA) в MQL5: Разработка полноценной библиотеки анализа
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования