FXTAA English version

Индикаторы MT4: три скользящие средние со всех таймфреймов

Переключаться между графиками, чтобы проверить, выше или ниже цены средняя H4, — занятие утомительное и располагающее к ошибкам. Вывести все три на один график несложно. Сложно правильно их прочитать.

Обновлено: 2026-09-22

Мультитаймфреймовая скользящая — не какой-то особый индикатор. Это обычная функция iMA, вызванная с другим аргументом периода, плюс арифметика индексов, чтобы бары старшего таймфрейма совпали с барами вашего графика.

Основной вызов

Таймфрейм у iMA — второй аргумент. Передав PERIOD_H4, сидя на M15, вы получите среднюю H4: функции безразлично, с какого графика её вызвали.

double maH4 = iMA(Symbol(), PERIOD_H4, 50, 0, MODE_EMA, PRICE_CLOSE, shift);

Трудность в shift. На M15 бар номер 20 — это пять часов назад. На H4 это примерно бар 1. Передать индекс M15 в вызов H4 и ждать осмысленного ответа нельзя.

Пересчёт индекса

Переводом занимается iBarShift: передайте ему таймфрейм и метку времени, и он вернёт номер бара этого таймфрейма, содержащего указанный момент.

// EMA H1, H4 и D1 на любом графике, куда повешен индикатор
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 clrGoldenrod
#property indicator_color2 clrSteelBlue
#property indicator_color3 clrSeaGreen

input int MaPeriod  = 50;
input int MaMethod  = MODE_EMA;
input bool UseClosedBarsOnly = true;

double bufH1[], bufH4[], bufD1[];

int OnInit()
{
   SetIndexBuffer(0, bufH1); SetIndexLabel(0, "EMA H1");
   SetIndexBuffer(1, bufH4); SetIndexLabel(1, "EMA H4");
   SetIndexBuffer(2, bufD1); SetIndexLabel(2, "EMA D1");
   return(INIT_SUCCEEDED);
}

double MtfMA(int tf, datetime t)
{
   int shift = iBarShift(Symbol(), tf, t, false);
   if(shift < 0) return(EMPTY_VALUE);
   if(UseClosedBarsOnly) shift += 1;          // пропускаем формирующийся бар
   return(iMA(Symbol(), tf, MaPeriod, 0, MaMethod, PRICE_CLOSE, shift));
}

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[])
{
   int limit = rates_total - MathMax(prev_calculated - 1, 1);

   for(int i = 0; i < limit; i++)
   {
      datetime t = Time[i];
      bufH1[i] = MtfMA(PERIOD_H1, t);
      bufH4[i] = MtfMA(PERIOD_H4, t);
      bufD1[i] = MtfMA(PERIOD_D1, t);
   }
   return(rates_total);
}

Ловушка перерисовки

Вот ради чего нужен флаг UseClosedBarsOnly, и это главное в статье.

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

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

Глубина истории

iMA на D1 с периодом 50 требует пятидесяти дневных баров. Если терминал их не скачал, функция вернёт ноль, и линия уедет вниз графика. Откройте «Сервис» → «Архив котировок» и дайте данным загрузиться для каждого таймфрейма, на который ссылаетесь, а не только для того, который смотрите.

Сколько истории доступно — свойство сервера брокера, а не MT4. Одни серверы отдают годы минутных данных, другие агрессивно обрезают, и это тихо ломает индикаторы с длинными периодами на старших таймфреймах. Проверить стоит до того, как что-то на них построено; платформенная часть, включая инструменты и типы счетов, разобрана в этом обзоре RoboForex.

Как читать три средние и не перечитать

Скользящие запаздывают по построению, три скользящих запаздывают трижды. Их ценность в описании состояния, а не в определении разворотов.