Files
2026-03-15 22:55:57 +01:00

212 lines
7.2 KiB
Plaintext

//+------------------------------------------------------------------+
//| VWAP_Bands_Pro.mq5 |
//| Copyright 2026, xxxxxxxx|
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, xxxxxxxx"
#property version "2.00" // Bulletproof Sync & Gapped Drawing
#property description "VWAP with Volume-Weighted Standard Deviation Bands."
#property description "Bands only display for the Current Session."
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_plots 8
// Plot 1-2: VWAP (Odd/Even for Gapped Drawing)
#property indicator_label1 "VWAP"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrOrange
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_label2 ""
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrange
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
// Plot 3-4: Band 1 (+/-)
#property indicator_label3 "Upper Band 1"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrDodgerBlue
#property indicator_style3 STYLE_SOLID
#property indicator_label4 "Lower Band 1"
#property indicator_type4 DRAW_LINE
#property indicator_color4 clrDodgerBlue
#property indicator_style4 STYLE_SOLID
// Plot 5-6: Band 2 (+/-)
#property indicator_label5 "Upper Band 2"
#property indicator_type5 DRAW_LINE
#property indicator_color5 clrCoral
#property indicator_style5 STYLE_SOLID
#property indicator_label6 "Lower Band 2"
#property indicator_type6 DRAW_LINE
#property indicator_color6 clrCoral
#property indicator_style6 STYLE_SOLID
// Plot 7-8: Band 3 (+/-)
#property indicator_label7 "Upper Band 3"
#property indicator_type7 DRAW_LINE
#property indicator_color7 clrRed
#property indicator_style7 STYLE_SOLID
#property indicator_label8 "Lower Band 3"
#property indicator_type8 DRAW_LINE
#property indicator_color8 clrRed
#property indicator_style8 STYLE_SOLID
#include <MyIncludes\VWAP_Calculator.mqh>
//--- Input Parameters
input group "VWAP Settings"
input ENUM_VWAP_PERIOD InpResetPeriod = PERIOD_SESSION;
input ENUM_APPLIED_VOLUME InpVolumeType = VOLUME_TICK;
input int InpTzShift = 0; // Timezone shift (Hours)
input group "Bands Settings"
input double InpBand1Mult = 1.0;
input double InpBand2Mult = 2.0;
input double InpBand3Mult = 3.0;
//--- Buffers
double BufVWAP_Odd[];
double BufVWAP_Even[];
double BufUp1[], BufDn1[];
double BufUp2[], BufDn2[];
double BufUp3[], BufDn3[];
//--- Calculator
CVWAPCalculator *g_vwap;
//+------------------------------------------------------------------+
//| Init |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, BufVWAP_Odd, INDICATOR_DATA);
SetIndexBuffer(1, BufVWAP_Even, INDICATOR_DATA);
SetIndexBuffer(2, BufUp1, INDICATOR_DATA);
SetIndexBuffer(3, BufDn1, INDICATOR_DATA);
SetIndexBuffer(4, BufUp2, INDICATOR_DATA);
SetIndexBuffer(5, BufDn2, INDICATOR_DATA);
SetIndexBuffer(6, BufUp3, INDICATOR_DATA);
SetIndexBuffer(7, BufDn3, INDICATOR_DATA);
// Disable drawing for empty values (Crucial for gapped lines)
for(int i=0; i<8; i++)
PlotIndexSetDouble(i, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetString(1, PLOT_LABEL, "VWAP (Segment)");
g_vwap = new CVWAPCalculator();
if(!g_vwap.Init(InpResetPeriod, InpVolumeType, InpTzShift, true, 0))
return INIT_FAILED;
IndicatorSetString(INDICATOR_SHORTNAME, "VWAP Bands Pro");
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int r) { if(CheckPointer(g_vwap)==POINTER_DYNAMIC) delete g_vwap; }
//+------------------------------------------------------------------+
//| Calculate |
//+------------------------------------------------------------------+
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;
// 1. Run Original VWAP Calculator (Fills Odd/Even properly)
g_vwap.Calculate(rates_total, prev_calculated, time, open, high, low, close, tick_volume, volume, BufVWAP_Odd, BufVWAP_Even);
// 2. Find the Start of the Current Session
// We look backwards until the Odd/Even status flips.
int current_session_start = 0;
for(int i = rates_total - 1; i > 0; i--)
{
bool is_odd_now = (BufVWAP_Odd[i] != EMPTY_VALUE && BufVWAP_Odd[i] != 0);
bool is_odd_prev = (BufVWAP_Odd[i-1] != EMPTY_VALUE && BufVWAP_Odd[i-1] != 0);
if(is_odd_now != is_odd_prev)
{
current_session_start = i;
break;
}
}
// 3. Clear Old Bands if a New Session just started
static int prev_session_start = -1;
if(current_session_start != prev_session_start)
{
// Wipe everything before the current session to keep chart clean
for(int i = 0; i < current_session_start; i++)
{
BufUp1[i] = EMPTY_VALUE;
BufDn1[i] = EMPTY_VALUE;
BufUp2[i] = EMPTY_VALUE;
BufDn2[i] = EMPTY_VALUE;
BufUp3[i] = EMPTY_VALUE;
BufDn3[i] = EMPTY_VALUE;
}
prev_session_start = current_session_start;
}
// 4. Calculate Bands strictly for the Current Session
double cum_vol = 0;
double cum_tpv2 = 0;
// We always recalc the current session to guarantee mathematical purity
for(int i = current_session_start; i < rates_total; i++)
{
double tp = (high[i] + low[i] + close[i]) / 3.0;
double vol = (InpVolumeType == VOLUME_TICK) ? (double)tick_volume[i] : (double)volume[i];
if(vol < 1.0)
vol = 1.0;
cum_vol += vol;
cum_tpv2 += (tp * tp) * vol;
double vwap = (BufVWAP_Odd[i] != EMPTY_VALUE && BufVWAP_Odd[i] != 0) ? BufVWAP_Odd[i] : BufVWAP_Even[i];
if(cum_vol > 0 && vwap != EMPTY_VALUE && vwap != 0)
{
// Variance = E[P^2] - E[P]^2
double variance = (cum_tpv2 / cum_vol) - (vwap * vwap);
double stddev = (variance > 0) ? MathSqrt(variance) : 0.0;
BufUp1[i] = vwap + (InpBand1Mult * stddev);
BufDn1[i] = vwap - (InpBand1Mult * stddev);
BufUp2[i] = vwap + (InpBand2Mult * stddev);
BufDn2[i] = vwap - (InpBand2Mult * stddev);
BufUp3[i] = vwap + (InpBand3Mult * stddev);
BufDn3[i] = vwap - (InpBand3Mult * stddev);
}
else
{
BufUp1[i] = EMPTY_VALUE;
BufDn1[i] = EMPTY_VALUE;
BufUp2[i] = EMPTY_VALUE;
BufDn2[i] = EMPTY_VALUE;
BufUp3[i] = EMPTY_VALUE;
BufDn3[i] = EMPTY_VALUE;
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+