Download MetaTrader 5

Contradictory information on IndicatorCounted()

To add comments, please log in or register
Nico
33
Nico  

I know this has been asked before, but it has never been clarified to my knowledge.

The manual states that IndicatorCounted() returns the amount of bars not changed after the indicator was launched most recently.

In most cases only the zero bar (current bar) is considered not to be counted, so IndicatorCounted() returns the number of bars minus 1. (I.e. all bars except for one is counted.)

However, there are some cases in which a tick is lost during program execution. When the bar is closed (its formation is done), this tick will not have been taken into account. That's why some people want to calculate the previous bar AND the current bar, in case the previous bar is erroneously formed due to a lost tick.

A solution to this problem, which even the "MQL reference" exemplifies, goes like this:

if(counted_bars>0) counted_bars--;

Now the previous bar will also be considered not counted. This solution (or a variant of it) is used in almost every custom indicator I've seen.

However, the MQL Book does something completely different:

The Book's example on how to build a custom indicator does not decrement counted_bars. In other words, the example only calculates the zero bar (current bar) and not the previous bar as well. It justifies this by stating that IndicatorCounted() does take into account the lost tick and therefore returns a number that is one less than what you would normally get. (I.e. it recognizes the previous bar as uncounted (changed) because the tick was ignored.)

If you run this in a custom indicator:

counted_bars = IndicatorCounted();
bars_to_count = Bars-counted_bars;
if(i>1)
{
   Alert("More than one bar will be counted: " , i);
}

... you will be alerted once every minute (in a 1-minute timeframe), i.e. after each formation of a bar. This reinforces the view that IndicatorCounted() does not consider the previous bar to be counted right after it is finished (wants to recount it). What's the point of decrementing counted_bars then, if IndicatorCounted() already does this for you? Please consider the image below:


Seems like you don't need to decrement counted_bars after all ...

So; what does IndicatorCounted() really do? Is the book correct, or are all the custom indicators and the MQL reference correct?

Ian Venner
2584
Ian Venner  

So it appears that when the first tick of a new bar appears, and gets the zero index, IndicatorCounted() is detecting both the new bar and also that something changed in the last bar. What could be changing in the last bar ?

Airat Safin
1300
Airat Safin  

Features of Custom Indicators Creation : https://www.mql5.com/en/articles/1497

...

  • The "IndicatorCounted" function allows to organize an economic calculation of an indicator. This function returns the amount of bars by the moment of the preceding launch of the indicator, i.e., the amount of bars having already been calculated (potentially, if there were no errors or early termination during the preceding launch) which do not need any recalculation. At reinitialization of the custom indicator or significant updating of history data, this amount will be automatically reset to 0.

  • Let us discuss one more example...

..

Author: MetaQuotes Software Corp."

Nico
33
Nico  

Thank you for replying.

SDC: Yes, it appears so. Let's say your EA sleeps through 3 ticks and therefore does not call your custom indicator. Suddenly a new bar is formed. Then you would obviously want to recalculate the previous bar (because it finished without evaluating the 3 ticks). But the testing I did indicates that IndicatorCounted() wants to recalculate the previous bar regardless.

Ais: Yes, IndicatorCounted() returns the amount of bars that don't need recalculation. But my question is why so many indicators decrement the amount of counted bars:

if(counted_bars>0) counted_bars--;

What's the point of this if IndicatorCounted() always considers the newly formed bar (index 1) as not counted right after a new bar is formed? Decrementing will only cause the indicator to recalculate yet another bar (i.e. index 0, 1 and 2).

Here's an example of decrementing counted_bars (if(i>0) CountedBars--;)

Do you understand my concern?

Counting three bars doesn't make sense to me. How could the third bar (index 2) ever be wrong? (unless the EA sleeps through a whole timeframe which isn't even possible.)

Airat Safin
1300
Airat Safin  

https://docs.mql4.com/customind/IndicatorCounted :

"int IndicatorCounted( )

The function returns the amount of bars not changed after the indicator had been launched last. The most calculated bars do not need any recalculation. In most cases, same count of index values do not need for recalculation. The function is used to optimize calculating.

Note: The latest bar is not considered to be calculated and, in the most cases, it is necessary to recalculate only this bar. However, there occur some boundary cases where custom indicator is called from the expert at the first tick of the new bar. It is possible that the last tick of the previous bar had not been processed (because the last-but-one tick was being processed when this last tick came), the custom indicator was not called and it was not calculated because of this. To avoid indicator calculation errors in such situations, the IndicatorCounted() function returns the count of bars minus one."

The events in 04:49:19 and 17:08:26 are representing such boundary case, as stated in Documentation, the first tick of the new bar.

In this case, on first tick of bar, IndicatorCounted() returns the count of bars minus one.

On the next ticks of the same bar IndicatorCounted() returns simply the count of bars, without "minus one".

Ian Venner
2584
Ian Venner  

I usually do my indicator loop this way:

   counted_bars=IndicatorCounted();
   limit=Bars-counted_bars-1;
   if(limit>MaxHistory-1) limit=MaxHistory-1;
   for(i=limit;i>=0;i--)

so I dont actually use

if(counted_bars>0) counted_bars--; 
Nico
33
Nico  

Ais: Thanks for replying. (I assume you meant "counted bars minus one" and "counted bars, without 'minus one'", because "the count of bars" refers to something else: the total amount of bars in the chart.)

This is how I understand it: At the first tick of a new bar, IndicatorCounted() returns the amount of counted bars minus one, not because the last tick of the previous bar had not been processed, but just in case it had not been processed. This is what my testing shows (referring to the two images I posted).

Do you understand it similarly? The documentation is obviously wrong, though, because "the count of bars minus one" is not worded correctly. It should be "the amount of counted bars minus one"

But the real question still remains: What is the point of this line:

if(counted_bars>0) counted_bars--; 

Almost every indicator I've seen uses this or something similar to it, including the IndicatorCounted() example from the documentation. However, the MQL Book does not do this.

SDC: Thanks for sharing. Your code is exactly how I would write it. You only count the bars that IndicatorCounted() labels as "not counted". Decrementing counted_bars would cause the indicator to count yet another old bar.

From the documentation: (comments by me)

                                     // Bars = 100
counted_bars = IndicatorCounted();   // counted_bars = 99
if(counted_bars>0) counted_bars--;   // counted_bars = 98
limit = Bars-counted_bars;           // limit = 2
for(i=0;i<limit;i++)
{
  // This will run TWICE (for Bar 0 and Bar 1)
}

Imagine what happens if IndicatorCounted() returns 98 instead of 99 (at the first tick of a new bar, as Ais pointed out). Then the 'for' loop would run three times; for Bar 0, Bar 1 and Bar 2. Unnecessary ... ?

Thanks again.

Airat Safin
1300
Airat Safin  

1.

https://docs.mql4.com/customind/IndicatorCounted :

"int IndicatorCounted( )

The function returns the amount of bars not changed after the indicator had been launched last."

Zero bar is always changing and always excluded from the count, and, consequently, we always have "minus one" in any case.

2.

https://docs.mql4.com/customind/IndicatorCounted :

"int IndicatorCounted( )

However, there occur some boundary cases where custom indicator is called from the expert at the first tick of the new bar. It is possible that the last tick of the previous bar had not been processed (because the last-but-one tick was being processed when this last tick came), the custom indicator was not called and it was not calculated because of this. To avoid indicator calculation errors in such situations, the IndicatorCounted() function returns the count of bars minus one.""

In this case, on first tick of bar, IndicatorCounted() returns the count of bars minus one, that is "minus one for this boundary case" and as always "minus one for the zero bar".

Minus one and minus one is equal to minus two.

3.

And if we use

counted_bars=IndicatorCounted();
if(counted_bars>0) counted_bars--; 

then in "counted_bars" we will have "minus ONE MORE one", that is up to minus three on the first tick of bar.

Ian Venner
2584
Ian Venner  

When I tested different ways of writing the loop and decided the code above was the most convenient I let it run with an alert to display the value of i.

i remains at 0 during the formation of a bar then changes to 1 at the first tick of a new bar so at that moment it re calculates the previous bar, it then returns to zero, therefore calculating the current bar, I never saw i change to 2 ...

Nico
33
Nico  

Ais, that is what I have been saying all along. You said: "then in "counted_bars" we will have "minus ONE MORE one", that is up to minus three on the first tick of bar."

I totally agree and I have been making this case since my first post. But why would you want "minus three"? Why would you count three bars? The third bar (index 2; third from the right) will never need to be recalculated, even if your EA sleeps through a whole bar. Only the second bar (index 1; second from the right) will need to be calculated in so-called "boundary cases". Why? As we have both pointed out countless times: IndicatorCounted() solves this problem for you. So I say you don't need to decrement counted_bars. It does it for you. Do you agree?

SDC: I'm not sure what code you are referring to. Could you please paste the code you have settled with and think is the most convenient?

counted_bars = IndicatorCounted();
bars_to_count = Bars - counted_bars;
Alert(bars_to_count);

Result:

13414, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1 ...

No decrementing needed, not matter how much your EA screws up.

Airat Safin
1300
Airat Safin  

"... I say you don't need to decrement counted_bars. It does it for you. Do you agree?"

Yes!

And, do you want to know a secret?

I never use "IndicatorCounted()" in my programs.

12
To add comments, please log in or register