What does LinearWeightedMAOnBuffer return? I doubt that it is array index.
//+------------------------------------------------------------------+ //| Linear weighted moving average on price array classic | //+------------------------------------------------------------------+ int LinearWeightedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[]) { //--- check period if(period<=1 || period>(rates_total-begin)) return(0); //--- save as_series flags bool as_series_price=ArrayGetAsSeries(price); bool as_series_buffer=ArrayGetAsSeries(buffer); ArraySetAsSeries(price,false); ArraySetAsSeries(buffer,false); //--- calculate start position int i,start_position; if(prev_calculated<=period+begin+2) // first calculation or number of bars was changed { //--- set empty value for first bars start_position=period+begin; for(i=0; i<start_position; i++) buffer[i]=0.0; } else start_position=prev_calculated-2; //--- calculate first visible value double sum=0.0,lsum=0.0; int l,weight=0; for(i=start_position-period,l=1; i<start_position; i++,l++) { sum +=price[i]*l; lsum +=price[i]; weight+=l; } buffer[start_position-1]=sum/weight; //--- main loop for(i=start_position; i<rates_total; i++) { sum =sum-lsum+price[i]*period; lsum =lsum-price[i-period]+price[i]; buffer[i]=sum/weight; } //--- restore as_series flags ArraySetAsSeries(price,as_series_price); ArraySetAsSeries(buffer,as_series_buffer); //--- return(rates_total); }
It returns rates_total. Also what I forgot to mention is that the problem persists with every MA method but only if they have src and dst buffer.
The begin parameter should be constant.
int on_calculate_result = LinearWeightedMAOnBuffer( rates_total, prev_calculated, InpMAPeriod+1, InpMAPeriod, VolumeBuffer, SmoothedVolumeBuffer);
Although I appreciate your advice, it would be more satisfying to have a source to back this up. I think the begin parameter is the only way not to calculate everything all over again. Because I am used to doing this:
int limit = prev_calculated; if(prev_calculated == rates_total) limit--; Copybuffer(xyzHandle,0,limit,rates_total,xyzBuffer);
It seemed right to use it similarly in the MAOnBuffer function, but may I also point you to the line
int start = (int)MathMax((double)InpMAPeriod+1, (double)limit);
where the begin at Period+1 has been taken into account in the start variable depending on which one is greater?
Update:
What does LinearWeightedMAOnBuffer return? I doubt that it is array index.
Although LinearWeightedMAOnBuffer does in fact return rates_total according to its function code, it seems not to return it every time or something. So instead of overcomplicating things and relying on it to do that, I just put the normal rates_total back in the OnCalculate return path so it is sure to return it everytime. And it does work now without flickering. But your advice lead me to try it out though, so thanks.
Something is still not right because the values drop to zero and stay there but I will find out why.
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { //--- Print(LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,Period,price,MABuffer)); //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Linear weighted moving average on price array classic | //+------------------------------------------------------------------+ int LinearWeightedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[]) { //--- check period if(period<=1 || period>(rates_total-begin)) return(0); //--- save as_series flags bool as_series_price=ArrayGetAsSeries(price); bool as_series_buffer=ArrayGetAsSeries(buf fer); ArraySetAsSeries(price,false); ArraySetAsSeries(buffer,false); //--- calculate start position int i,start_position,count; if(prev_calculated<=period+begin+2) // first calculation or number of bars was changed { //--- set empty value for first bars start_position=period+begin; for(i=0; i<start_position; i++) buffer[i]=0.0; } else start_position=prev_calculated-2; //--- calculate first visible value double sum=0.0,lsum=0.0; int l,weight=0; for(i=start_position-period,l=1; i<start_position; i++,l++) { sum +=price[i]*l; lsum +=price[i]; weight+=l; } buffer[start_position-1]=sum/weight; //--- main loop for(i=start_position,count=0; i<rates_total; i++,count++) { sum =sum-lsum+price[i]*period; lsum =lsum-price[i-period]+price[i]; buffer[i]=sum/weight; } //--- restore as_series flags ArraySetAsSeries(price,as_series_price); ArraySetAsSeries(buffer,as_series_buffer); //--- return(count); } //+------------------------------------------------------------------+ 2021.12.30 08:42:10.782 MA (EURUSD,H1) 100254 2021.12.30 08:42:15.221 MA (EURUSD,H1) 2 2021.12.30 08:42:15.314 MA (EURUSD,H1) 2 2021.12.30 08:42:27.537 MA (EURUSD,H1) 2 2021.12.30 08:42:27.624 MA (EURUSD,H1) 2
It's what this block is for:
if(prev_calculated<=period+begin+2) // first calculation or number of bars was changed { //--- set empty value for first bars start_position=period+begin; for(i=0; i<start_position; i++) buffer[i]=0.0; }
It's what this block is for:
if(prev_calculated<=period+begin+2) // first calculation or number of bars was changed { //--- set empty value for first bars start_position=period+begin; for(i=0; i<start_position; i++) buffer[i]=0.0; }
You are right, I unnecessarily fumbled around with the begin. It is only required when you put it on another indicator buffer that has also a period I guess.
Then inside LiniarWeightedMAOnBuffer() there is this preliminary condition right in the beginning:
//--- check period if(period<=1 || period>(rates_total-begin)) return(0);
I am not sure what it is good for but it returned zero instead of rates_total in my case. Now it seems to work.
As a little bonus if you are interested in a unified MAOnBuffer mqh where you can input the ENUM_MA_METHOD:
Happy New Year.
Wasn't aware of the function without the weight_sum parameter until it was posted above, as I've added a second parameter to avoid recalculating old prices every time.
int LinearWeightedMAOnBuffer(const int rates_total, const int prev_calculated, const int begin, const int period, const double& price[], double& buffer[], double& sum_price, int& sum_weight) { //--- check new bar bool newBar=rates_total!=prev_calculated; int i,k,limit=(newBar)?prev_calculated:prev_calculated-1; //--- save as_series flags bool as_series_price=ArrayGetAsSeries(price); bool as_series_buffer=ArrayGetAsSeries(buffer); if(as_series_price) ArraySetAsSeries(price,false); if(as_series_buffer) ArraySetAsSeries(buffer,false); //--- first calculation or number of bars has changed if(prev_calculated==0) { //--- check for data if(period<=1 || (limit=begin+period-1)>=rates_total) return(0); for(i=0;i<limit;i++) buffer[i]=EMPTY_VALUE; //--- calculate first visible value sum_price=sum_weight=0; for(i=begin,k=1;i<=limit;i++,k++) { sum_price+=k*price[i]; sum_weight+=k; } //--- set first value buffer[limit++]=sum_price/sum_weight; } //--- main loop for(i=limit;i<rates_total;i++) { //--- get price sum on new bar if(newBar) { sum_price=0; for(k=1;k<period;k++) sum_price+=price[i-period+k]*k; } //--- get last bar's value buffer[i]=(sum_price+price[i]*period)/sum_weight; } //--- restore as_series flags if(as_series_price) ArraySetAsSeries(price,true); if(as_series_buffer) ArraySetAsSeries(buffer,true); //--- return(rates_total); }
Happy new year to you too.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
It is just going off and on irregularly
On
Off
This uses the buffer function with a source and destination buffer rates_total and prev_calculated. The normal version where it calculates every indexing field one by one works fine. Is this problem commonly known? Thanks for your help.