Hello, I'm trying to create a exponential moving average on an array. I seem to get the correct values every time I refresh the chart, but not when I just let it run. The buyEMA returns 0.0 or an insanely high value, once I let it run. Below is my code snippet. I checked the buying_volume array, it never returns 0.0. The indicator seems to be working fine initially, but not when receiving new bars.. the buyEMA array is what im plotting on the chart.
What do I need to change so that, when running, it updates, and doesn't return 0.0 on new bars?
thank you for your time.
hey
when i run it on the tester like this its okay . also i don't think prev_calculated is an index but an amount
#property version "1.00" #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot ema #property indicator_label1 "ema" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 input int cumulation_length=14; //--- indicator buffers double buyEMA[]; int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,buyEMA,INDICATOR_DATA); //--- return(INIT_SUCCEEDED); } //------inside oncaculate function. using Calculations based on the current timeframe timeseries. //------seperate void CalculateBUYEMA(int rates_total,int prev_calculated,int begin,const double &price[]){ int i,start; double SmoothFactor=2.0/(1.0+cumulation_length); //first calculation or number of bars was changed if(prev_calculated==0){ start=cumulation_length+begin; buyEMA[begin]=price[begin]; for(i=begin+1; i<start; i++) buyEMA[i]=price[i]*SmoothFactor+buyEMA[i-1]*(1.0-SmoothFactor); } else start=prev_calculated-1; //main loop for(i=start; i<rates_total && !IsStopped(); i++) buyEMA[i]=price[i]*SmoothFactor+buyEMA[i-1]*(1.0-SmoothFactor); } 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[]) { CalculateBUYEMA(rates_total,prev_calculated,0,close); return(rates_total); }
It is difficult to debug your code when you don't share all of it.
For example- it could be that your problem is in the calculation of buying_volume and not in the code you've shared here.
Share all of your code mate.
hey
when i run it on the tester like this its okay . also i don't think prev_calculated is an index but an amount
It is difficult to debug your code when you don't share all of it.
For example- it could be that your problem is in the calculation of buying_volume and not in the code you've shared here.
Share all of your code mate.
Thank you for your time and response.
When I try to run the moving average using the close array it does look like its suppose to.. thanks for that. below is how I'm calculating the buying and selling volume values. I ArraySetAsSeries the close, high, open, low and tickvolume. And resized the upper/lower_wick, Cspread, body, percent_upper/lower/body and buying/selling volume by the rates_total.
for(int i=0; i<rates_total; i++){ upper_wick[i] = close[i]>open[i] ? high[i]-close[i] : high[i]-open[i]; lower_wick[i] = close[i]>open[i] ? open[i]-low[i] : close[i]-low[i]; Cspread[i] = high[i]-low[i]; body_length[i] = Cspread[i] - (upper_wick[i] + lower_wick[i]); percent_upper_wick[i] = upper_wick[i] / Cspread[i]; percent_lower_wick[i] = lower_wick[i] / Cspread[i]; percent_body_length[i] = body_length[i] / Cspread[i]; buying_volume[i] = close[i]>open[i] ? (percent_body_length[i] + (percent_upper_wick[i] + percent_lower_wick[i])/2)*tick_volume[i] : ((percent_upper_wick[i] + percent_lower_wick[i])/2) * tick_volume[i]; selling_volume[i] = close[i]<open[i] ? (percent_body_length[i] + (percent_upper_wick[i] + percent_lower_wick[i])/2)*tick_volume[i] : ((percent_upper_wick[i] + percent_lower_wick[i])/2) * tick_volume[i]; }
Again mate- share all of your code.
It is really difficult to debug it this way.
For example- you say that you SetAsSeries the close, high, open, low and tickvolume.
What about buying_volume? is this SetAsSeries or not?
What about buyEMA? is this SetAsSeries or not?
Share all of your code.
It will help others help you.
Again mate- share all of your code.
It is really difficult to debug it this way.
For example- you say that you SetAsSeries the close, high, open, low and tickvolume.
What about buying_volume? is this SetAsSeries or not?
What about buyEMA? is this SetAsSeries or not?
Share all of your code.
It will help others help you.
Again, thanks for your time, here is my full code.... I found that there is a build-in library called MovingAverages. Which is why I decided to use it for ease of use. The code inside that library is pretty much the same as my original for calculating the moving average. It now seems like the indicator isnt drawing the last 200 or so bars.
How would I make it so that it does draw the last bars? Thanks in advance.
//+------------------------------------------------------------------+ //| CumulativeVolume.mq5 | //| Copyright 2022, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <MovingAverages.mqh> //#property indicator_chart_window #property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 //--- plot cumulative_buying_volume #property indicator_label1 "buyEMA" #property indicator_type1 DRAW_LINE #property indicator_color1 clrGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 #property indicator_level1 0 //--- plot cumulative_selling_volume #property indicator_label2 "sellEMA" #property indicator_type2 DRAW_LINE #property indicator_color2 clrRed #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- input parameters input int cumulation_length = 12; //--- indicator buffers double upper_wick[], lower_wick[], Cspread[], percent_upper_wick[], percent_lower_wick[], percent_body_length[], body_length[], buying_volume[], selling_volume[], cumulative_volume_delta[]; double buyEMA[], sellEMA[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ //--- indicator buffers mapping SetIndexBuffer(0,buyEMA,INDICATOR_DATA); SetIndexBuffer(1,sellEMA,INDICATOR_DATA); 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[]){ //set price data arrays as series ArraySetAsSeries(close,true); ArraySetAsSeries(high,true); ArraySetAsSeries(open,true); ArraySetAsSeries(low,true); ArraySetAsSeries(tick_volume,true); //resize arrays ArrayResize(upper_wick,rates_total); ArrayResize(lower_wick,rates_total); ArrayResize(Cspread,rates_total); ArrayResize(body_length,rates_total); ArrayResize(percent_upper_wick,rates_total); ArrayResize(percent_lower_wick,rates_total); ArrayResize(percent_body_length,rates_total); ArrayResize(buying_volume,rates_total); ArrayResize(selling_volume,rates_total); ArrayResize(buyEMA,rates_total); ArrayResize(sellEMA,rates_total); //for loop to calculate the buying and selling volume val's for(int i=0; i<rates_total; i++){ upper_wick[i] = close[i]>open[i] ? high[i]-close[i] : high[i]-open[i]; lower_wick[i] = close[i]>open[i] ? open[i]-low[i] : close[i]-low[i]; Cspread[i] = high[i]-low[i]; body_length[i] = Cspread[i] - (upper_wick[i] + lower_wick[i]); percent_upper_wick[i] = upper_wick[i] / Cspread[i]; percent_lower_wick[i] = lower_wick[i] / Cspread[i]; percent_body_length[i] = body_length[i] / Cspread[i]; buying_volume[i] = close[i]>open[i] ? (percent_body_length[i] + (percent_upper_wick[i] + percent_lower_wick[i])/2)*tick_volume[i] : ((percent_upper_wick[i] + percent_lower_wick[i])/2) * tick_volume[i]; selling_volume[i] = close[i]<open[i] ? (percent_body_length[i] + (percent_upper_wick[i] + percent_lower_wick[i])/2)*tick_volume[i] : ((percent_upper_wick[i] + percent_lower_wick[i])/2) * tick_volume[i]; } //EMA on buffer ExponentialMAOnBuffer(rates_total,prev_calculated,0,cumulation_length,buying_volume,buyEMA); ExponentialMAOnBuffer(rates_total,prev_calculated,0,cumulation_length,selling_volume,sellEMA); return(rates_total); }
Just a couple of things I've noticed-
1) You shouldn't resize buyEMA and sellEMA as they are both buffers, so they are of dynamic size and resize automatically.
2) Every tick your are calculating all of the values again, which is really inefficient.
3) The use of arrays of upper_wick, lower_wick, Cspread, body_length, percent_upper_wick, percent_lower_wick and percent_body_length is redundant since you don't need to save their values, as only current values being used in calculations.
Regardless of the above 3 points-
When you've used your function you've had problem with last bar only,
And not that you've switched to using ExponentialMAOnBuffer you have problem with latest 200 bars?
Just a couple of things I've noticed-
1) You shouldn't resize buyEMA and sellEMA as they are both buffers, so they are of dynamic size and resize automatically.
2) Every tick your are calculating all of the values again, which is really inefficient.
3) The use of arrays of upper_wick, lower_wick, Cspread, body_length, percent_upper_wick, percent_lower_wick and percent_body_length is redundant since you don't need to save their values, as only current values being used in calculations.
Regardless of the above 3 points-
When you've used your function you've had problem with last bar only,
And not that you've switched to using ExponentialMAOnBuffer you have problem with latest 200 bars?
Hey, thank you for your response. Thanks for letting me know those 3 points. I've made some adjustments, commented below.
1) I Removed the ArrayResize for both functions.
2) I should have seen that one coming, I was planning on adding that later. Added per bar calculations now.
3) I don't see what I did wrong there, could you give me an example? I thought using the current way was necessary to calculate past values..
int ExponentialMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[])
yes. 44 bars now, to be exact. Used to be around 200.. The buyEMA and sellEMA = -9223372036854775.808 from bar 44 till 0.
Thank you for your time, it is much appreciated.
I think you needed to set the buyEMA , sellEMA the buying volume , selling volume , as buffers too and as series as well .
The code below uses a custom ema function -which also works on mt4- and the excellent observations of @AMI289 👍 👍 👍
#property version "1.00" #property indicator_separate_window #property indicator_buffers 4 #property indicator_plots 2 //--- plot cumulative_buying_volume #property indicator_label1 "buyEMA" #property indicator_type1 DRAW_LINE #property indicator_color1 clrGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 #property indicator_level1 0 //--- plot cumulative_selling_volume #property indicator_label2 "sellEMA" #property indicator_type2 DRAW_LINE #property indicator_color2 clrRed #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- input parameters input int cumulation_length = 12; //--- indicator buffers double upper_wick,lower_wick,Cspread,percent_upper_wick,percent_lower_wick,percent_body_length,body_length; double buying_volume[],selling_volume[]; double buyEMA[], sellEMA[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ //--- indicator buffers mapping SetIndexBuffer(0,buyEMA,INDICATOR_DATA); SetIndexBuffer(1,sellEMA,INDICATOR_DATA); SetIndexBuffer(2,buying_volume,INDICATOR_DATA); PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_NONE); SetIndexBuffer(3,selling_volume,INDICATOR_DATA); PlotIndexSetInteger(3,PLOT_DRAW_TYPE,DRAW_NONE); reset(); return(INIT_SUCCEEDED); } void reset(){ ArraySetAsSeries(buyEMA,true); ArraySetAsSeries(sellEMA,true); ArraySetAsSeries(buying_volume,true); ArraySetAsSeries(selling_volume,true); ArrayFill(buyEMA,0,ArraySize(buyEMA),0.0); ArrayFill(sellEMA,0,ArraySize(sellEMA),0.0); ArrayFill(buying_volume,0,ArraySize(buying_volume),0.0); ArrayFill(selling_volume,0,ArraySize(selling_volume),0.0); } //+------------------------------------------------------------------+ //| 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[]){ ArraySetAsSeries(close,true); ArraySetAsSeries(high,true); ArraySetAsSeries(open,true); ArraySetAsSeries(low,true); ArraySetAsSeries(tick_volume,true); int calcs=rates_total-prev_calculated; int from=calcs; if(calcs>cumulation_length){ from=rates_total-1-cumulation_length*2; reset(); } //for loop to calculate the buying and selling volume val's for(int i=from; i>=0; i--){ upper_wick = close[i]>open[i] ? high[i]-close[i] : high[i]-open[i]; lower_wick = close[i]>open[i] ? open[i]-low[i] : close[i]-low[i]; Cspread = high[i]-low[i]; body_length = Cspread - (upper_wick + lower_wick); percent_upper_wick = upper_wick / Cspread; percent_lower_wick = lower_wick / Cspread; percent_body_length = body_length / Cspread; buying_volume[i] = close[i]>open[i] ? (percent_body_length + (percent_upper_wick + percent_lower_wick)/2)*tick_volume[i] : ((percent_upper_wick + percent_lower_wick)/2) * tick_volume[i]; selling_volume[i] = close[i]<open[i] ? (percent_body_length + (percent_upper_wick + percent_lower_wick)/2)*tick_volume[i] : ((percent_upper_wick + percent_lower_wick)/2) * tick_volume[i]; buyEMA[i]=maOnArray(buying_volume,i,cumulation_length,MODE_EMA,true,(int)MathMin(1,prev_calculated),buyEMA[i+1]); sellEMA[i]=maOnArray(selling_volume,i,cumulation_length,MODE_EMA,true,(int)MathMin(1,prev_calculated),sellEMA[i+1]); } return(rates_total); } /* ma of array */ double maOnArray(const double &which_array[], int where,//start from where int period, ENUM_MA_METHOD mode, bool is_series, int calc_index,//this measures which calculation this is starting from 0 double previous_ma){//and this receives the previous value double result=0.0; //starting point int from=0; int step=0; int until=where; if(!is_series){ from=where-period+1; step=1; } else{ from=where+period-1; step=-1; } if(until>=0&&until<ArraySize(which_array)&&from>=0&&from<ArraySize(which_array)){ //sma or first ema or first smma if(mode==MODE_SMA||(mode==MODE_EMA&&calc_index==0)||(mode==MODE_SMMA&&calc_index==0)){ int i=from-step; while(i!=until) { i+=step; result+=which_array[i]; } result/=((double)period); } //ema non first else if(mode==MODE_EMA){ double w=2.00/((double)period+1.0); result=which_array[until]*w+previous_ma*(1-w); } //smma non first else if(mode==MODE_SMMA){ result=((previous_ma*((double)period))-previous_ma+which_array[until])/((double)period); } //lwma else if(mode==MODE_LWMA){ int i=from-step; double divider=0.0; int weight=0.0; while(i!=until) { i+=step; weight+=1.0; result+=which_array[i]*weight; divider+=weight; } result/=divider; } } return(result); }
Although Lorentzos Roussos did an awesome job providing his code modifications,
I don't think it will solve your problem.
I've noticed some cases where a candle's high and low were the same (perhaps because no ticks, or bad history data).
Anyway, I've re-written your code in a more clean and efficient way, and added some notes to explain some of the things I've did,
And I've also addressed the issue I've wrote above, that I believe that was the problem you were having.
Enjoy-
//+------------------------------------------------------------------+ //| CumulativeVolume.mq5 | //| Copyright 2022, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <MovingAverages.mqh> //#property indicator_chart_window #property indicator_separate_window #property indicator_buffers 4 #property indicator_plots 2 //--- plot cumulative_buying_volume #property indicator_label1 "buyEMA" #property indicator_type1 DRAW_LINE #property indicator_color1 clrGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 #property indicator_level1 0 //--- plot cumulative_selling_volume #property indicator_label2 "sellEMA" #property indicator_type2 DRAW_LINE #property indicator_color2 clrRed #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- input parameters input int cumulation_length = 12; //--- indicator buffers double buyEMA[], sellEMA[], buying_volume[], selling_volume[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ //--- indicator buffers mapping SetIndexBuffer(0,buyEMA,INDICATOR_DATA); SetIndexBuffer(1,sellEMA,INDICATOR_DATA); SetIndexBuffer(2,buying_volume,INDICATOR_CALCULATIONS); SetIndexBuffer(3,selling_volume,INDICATOR_CALCULATIONS); 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[]){ // Check if there is enough data for calculation if(rates_total < cumulation_length) return 0; // Check calculation loop start position // We use prev_calculated-1 to see 'live' indicator update on open candle int iStart = MathMax(0, prev_calculated-1); //for loop to calculate the buying and selling volume val's for(int i=iStart; i<rates_total; i++){ double upper_wick = close[i]>open[i] ? high[i]-close[i] : high[i]-open[i]; double lower_wick = close[i]>open[i] ? open[i]-low[i] : close[i]-low[i]; double Cspread = high[i]-low[i]; double body_length = Cspread - (upper_wick + lower_wick); // The below prevents zero division in case of high[i] being equal to low[i] // Due to no ticks within candle, or bad candle history if(Cspread == 0) { buying_volume[i] = buying_volume[i-1]; selling_volume[i] = selling_volume[i-1]; continue; } double percent_upper_wick = upper_wick / Cspread; double percent_lower_wick = lower_wick / Cspread; double percent_body_length = body_length / Cspread; buying_volume[i] = close[i]>open[i] ? (percent_body_length + (percent_upper_wick + percent_lower_wick)/2)*tick_volume[i] : ((percent_upper_wick + percent_lower_wick)/2) * tick_volume[i]; selling_volume[i] = close[i]<open[i] ? (percent_body_length + (percent_upper_wick + percent_lower_wick)/2)*tick_volume[i] : ((percent_upper_wick + percent_lower_wick)/2) * tick_volume[i]; } //EMA on buffer ExponentialMAOnBuffer(rates_total,prev_calculated,0,cumulation_length,buying_volume,buyEMA); ExponentialMAOnBuffer(rates_total,prev_calculated,0,cumulation_length,selling_volume,sellEMA); return(rates_total); }
3) I don't see what I did wrong there, could you give me an example? I thought using the current way was necessary to calculate past values..
You did nothing wrong.
You just did something that is useless.
Usually when you create arrays it is because you want to make use of several values.
For example- when calculating MA of price you are not only looking at current price, but you are also looking at previous prices, depends on the period of the MA.
In your code you have created several arrays to hold all of the values you've calculated, but you only used them one time, and then didn't need them anymore.
For example-
You've calculated upper_wick,
And then you used the current calculation of upper_wick for calculating percent_upper_wick,
But then you are done with upper_wick, and don't care anymore about its value.
Then you use percent_upper_wick to calculate buying/selling volume,
But then you are done with percent_upper_wick, and don't care anymore about its value.
So there is no need to save those values forever in arrays.

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hello, I'm trying to create a exponential moving average on an array. I seem to get the correct values every time I refresh the chart, but not when I just let it run. The buyEMA returns 0.0 or an insanely high value, once I let it run. Below is my code snippet. I checked the buying_volume array, it never returns 0.0. The indicator seems to be working fine initially, but not when receiving new bars.. the buyEMA array is what im plotting on the chart.
What do I need to change so that, when running, it updates, and doesn't return 0.0 on new bars?
thank you for your time.