Индикатор дивергенции MACD для MT4
Дивергенция — одно из немногих понятий теханализа с механическим определением. Это делает её автоматизируемой, а слабости автоматизации конкретными, а не расплывчатыми.
Дивергенция означает, что цена и осциллятор расходятся в оценке силы движения. Цена обновляет максимум, осциллятор — нет. Трактовка: во втором рывке было меньше импульса.
MACD в MT4 — не классический MACD
На этом спотыкаются постоянно. У стандартного MACD три компонента: быстрая линия (EMA12 − EMA26), сигнальная (EMA9 от быстрой) и гистограмма их разности.
Встроенный индикатор MetaTrader 4 рисует быструю линию гистограммой, а сигнальную — линией. Гистограммы разности нет вовсе. Стратегия, написанная под классический MACD и применённая к версии MT4, читает не те числа, которые имел в виду автор.
| Буфер | Классический MACD | Встроенный в MT4 |
|---|---|---|
| MODE_MAIN | EMA12 − EMA26 (линия) | EMA12 − EMA26 (рисуется гистограммой) |
| MODE_SIGNAL | EMA9 от main (линия) | SMA9 от main (линия) |
| Гистограмма | main − signal | Отсутствует |
Нужно классическое поведение — считайте iMACD(...,MODE_MAIN,i) - iMACD(...,MODE_SIGNAL,i) самостоятельно. Не считайте, что картинка совпадает с тем, что вы читали в других источниках.
Поиск экстремумов
Поиск дивергенции сводится к нахождению двух вершин (или впадин) цены и сравнению осциллятора на тех же барах. Вся сложность — в слове «находить».
// Вершина: строго выше `depth` баров с каждой стороны
bool IsSwingHigh(int i, int depth)
{
for(int k = 1; k <= depth; k++)
if(High[i] <= High[i+k] || High[i] <= High[i-k]) return(false);
return(true);
}
// Ищем две последние подтверждённые вершины
int FindDivergence(int depth, int maxBars)
{
int found = 0, idx[2];
for(int i = depth; i < maxBars && found < 2; i++)
{
if(i - depth < 0) continue; // правая сторона = подтверждение
if(IsSwingHigh(i, depth)) { idx[found] = i; found++; }
}
if(found < 2) return(0);
int recent = idx[0], older = idx[1];
double pRecent = High[recent], pOlder = High[older];
double mRecent = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, recent);
double mOlder = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, older);
if(pRecent > pOlder && mRecent < mOlder) return(-1); // медвежья дивергенция
if(pRecent < pOlder && mRecent > mOlder) return(+1); // бычья (по минимумам)
return(0);
}
Почему подтверждение стоит `depth` баров
Вершина становится вершиной только когда справа сформировалось достаточно баров. При depth = 5 вы узнаёте о ней через пять баров после события. Это не недостаток кода — это определение.
Индикаторы, показывающие дивергенцию мгновенно, сообщают о неподтверждённых экстремумах, которые исчезают, когда следующий бар обновляет максимум. Это и есть перерисовка, и она — главная причина, по которой индикатор дивергенции идеален на истории и бесполезен в реальном времени.
Если индикатор никогда не показывает дивергенцию, которая потом пропадает, он либо ждёт подтверждения, либо врёт вам о прошлом.
Чего дивергенция не сообщает
- Времени. Она может сохраняться через несколько новых рывков. В сильном тренде появляется многократно и разрешается только в конце.
- Масштаба. Дивергенция перед откатом на десять пунктов и перед разворотом выглядят одинаково в момент обнаружения.
- Надёжного направления. Она сигнализирует об ослаблении импульса. Ослабление импульса часто предшествует продолжению после паузы.
Практическое применение — фильтр, а не триггер: не наращивать позицию против дивергенции, подтягивать стоп при её появлении, требовать её как одно из нескольких условий перед контртрендовым входом.
Скрытая дивергенция
Менее обсуждаемый вариант меняет сравнение местами: цена делает более высокий минимум, а осциллятор — более низкий. Читается как продолжение тренда, а не разворот, и срабатывает на откатах. Код тот же, со знаками неравенств наоборот.