Индикаторы MT4: три скользящие средние со всех таймфреймов
Переключаться между графиками, чтобы проверить, выше или ниже цены средняя H4, — занятие утомительное и располагающее к ошибкам. Вывести все три на один график несложно. Сложно правильно их прочитать.
Мультитаймфреймовая скользящая — не какой-то особый индикатор. Это обычная функция 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.
Как читать три средние и не перечитать
- Все три наклонены в одну сторону и выстроены по порядку — самое чистое трендовое состояние, какое дают скользящие. Оно же и самое редкое.
- Цена между H1 и H4 — никакой информации. Это состояние по умолчанию, и означает оно, что рынок не делает ничего, заслуживающего действий.
- D1 плоская, а H1 хлещет через неё — на дневках диапазон. Трендовая торговля на младшем таймфрейме здесь будет терять.
Скользящие запаздывают по построению, три скользящих запаздывают трижды. Их ценность в описании состояния, а не в определении разворотов.