Complete .mq5 source code

VWAP Indicator MT5: MQL5 Custom VWAP Code, Usage & Download

Build a custom MT5 overlay using a bar-level volume-weighted average of typical price, with weighted deviation bands. The sample supports broker-calendar daily resets on intraday charts or continuous accumulation from loaded history. Its explicit tick/real-volume choice and update behavior are visible in the complete source.

How the indicator signal works

Calculation and signal conditions

Each chart bar contributes (high + low + close) / 3 with the selected volume weight. Weighted online mean and variance are recomputed from scratch on each callback, so updating a forming bar replaces its prior contribution rather than adding it repeatedly. Daily mode resets at broker-calendar midnight and withholds the first loaded date because its beginning may be truncated.

Interpretation and limitations

No trade entries, exits, alerts, stop placement or profitability test are implemented. Daily mode requires an intraday chart; continuous mode starts at the oldest loaded bar and is not anchored to a fixed date. The bands describe weighted bar-price dispersion, not a probability bound, transaction-price guarantee or institutional order-flow signal.

MQL5 Custom Indicator Code

#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 3
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_label1 "Weighted mean"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrangeRed
#property indicator_label2 "Upper weighted deviation"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrOrangeRed
#property indicator_label3 "Lower weighted deviation"
input double BandMultiplier=2;
input bool UseTickVolume=true; // Explicit source; no per-bar fallback or unit mixing.
input int LineWidth=2;
double meanLine[],upper[],lower[];
input bool ResetDaily=true; // Broker-calendar midnight, not an exchange calendar.
int OnInit()
{
   if(BandMultiplier<0 || LineWidth<1 || LineWidth>5 || (ResetDaily && PeriodSeconds(_Period)>=PeriodSeconds(PERIOD_D1)))
      return INIT_PARAMETERS_INCORRECT;
   SetIndexBuffer(0,meanLine,INDICATOR_DATA); SetIndexBuffer(1,upper,INDICATOR_DATA); SetIndexBuffer(2,lower,INDICATOR_DATA);
   ArraySetAsSeries(meanLine,false); ArraySetAsSeries(upper,false); ArraySetAsSeries(lower,false);
   for(int p=0;p<3;p++) { PlotIndexSetDouble(p,PLOT_EMPTY_VALUE,EMPTY_VALUE); PlotIndexSetInteger(p,PLOT_LINE_WIDTH,LineWidth); }
   IndicatorSetString(INDICATOR_SHORTNAME,"Bar-volume VWAP approximation");
   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[])
{
   ArraySetAsSeries(time,false); ArraySetAsSeries(high,false); ArraySetAsSeries(low,false); ArraySetAsSeries(close,false);
   ArraySetAsSeries(tick_volume,false); ArraySetAsSeries(volume,false);
   ArrayInitialize(meanLine,EMPTY_VALUE); ArrayInitialize(upper,EMPTY_VALUE); ArrayInitialize(lower,EMPTY_VALUE);
   double weight=0,mean=0,m2=0;
   datetime day=0;
   bool completeStart=!ResetDaily;
   for(int i=0;i<rates_total;i++)
   {
      datetime barDay=StringToTime(TimeToString(time[i],TIME_DATE));
      if(ResetDaily && barDay!=day)
      {
         // First loaded date can be truncated; withhold it until a date transition is observed.
         completeStart=(day!=0); day=barDay; weight=0; mean=0; m2=0;
      }
      double w=UseTickVolume?(double)tick_volume[i]:(double)volume[i];
      if(w>0)
      {
         double price=(high[i]+low[i]+close[i])/3.0,total=weight+w,delta=price-mean;
         mean+=w/total*delta; m2+=w*delta*(price-mean); weight=total;
      }
      if(weight<=0 || !completeStart) continue;
      double deviation=MathSqrt(MathMax(0,m2/weight));
      meanLine[i]=mean; upper[i]=mean+BandMultiplier*deviation; lower[i]=mean-BandMultiplier*deviation;
   }
   return rates_total;
}

Copy this code into MetaEditor, save it in the MQL5/Indicators folder, and compile with F7.

Change the settings or add your own signal filter

Describe the inputs, buffers, alerts, visual style, or confirmation filter you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionSeries evaluated on chart updatesEvent handlers with explicit buffers
DeploymentRuns in TradingView with alertsRuns in the MT5 terminal or on a VPS
Broker accessStrategy orders are simulated; live automation needs a separate integrationDirect broker connectivity
BacktestingStrategy Tester for strategy scriptsStrategy Tester for Expert Advisors
Code complexitySimpler, functional syntaxC++-like, more powerful

The calculation can be implemented on either platform, but the runtime model and buffer APIs differ. Read the Pine Script reference guide before porting logic between them.

Frequently Asked Questions

Related MQL5 pages

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.