Реализация сессионного VWAP в MQL5: Пошаговое руководство

Реализация сессионного VWAP в MQL5: Пошаговое руководство MQL4 / MQL5 (MetaTrader)
Как написать индикатор VWAP с привязкой к азиатской, европейской и американской сессиям на MQL5. Полный код с расчетом среднеквадратического отклонения.
Суть: Реализация индикатора VWAP (Volume Weighted Average Price) на MQL5 с динамическим сбросом накопительных сумм (объема и взвешенной цены) в моменты начала азиатской, европейской и американской торговых сессий. Код включает расчет среднеквадратического отклонения для построения ценовых каналов (Standard Deviation Bands).

Исходный код

Приветствую, коллеги! Как Senior Quant Developer, я часто сталкиваюсь с необходимостью анализа внутридневной ликвидности. VWAP — это базовый инструмент институциональных трейдеров, показывающий справедливую стоимость актива с учетом объемов. Однако классический VWAP, рассчитываемый от начала суток, не учитывает специфику сессий. Привязка (anchoring) к открытию Лондона, Нью-Йорка или Токио позволяет точнее определять институциональный интерес.

Для фильтрации ложных пробоев границ VWAP рекомендую использовать Скрипт определения фазы рынка (Флэт/Тренд) на MQL5: ADX + Bollinger Bands, который поможет понять, стоит ли торговать на отскок от канала или ожидать импульсного выхода.

Ниже представлен оптимизированный код индикатора для MetaTrader 5. Он использует тиковые объемы (или реальные, если они транслируются брокером) и рассчитывает VWAP вместе с верхней и нижней границами среднеквадратического отклонения.

//+------------------------------------------------------------------+
//|                                         SessionAnchoredVWAP.mq5  |
//|                                  Copyright 2024, Quant Developer |
//+------------------------------------------------------------------+
#property copyright "Quant Developer"
#property link      "https://finfluct.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3

#property indicator_label1  "VWAP"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

#property indicator_label2  "Upper Band"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_DOT
#property indicator_width2  1

#property indicator_label3  "Lower Band"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrGreen
#property indicator_style3  STYLE_DOT
#property indicator_width3  1

input group "--- Session Settings (Server Time) ---"
input int InpAsiaHour = 0;      // Asian Session Start Hour
input int InpEuroHour = 8;      // European Session Start Hour
input int InpUSAHour  = 15;     // American Session Start Hour
input double InpDevMultiplier = 2.0; // StdDev Multiplier

double BufferVWAP[];
double BufferUpper[];
double BufferLower[];

int OnInit()
{
   SetIndexBuffer(0, BufferVWAP, INDICATOR_DATA);
   SetIndexBuffer(1, BufferUpper, INDICATOR_DATA);
   SetIndexBuffer(2, BufferLower, INDICATOR_DATA);

   IndicatorSetString(INDICATOR_SHORTNAME, "Session VWAP");
   return(INIT_SUCCEEDED);
}

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[])
{
   if(rates_total < 2) return 0;

   int limit = prev_calculated - 1;
   if(limit < 0) limit = 0;

   double sumPV = 0.0;
   double sumV = 0.0;
   double sumPV2 = 0.0;

   for(int i = limit; i < rates_total; i++)
   {
      bool isReset = false;
      if(i == 0)
      {
         isReset = true;
      }
      else
      {
         isReset = IsSessionReset(time[i], time[i-1]);
      }

      if(isReset)
      {
         sumPV = 0.0;
         sumV = 0.0;
         sumPV2 = 0.0;
      }

      double typicalPrice = (high[i] + low[i] + close[i]) / 3.0;
      double vol = (double)tick_volume[i];
      if(vol <= 0) vol = 1.0;

      sumPV += typicalPrice * vol;
      sumV += vol;
      sumPV2 += typicalPrice * typicalPrice * vol;

      if(sumV > 0)
      {
         BufferVWAP[i] = sumPV / sumV;
         double meanSquare = sumPV2 / sumV;
         double variance = meanSquare - (BufferVWAP[i] * BufferVWAP[i]);
         if(variance < 0) variance = 0;
         double stdDev = MathSqrt(variance);

         BufferUpper[i] = BufferVWAP[i] + InpDevMultiplier * stdDev;
         BufferLower[i] = BufferVWAP[i] - InpDevMultiplier * stdDev;
      }
      else
      {
         BufferVWAP[i] = EMPTY_VALUE;
         BufferUpper[i] = EMPTY_VALUE;
         BufferLower[i] = EMPTY_VALUE;
      }
   }

   return(rates_total);
}

bool IsSessionReset(datetime current, datetime previous)
{
   int hours[3] = {InpAsiaHour, InpEuroHour, InpUSAHour};

   for(int i = 0; i < 3; i++)
   {
      datetime currSessionStart = GetSessionStartToday(current, hours[i]);
      if(current >= currSessionStart && previous < currSessionStart)
      {
         return true;
      }
   }
   return false;
}

datetime GetSessionStartToday(datetime time, int hour)
{
   MqlDateTime dt;
   TimeToStruct(time, dt);
   dt.hour = hour;
   dt.min = 0;
   dt.sec = 0;
   return StructToTime(dt);
}

Разбор параметров

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

  • InpAsiaHour: Час начала азиатской сессии (по времени торгового сервера, обычно 0).
  • InpEuroHour: Час начала европейской сессии (обычно 8 или 9).
  • InpUSAHour: Час начала американской сессии (обычно 15 или 16).
  • InpDevMultiplier: Множитель стандартного отклонения для построения волатильного канала вокруг VWAP (по умолчанию 2.0).

Как запустить

1. Откройте MetaTrader 5 и нажмите клавиши F4 для запуска MetaEditor.

2. Создайте новый пользовательский индикатор (Файл -> Новый -> Пользовательский индикатор), назовите его SessionAnchoredVWAP.

3. Полностью замените сгенерированный шаблон кодом, представленным выше, и нажмите F7 для компиляции.

4. Перенесите индикатор из навигатора терминала на график нужного инструмента (рекомендуемые таймфреймы: M1, M5, M15).

При подходе цены к границам канала VWAP quant-трейдеры ищут паттерны разворота. Если вы открываете позицию на отскок от VWAP, критически важно правильно рассчитать объем сделки. Для этого отлично подойдет Расчет лота от свободной маржи в MQL4: Скрипт с автоокруглением (концепцию которого легко перенести на MQL5).

Для фиксации прибыли и сопровождения сделки вдоль тренда, сформированного крупным игроком от линии VWAP, используйте Трейлинг-стоп по фракталам Билла Вильямса в MQL5: Руководство. Это позволит забирать максимальные движения рынка, минимизируя ручное вмешательство.

Оцените статью
FinFluct