Исходный код
Приветствую, коллеги! Как 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: Руководство. Это позволит забирать максимальные движения рынка, минимизируя ручное вмешательство.




