IndicatorCounted() - let's clarify this once and for all

 

According to the description of the IndicatorCounted() function in the manual:


...To avoid indicator calculation errors in such situations, the IndicatorCounted() function returns the count of bars minus one.


The above is clear, then after this a code example follows:


//---- the last counted bar will be recounted

if(counted_bars>0) counted_bars--;


Why is the number of counted bars decremented (again) if it was done already in the above function?


In the same code a check for possible errors is done:


//---- check for possible errors

if(counted_bars<0) return(-1);


There is no explanation on what conditions an error can occur. To complicate things further, source code of some indicators that ship with MT4 use the above condition not to exit but to reset indicator buffers. Here is an example from Momentum.mq4:


/---- initial zero
if(counted_bars<1)
for(i=1;i<=MomPeriod;i++) MomBuffer[Bars-i]=0.0;


Is it necessary to reset indicator buffer(s) inside start() function when IndicatorCounted() < 1 (= 0) ? (I guess that the indicator code doesn't handle errors, but wants to reset buffers when IndicatorCounted() = 0 (on the first execution when no bars are counted), but since errors are not handled the initialization will also run when IndicatorCounted() < 0).


I want to better understand this rather than copy and paste other people's code. I'd really appreciate if someone could clarify the above. Thanks a lot!


Lukasz

 
lukasz74nj:

According to the description of the IndicatorCounted() function in the manual:


...To avoid indicator calculation errors in such situations, the IndicatorCounted() function returns the count of bars minus one.


The above is clear, then after this a code example follows:


//---- the last counted bar will be recounted

if(counted_bars>0) counted_bars--;


Why is the number of counted bars decremented (again) if it was done already in the above function?


See more detailed code from documentaion refference:

  //---- the last counted bar will be recounted
     if(counted_bars>0) counted_bars--;
     limit=Bars-counted_bars;
  //---- main loop
     for(int i=0; i<limit; i++)
       {
        //---- ma_shift set to 0 because SetIndexShift called abowe
        ExtBlueBuffer[i]=iMA(NULL,0,JawsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtRedBuffer[i]=iMA(NULL,0,TeethPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtLimeBuffer[i]=iMA(NULL,0,LipsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
       }
  //---- done
     return(0);
    }

You can rewrite it so:

  //---- the last counted bar will be recounted
     //if(counted_bars>0) counted_bars--;
     limit=Bars-counted_bars;
  //---- main loop
     for(int i=limit; i>=0; i--)
       {
        //---- ma_shift set to 0 because SetIndexShift called abowe
        ExtBlueBuffer[i]=iMA(NULL,0,JawsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtRedBuffer[i]=iMA(NULL,0,TeethPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
        ExtLimeBuffer[i]=iMA(NULL,0,LipsPeriod,0,MODE_SMMA,PRICE_MEDIAN,i);
       }
  //---- done
     return(0);
    }
 
lukasz74nj:


/---- initial zero
if(counted_bars<1)
for(i=1;i<=MomPeriod;i++) MomBuffer[Bars-i]=0.0;


Is it necessary to reset indicator buffer(s) inside start() function when IndicatorCounted() < 1 (= 0) ? (I guess that the indicator code doesn't handle errors, but wants to reset buffers when IndicatorCounted() = 0 (on the first execution when no bars are counted), but since errors are not handled the initialization will also run when IndicatorCounted() < 0).


Is it code from Momentum indicator? For first MomPeriod bars values are not calculated that's why we have to set epmty (zero) value.

 
Rosh wrote >>

See more detailed code from documentaion refference:

You can rewrite it so:

I think you meant:


for(int i=limit - 1; i>=0; i--)
       {

So I understand that decrementing this was intended for code clarity.

Now going back to Momentum, it is indeed not calculated for the first period bars, but this is taken care of by the following code:


if(Bars<=MomPeriod) return(0);


However, it is still not clear to me whether the below code is absolutely needed:


/---- initial zero
if(counted_bars<1)
for(i=1;i<=MomPeriod;i++) MomBuffer[Bars-i]=0.0;


What are the conditions when IndicatorCounted() returns 0 (counted_bars<1 above)?


I understand that it will be 0 when start() is called for the first time, and there is no need to reset the buffer as it was not used yet; the buffer could be zeroed explicitly (for code clarity) in the init(), correct?


Are there any other conditions where this function could return 0, except on the first execution of the start()?


Thanks,

Lukasz

 

What I also found is that the init() special function of an indicator that is attached to a chart window is not being called when the indicator code is recompiled. Is this indented or a bug? According to the manual:


init() is a function to be called during the module initialization. If it is not available, no function will be called at initialization.


For example, if we place the following code in the init():


SetIndexBuffer(3, buf3);
SetIndexStyle(3, DRAW_LINE, EMPTY, 2);


And recompile it while the indicator is attached to a chart window, the line width (set to 2 above) will be reset to the default value (1).


If we place the same code in the start() function and call it when (IndicatorCounted() = 0) the line width (2) will be maintained even after the code is recompiled:


This may explain why the code in the Momentum indicator resets the buffer in the start() function.


Rosh, can you please confirm that the proper way of coding this would be:


init() {

// this is probably redundant

resetIndicator()

}


start() {

if (IndicatorCounted() == 0) {

resetIndicator();

}

}


resetIndicator() {

a) zero indicator buffers

b) set styles for indicator buffers


// is both a) and b) needed, or b) would suffice?

}


Thanks,

Lukasz

 

What are the conditions when IndicatorCounted() returns 0 (counted_bars<1 above)?



If history changes IndicatorCounted() returns 0 (zero). For example, you attached an indicator to a chart and pressed key "Home" several times.

 
Why should we need to count the bar using IndicatorCounted() ? please explain  
 
Hari Hara #: Why should we need to count the bar using IndicatorCounted() ? please explain  

Read the documentation and study the examples.

However, that functionality it is outdated and decrepit. Use the newer MQL4+ OnCalculate() method instead, which is also mostly compatible with MQL5.

IndicatorCounted - Custom Indicators - MQL4 Reference
IndicatorCounted - Custom Indicators - MQL4 Reference
  • docs.mql4.com
IndicatorCounted - Custom Indicators - MQL4 Reference
 

prev_calculated only works if your code ends with return(rates_total);

prev_calculated is the MT5 equivalent of IndicatorCounted();  but either are okay to use in MT4.

 

maximo #: prev_calculated only works if your code ends with return(rates_total);

Wrong. It does not work at all. It is just a variable with whatever you previously returned. It is up to you to correctly handle what you previously returned.

Most examples return rates_total and thus have to check it on the next tick for first/previous run.

That is unnecessary if you return a correct value.
          How to do your lookbacks correctly #9 - #14 & #19 (2016)

 
William Roeder #:

Wrong. It does not work at all. It is just a variable with whatever you previously returned. It is up to you to correctly handle what you previously returned.

Most examples return rates_total and thus have to check it on the next tick for first/previous run.

That is unnecessary if you return a correct value.
          How to do your lookbacks correctly #9 - #14 & #19 (2016)

Why would Metatrader in any case use the following if " It does not work at all."  😆

int OnCalculate(const int prev_calculated,

int limit = (prev_calculated>0) ? rates_total-prev_calculated : rates_total-1;

 This alternative works for me also instead of the previous line.  Comments are meant as a reminder to the new names appropriated to older functions.

 int counted_bars=prev_calculated; //IndicatorCounted();  prev_calculated only works if code ends with return(rates_total) which=Bars as in number of historical bars available. 

Improperly formatted code corrected by moderator. Use the CODE (Alt-S) button.

Reason: