Calculating last bar only

 

Hello,

I'm stuck with my new indicator because it is still not clear which is the current bar's value in the buffer array. Is it 0 or rates_total-1? I'm confused.

Here it the code of the OnCalculate() function, which displays two MAs. What I'd like to do is to get rid of the loop in order to show only the last bar's values. This is to save computing time. Whatever I try, the whole curve is displayed anyway when the indicator is loaded.

Thank you.

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[])
  {
//---

   int first;
   double SumLong,SumShort;
  
   if (rates_total < MALongPeriod - 1)
    return(0);

   if (prev_calculated == 0)
    first = MALongPeriod - 1 + ExtDepth;
   else first = prev_calculated - 1;
  
   for(int bar = first; bar <= rates_total-1; bar++)
    {
     SumLong = 0.0;
     for(int iii = 0; iii < MALongPeriod; iii++)
     {
         SumLong += close[bar - iii];
     }
    MALong[bar]=SumLong/MALongPeriod;
    if(MALong_Method==METHOD_EXPONENTIAL)
    {
       double div=MALongPeriod + 1;
       double weight=2 / div;
       if(bar>first)
       {
          MALong[bar] = (close[bar]- MALong[bar - 1]) * weight + MALong[bar -1];
       }
    }
        
//
     SumShort = 0.0;
     for(int iii = 0; iii < MAShortPeriod; iii++)
     {
         SumShort += close[bar - iii];
     }    
    MAShort[bar]=SumShort/MAShortPeriod; // 2*0.5
    if(MAShort_Method==METHOD_EXPONENTIAL)
    {
       double div=MAShortPeriod + 1;
       double weight=2 / div;
       if(bar>first)
       {
          MAShort[bar] = (close[bar]- MAShort[bar - 1]) * weight + MAShort[bar -1];
       }
    }  
    
    }      
//--- return value of prev_calculated for next call
   return(rates_total);
  }
 
Fred Metraux:

Hello,

I'm stuck with my new indicator because it is still not clear which is the current bar's value in the buffer array. Is it 0 or rates_total-1? I'm confused.


It depends if the array is set as series or not.

If yes, then current bar is 0. If not, then current bar is rates_total-1.

On mql4, arrays provided with OnCalculate() are set as series by default.

On mql5, the same arrays are set NOT as series by default. Use ArraySetAsSeries() to set the array indexing as you want.

 
Great. This explains also why I'm lost when translating MQL4 indis ;)
 
Fred Metraux: ... it is still not clear which is the current bar's value in the buffer array. Is it 0 or rates_total-1? I'm confused.

It depends on if you are setting the array as a Series or not - ArraySetAsSeries().

If setting it as a Series, then "0" is the current bar, if not then it is "rates_total - 1".

EDIT: Looks like my post took too long and Alain "beat me to the punch"!

 
Fernando Carreiro:

It depends on if you are setting the array as a Series or not - ArraySetAsSeries().

If setting it as a Series, then "0" is the current bar, if not then it is "rates_total - 1".

EDIT: Looks like my post took too long and Alain "beat me to the punch"!

 

Well, well... This helps, but I still have a small problem. I changed the code like this,


   //for(int bar = first; bar <= rates_total-1; bar++)
   for(int bar = (rates_total-1)- BarsToCalculate ; bar <= rates_total-1; bar++)

In order to display only a few bars.

And added this which will help the EA I guess.

   ArraySetAsSeries(MAShort,true);
   ArraySetAsSeries(MALong,true);


But how to avoid the blur at the beginning? I tried with PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,... But no success... I can live with it but this is not nice.


 
I got it. PLOT_DRAW_BEGIN counts from the first bar (the oldest), so it has to be put in the OnCalculate(), using (rates_total-1) - BarsToCalculate
 
Fred Metraux:
   ArraySetAsSeries(MAShort,true);
   ArraySetAsSeries(MALong,true);

When you change the order of arrays with ArraySetAsSeries(), you should follow through and do it for ALL arrays that are part of the calculations, such as the "close[]" or any of the other arrays passed down to OnCalculate() that you may be using.

I know Alain said that depending on MQL4 or MQL5 there are default values for the "Series", but I prefer setting them explicitly just to make sure and not run into problems (especially if you intend having common code that will work in both environments).

 

Right, I noticed fancy curves when reloading the indicator. And reverting the close[] array slowed down the chart. So better to leave it as is with

   ArraySetAsSeries(MAShort,false);
   ArraySetAsSeries(MALong,false);
Or do nothing.
 
Fernando Carreiro:

...

I know Alain said that depending on MQL4 or MQL5 there are default values for the "Series", but I prefer setting them explicitly just to make sure and not run into problems (especially if you intend having common code that will work in both environments).

You are right, and it's what is recommended by the documentation.
 
Fred Metraux:

Right, I noticed fancy curves when reloading the indicator. And reverting the close[] array slowed down the chart. So better to leave it as is with

   ArraySetAsSeries(MAShort,false);
   ArraySetAsSeries(MALong,false);
Or do nothing.
Changing indexing (Set as series or not) should not impact the performance. You probably have an other issue.