-
while(TimeDay(Time[q]) == TimeDay(Time[p]) && !IsStopped())
You are accessing the Predefine array (Time), not the array (time) in OnCalculate.
-
In MT4, buffers and MT4 predefined arrays are all ordered AsSeries. There is a difference between the arrays passed to OnCalculate (e.g. low[]) and the MT4 predefined variables (e.g. Low[].) The passed arrays have no default direction, just like MT5.
To determine the indexing direction of time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[], call ArrayGetAsSeries(). In order not to depend on default values, you should unconditionally call the ArraySetAsSeries() function for those arrays, which are expected to work with.
Event Handling Functions - Functions - Language Basics - MQL4 ReferenceYou are accessing your buffers as non-series.
-
int limit = rates_total - prev_calculated; for(int i=0;i<limit;i++) for(int p=0;p<limit;p++)
You are computing all bars to up limit. Instead of limit to rates_total-1.
How to do your lookbacks correctly #9 — #14 & #19 (2016) - After the first run you loose the values of SumPrice/SumVol. You must restart to the beginning of the day on the next tick.
-
You are accessing the Predefine array (Time), not the array (time) in OnCalculate.
-
In MT4, buffers and MT4 predefined arrays are all ordered AsSeries. There is a difference between the arrays passed to OnCalculate (e.g. low[]) and the MT4 predefined variables (e.g. Low[].) The passed arrays have no default direction, just like MT5.
-
You are computing all bars to up limit. Instead of limit to rates_total-1.
How to do your lookbacks correctly #9 — #14 & #19 (2016) - After the first run you loose the values of SumPrice/SumVol. You must restart to the beginning of the day on the next tick.
Thanks for your reply. I am still horrendously confused.
The documentation states:
Access to Timeseries and Indicator Data
These are functions for working with timeseries and indicators. A timeseries differs from the usual data array by its reverse ordering - elements of timeseries are indexed from the end of an array to its begin (from the most recent data to the oldest ones).
In your post How to do your lookbacks correctly #9 you state:
This counts from low number (bar) to high number (bar) which is a Timeseries (as above).
Am I reading this wrong?
You understand it, you just are not using it.
You haven't set your OnCalculate arrays, predefined arrays, buffers, and loop to match. Is your loop oldest (0) to newest (rates_total-1) or the other way (as-series)? You are assuming the OnCalculate arrays direction.
You understand it, you just are not using it.
You haven't set your OnCalculate arrays, predefined arrays, buffers, and loop to match. Is your loop oldest (0) to newest (rates_total-1) or the other way (as-series)? You are assuming the OnCalculate arrays direction.
you didn't really answer my confusion - in your example you state it is not a Timeseries whereas the MQL4 docs say that counting from newest data (low bar number) to old data (highest bar number) IS a Timeseries??
4. After the first run you loose the values of SumPrice/SumVol. You must restart to the beginning of the day on the next tick. - sorry don't understand this.
Anyway, this is latest code with suggested implementations as far as I can understand. There is still the 'out of array range' error if I use all bars but not if I use limited bar number i.e 3000. It draws the indicator but it doesn't look right i.e straight lines here and there.
#property indicator_chart_window #property indicator_buffers 4 #property indicator_label1 "VWAP" #property indicator_color1 clrGreen #property indicator_color2 clrMagenta #property indicator_color3 clrBrown #property indicator_width1 2 #property indicator_width2 2 #property indicator_width3 2 input bool day = True; //Show Daily VWAP input bool week = True; //Show Weekly VWAP input bool month = True; //Show Monthly VWAP double DailyBuffer[]; double WeeklyBuffer[]; double MonthlyBuffer[]; double PriceBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0,DailyBuffer); SetIndexStyle(0,DRAW_LINE); SetIndexLabel(0,"Daily VWAP"); SetIndexBuffer(1,WeeklyBuffer); SetIndexStyle(1,DRAW_LINE); SetIndexLabel(1,"Weekly VWAP"); SetIndexBuffer(2,MonthlyBuffer); SetIndexStyle(2,DRAW_LINE); SetIndexLabel(2,"Monthly VWAP"); SetIndexBuffer(3,PriceBuffer,INDICATOR_CALCULATIONS); SetIndexStyle(3,DRAW_NONE); IndicatorSetInteger(INDICATOR_DIGITS,4); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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(prev_calculated==0) { ArrayInitialize(DailyBuffer,EMPTY_VALUE); ArrayInitialize(WeeklyBuffer,EMPTY_VALUE); ArrayInitialize(MonthlyBuffer,EMPTY_VALUE); ArrayInitialize(PriceBuffer,EMPTY_VALUE); } ArraySetAsSeries(DailyBuffer,True); ArraySetAsSeries(PriceBuffer,True); ArraySetAsSeries(tick_volume,True); ArraySetAsSeries(time,True); ArraySetAsSeries(close,True); ArraySetAsSeries(high,True); ArraySetAsSeries(low,True); int limit; PriceBuffer[0]=0.0; int nbars = 3000; limit = rates_total - MathMax(1,prev_calculated) - 1; double sumPrice,sumVol; //calculate price buffer for(int i=0;i<limit;i++)PriceBuffer[i]=NormalizeDouble((close[i]+high[i]+low[i])/3,2); // ---- CALCULATE DAILY VWAP --------------------------------------- int q=0; for(int p=0;p<limit;p++) { q=p; sumPrice=0; sumVol=0; while(TimeDay(time[q]) == TimeDay(time[p]) && !IsStopped()) { sumPrice += PriceBuffer[q]*tick_volume[q]; sumVol += (double)tick_volume[q]; q++; } if(sumVol != 0)DailyBuffer[p]= sumPrice/sumVol; else DailyBuffer[p]=EMPTY_VALUE; } return(rates_total -1); } //+------------------------------------------------------------------+
- sd59 #: you didn't really answer my confusion - in your example you state it is not a Timeseries whereas the MQL4 docs say that counting from newest data (low bar number) to old data (highest bar number) IS a Timeseries??
Correct, but are your arrays and loop accessing as timeseries or not?
ArraySetAsSeries(time,True); ArraySetAsSeries(close,True); ArraySetAsSeries(high,True); ArraySetAsSeries(low,True);
You have now, set the arrays as-timeseries matching buffers.
- sd59 #: 4. After the first run you loose the values of SumPrice/SumVol. You must restart to the beginning of the day on the next tick. - sorry don't understand this.
sumPrice=0; sumVol=0; while(TimeDay(time[q]) == TimeDay(time[p]) && !IsStopped()){ sumPrice += PriceBuffer[q]*tick_volume[q]; sumVol += (double)tick_volume[q]; q++; }
VWAP starts at the beginning of the day and increments has the day progresses. Now I see you are summing all bars of the current day. No problem. But you read backwards up to 24 hours. Therefor you get array exceeded.
How to do your lookbacks correctly #9 — #14 & #19 (2016)
-
Correct, but are your arrays and loop accessing as timeseries or not?
You have now, set the arrays as-timeseries matching buffers.
-
VWAP starts at the beginning of the day and increments has the day progresses. Now I see you are summing all bars of the current day. No problem. But you read backwards up to 24 hours. Therefor you get array exceeded.
How to do your lookbacks correctly #9 — #14 & #19 (2016)
1. Yes they appear to be.
2. I still do not understand this - TimeDay() returns the number of day i.e 1st, 2nd , 3rd etc; - whatever timeframe you have displayed simply compares bars on the same day - no hours or minutes included.
I put in a few Print statements (code below) + output
int limit; PriceBuffer[0]=0.0; int nbars = 3000; limit = rates_total - prev_calculated; //limit=nbars; double sumPrice,sumVol; Print("prev_calculated = ",prev_calculated); Print("limit = ",limit," ","rates_total = ",rates_total); //calculate price buffer for(int i=0;i<limit;i++)PriceBuffer[i]=NormalizeDouble((close[i]+high[i]+low[i])/3,2); // ---- CALCULATE DAILY VWAP --------------------------------------- Print("time araysize = ",ArraySize(time)); int q=0; for(int p=0;p<limit;p++) { q=p; sumPrice=0; sumVol=0; while(TimeDay(time[q]) == TimeDay(time[p]) && !IsStopped()) { sumPrice += PriceBuffer[q]*tick_volume[q]; sumVol += (double)tick_volume[q]; q++; } if(sumVol != 0)DailyBuffer[p]= sumPrice/sumVol; else DailyBuffer[p]=EMPTY_VALUE; } Print("prev_calculated = ",prev_calculated); return(rates_total -1); The 'array out of range' line is:while(TimeDay(time[q]) == TimeDay(time[p]) && !IsStopped())
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi guys,
I'm trying to produce a VWAP indicator over a daily time period using the 'OnCalculate' event handler as most still use the 'start()' version.
After many hours of struggling with this it works about 90%. The indicator does draw on the chart but I get an 'array out of range' error on this line of code:
Also, the indicator doesn't appear to update on a new candle.
I'm also trying to make it as fast as possible as down at the smaller timeframes where it is most useful there are a lot of iterations because of huge bar numbers.
i'd appreciate any help in optimising the code.
thank you
p.s I will add code for Weekly and Monthly lines later