Download MetaTrader 5

In MQL4 there was IndicatorCounted (), is there an equivalent function in MQL5 to access this value from anywhere in the program?

To add comments, please log in or register
Pierre Rougier
552
Pierre Rougier  

Hello,

In MQL4 there was IndicatorCounted () whose equivalent in MQL5 is prev_calculated.

But the big difference is that IndicatorCounted () is accessible from anywhere in the program, whereas prev_calculated is only accessible from the OnCalculate event.

Is there an equivalent function in MQL5 to access this value from anywhere in the program?

Regards,

Pierre8r

Jose Francisco Casado Fernandez
4644
Jose Francisco Casado Fernandez  
Try BarsCalculated().  Regards.
Documentation on MQL5: Timeseries and Indicators Access / BarsCalculated
Documentation on MQL5: Timeseries and Indicators Access / BarsCalculated
  • www.mql5.com
Timeseries and Indicators Access / BarsCalculated - Reference on algorithmic/automated trading language for MetaTrader 5
whroeder1
17063
whroeder1  
Pierre Rougier: whereas prev_calculated is only accessible from the OnCalculate event.
  1. So pass it to your functions or store it in a global. What's the problem?
  2. The real question is why do you think you need it. Do you loop in OnCalculate and pass the bar index to your functions. They shouldn't need to know anything else.
              How to do your lookbacks correctly.
Jose Francisco Casado Fernandez
4644
Jose Francisco Casado Fernandez  
whroeder1:
  1. So pass it to your functions or store it in a global. What's the problem?
  2. The real question is why do you think you need it. Do you loop in OnCalculate and pass the bar index to your functions. They shouldn't need to know anything else.
              How to do your lookbacks correctly.
Yes, but maybe he wants to use it inside OnTimer() or inside OnChartEvent(), and you cannot pass any aditional parameter to those functions. Maybe he wants to build a Multi-Symbol and/or Multi-Timeframe indicator.  Regards.
Fernando Carreiro
3952
Fernando Carreiro  
Jose Francisco Casado Fernandez: Yes, but maybe he wants to use it inside OnTimer() or inside OnChartEvent(), and you cannot pass any aditional parameter to those functions. Maybe he wants to build a Multi-Symbol and/or Multi-Timeframe indicator.  Regards.

That is why @whroeder1 also stated:  "So pass it to your functions or store it in a global ..."

// Untested, uncompiled example code

#property strict

...

int rates_total_global     = 0; // Globally Scoped copy of "rates_total" (if required)
int prev_calculated_global = 0; // Globally Scoped copy of "prev_calculated"

...

int OnCalculate (const int rates_total,      // size of the price[] array
                 const int prev_calculated,  // bars handled on a previous call
                 ... )
{
   rates_total_global     = rates_total;     // Update Global copy (if required)
   prev_calculated_global = prev_calculated; // Update Global copy

   ...

   // Update and Return currently processed/calculated bar count
   prev_calculated_global = rates_total;
   return( rates_total );
}

...

void OnTimer()
{
   ...

   // use "prev_calculated_global" or "rates_total_global" in expressions

   ...
}
Jose Francisco Casado Fernandez
4644
Jose Francisco Casado Fernandez  
Fernando Carreiro:

That is why @whroeder1 also stated:  "So pass it to your functions or store it in a global ..."

Yes, but again, if you want to calculate some indicator of another symbol or another timeframe different from the current chart, and you want to know how many bars have been calculated from that indicator, you should use BarsCalculated (). This function is universal and it is useful for all the cases that you may need (even to be able to be used within an EA or script), instead what @whroeder1 and you propose is only useful for the specific case in which you only want to calculate the bars returned on the previous call of OnCalculate() from the current indicator in the current symbol and current timeframe.


That's why I said that maybe he wanted to develop a MultiSymbol or MultiTimeframe indicator.


Regards.

Fernando Carreiro
3952
Fernando Carreiro  
Jose Francisco Casado Fernandez:

Yes, but again, if you want to calculate some indicator of another symbol or another timeframe different from the current chart, and you want to know how many bars have been calculated from that indicator, you should use BarsCalculated (). This function is universal and it is useful for all the cases that you may need (even to be able to be used within an EA or script), instead what @whroeder1 and you propose is only useful for the specific case in which you only want to calculate the bars returned on the previous call of OnCalculate() from the current indicator in the current symbol and current timeframe.

That's why I said that maybe he wanted to develop a MultiSymbol or MultiTimeframe indicator.

BarsCalculated() is useful with other indicators, but not within the indicator code itself as you cannot obtain an internal "handle" from within the Indicator code.

For the OP's question, as clearly stated that wanted an alternative for MQL4's IndicatorCounted() and in that respect the use of the global variable is exactly the solution as BarsCalculated() would not work in that situation.

IndicatorCounted - Custom Indicators - MQL4 Reference
IndicatorCounted - Custom Indicators - MQL4 Reference
  • docs.mql4.com
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.
Jose Francisco Casado Fernandez
4644
Jose Francisco Casado Fernandez  
Fernando Carreiro:

BarsCalculated() is useful with other indicators, but not within the indicator code itself as you cannot obtain an internal "handle" from within the Indicator code.

For the OP's question, as clearly stated that wanted an alternative for MQL4's IndicatorCounted() and in that respect the use of the global variable is exactly the solution as BarsCalculated() would not work in that situation.

OP asked what is the mql5 function equivalent to mql4 IndCounted(), and it is BarsCalculated(). The difference between the two is that IndCounted() can only be used based on the current indicator, and instead BarsCalculated() is universal and can be used referred to any indicator.

Regarding prev_calculated, it also exists in mql4, and obviously in mql5 it can be used in the same way as in mql4. There is no difference in this between one language and the other. 


Regards.

Fernando Carreiro
3952
Fernando Carreiro  
Jose Francisco Casado Fernandez: OP asked what is the mql5 function equivalent to mql4 IndCounted(), and it is BarsCalculated(). The difference between the two is that IndCounted() can only be used based on the current indicator, and instead BarsCalculated() is universal and can be used referred to any indicator. Regarding prev_calculated, it also exists in mql4, and obviously in mql5 it can be used in the same way as in mql4. There is no difference in this between one language and the other. 

No, it is NOT universal! It cannot be used within the Indicator itself in reference to itself. That is what IndicatorCounted() was for and which was then replaced by "prev_calculated" for both MQL4+ and MQL5. BarsCalculated() has its use, but it is NOT the MQL5 equivalent. Its purpose is something different. It is NOT the the substitute for IndicatorCounted() and I dare you to prove otherwise and there is no way you will ever be able to use BarsCalculated() to reference itself in an Indicator. It can only be used by way of reference of a handle of an externally implemented Indicator and NEVER within the the implementation code of the the Indicator itself.

IndicatorCounted - Custom Indicators - MQL4 Reference
IndicatorCounted - Custom Indicators - MQL4 Reference
  • docs.mql4.com
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.
Jose Francisco Casado Fernandez
4644
Jose Francisco Casado Fernandez  
Fernando Carreiro:

No, it is NOT universal! It cannot be used within the Indicator itself in reference to itself.


Why not ???.  For example, you can use ChartIndicatorGet() to retrieve the indicator's own handle, from within its own code. There are also other ways to do it.


Fernando Carreiro:
BarsCalculated() has its use, but it is NOT the MQL5 equivalent. Its purpose is something different. It is NOT the the substitute for IndicatorCounted() and I dare you to prove otherwise and there is no way you will ever be able to use BarsCalculated() to reference itself in an Indicator. It can only be used by way of reference of a handle of an externally implemented Indicator and NEVER within the the implementation code of the the Indicator itself.


The fact that you did not know how to do it,  does not mean that it is not possible.

Well, I did not plan to code, but since you challenged me, here's an example:


//+------------------------------------------------------------------+
//|                                          Bars Calculated Ind.mq5 |
//|                                Copyright 2017, Robertomar Trader |
//|         http://www.tradingunited.es/foro/members/robertomar.html |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Robertomar Trader"
#property link      "http://www.tradingunited.es/foro/members/robertomar.html"
#property version   "1.00"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Histogram
#property indicator_label1  "Histogram"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

input int      TimerLag  =  5;        //  Timer Lag (in milliseconds)

double         HistogramBuffer[];
string         shortname;
int            handle;
bool           timerok;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,HistogramBuffer,INDICATOR_DATA);
   shortname=MQLInfoString(MQL_PROGRAM_NAME) + "-" + IntegerToString(TimeCurrent());
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);
   timerok = false;
   ResetLastError();
   handle = ChartIndicatorGet(0, ChartWindowFind(), shortname);  
   if(handle == INVALID_HANDLE)  
   {
      Print("Unable to retrieve the own handle by itself.  Error code: ", GetLastError());
      return(INIT_FAILED);
   }
   
   Print("Own handle = ", handle);
   if(EventSetMillisecondTimer(TimerLag))  timerok = true;
   else  
   {
      Print("Unable to set Timer. Error code: ", GetLastError());
      return(INIT_FAILED);
   }
   
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   if(timerok)  EventKillTimer();
   if(handle != INVALID_HANDLE)     IndicatorRelease(handle);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,      
                 const int prev_calculated,  
                 const int begin,            
                 const double& price[])
  {
  
   int start=prev_calculated-1;
   if(start<0) start=0;

   for(int i=start;i<rates_total;i++)
     {
      HistogramBuffer[i]=price[i];
     }
   
   return(rates_total);
  }

void OnTimer()
{
   static int prev_calc = 0;
   int calc = BarsCalculated(handle);
 
   if(calc > prev_calc)
   {
     Print("Bars Calculated = ", calc, ", Prev Bars Calculated = ", prev_calc);
    
     double buffer[];
     ResetLastError();
     if(CopyBuffer(handle, 0, 1, 1, buffer) < 1)  { Print("Copybuffer failed.  Error code: ", GetLastError());     return;  }
     Print("CopyBuffer[1] = ", buffer[0]);
     prev_calc = calc;
   }
}


As you can see, the indicator can retrieve the handle of itself, and use the BarsCalculated() function with it, and it can also use the CopyBuffer() function to obtain its own values.

Imagine that we want the indicator to do something every time a new candle appears, and only once for each candle (for example, to print indicator values for the newly closed candle in the log). Well, this is the result:




As you can see, everything is correct, we have obtained what we wanted. For a better visual appreciation, I highlighted the printed data for each candle in a different color.


Now imagine that we want to do something similar with the method you proposed (store the values of rates_total and prev_calculated in global variables), and use them in another part of the code (inside the OnTimer () function, for example). For this we use an indicator similar to the previous one:


//+------------------------------------------------------------------+
//|                                   Prev Calculated Global Ind.mq5 |
//|                                Copyright 2017, Robertomar Trader |
//|         http://www.tradingunited.es/foro/members/robertomar.html |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Robertomar Trader"
#property link      "http://www.tradingunited.es/foro/members/robertomar.html"
#property version   "1.00"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Histogram
#property indicator_label1  "Histogram"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

input int      TimerLag  =  5;        //  Timer Lag (in milliseconds)

double         HistogramBuffer[];
string         shortname;
int            rates_total_global,  prev_calculated_global;
bool           timerok;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,HistogramBuffer,INDICATOR_DATA);
   shortname=MQLInfoString(MQL_PROGRAM_NAME) + "-" + IntegerToString(TimeCurrent());
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);  
   timerok = false; 
   if(EventSetMillisecondTimer(TimerLag))  timerok = true;
   else  
   {
      Print("Unable to set Timer. Error code: ", GetLastError());
      return(INIT_FAILED);
   }
   
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   if(timerok)   EventKillTimer();
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,      
                 const int prev_calculated,  
                 const int begin,            
                 const double& price[])
  {
  
   rates_total_global = rates_total;
   prev_calculated_global = prev_calculated;
  
   int start=prev_calculated-1;
   if(start<0) start=0;

   for(int i=start;i<rates_total;i++)
     {
      HistogramBuffer[i]=price[i];
     }
   
   /*  
   prev_calculated_global = rates_total;  
   
   If you put this here, the condition (if rates_total_global > prev_calculated_global) 
   inside Ontimer() is never fulfilled.  
   */
   return(rates_total);
  }

void OnTimer()
{
   if(rates_total_global > prev_calculated_global)
   {     
      Print("Rates total global = ", rates_total_global, ", Prev calculated global = ", prev_calculated_global);
      int size = ArraySize(HistogramBuffer);
      if(size >= 2)
      Print("Histogram Buffer[1] = ", HistogramBuffer[size-2]);
   }
}


First, from the code you showed above, I had to remove the line 'prev_calculated_global = rates_total;'  that was just above 'return (rates_total);',  because otherwise the condition configured inside OnTimer() was never fulfilled.

Removing this line, the condition is met, but not only once for each candle, but many times for each candle. Here are the results:




As you can see, inside OnTimer(), the condition 'if (rates_total_global > prev_calculated_global)'  is fulfilled many times for each candle (not all fit in the image). Therefore, with the method you proposed, we have not achieved the goal we wanted.

These are just examples. Prev_calculated is useful (I use it a lot) for normal indicators that only use the OnCalculate() function and only take into account the current symbol and timeframe candles. But storing these values in global variables and trying to use them in other functions handled by other events (such as OnTimer ()) can lead to desynchronization problems.
Depending on what you want to develop, one or the other is more appropriate.


Conclusions:

1. If you do not know something with certainty, please do not affirm categorically that it is not possible, that it is false, (do not use uppercase words such as NOT, NEVER, etc.), much less even challenge someone who does.

2. I said that BarsCalculated () is the equivalent (extended and universalized) of IndicatorCounted (), because both are functions (prev_calculated is not, but it is a variable of constant type passed to the function that handles the OnCalculate event), also because both can be used anywhere in the indicator code (which is what OP requested) and because they serve the same functionality, with the difference that BarCalculated () is universal and IndicatorCounted () could only be used from within the code of the indicator itself.
Exactly as I mentioned. This unique difference is motivated by the way in which the indicators are managed in MT5 (that is, by handles).

3. And yes, as you see, BarsCalculated() is universal, whereas prev_calculated is not the equivalent of IndicatorCounted(), but it is another way of doing things, initially implemented in mql5 and later incorporated also in mql4 (currently it exists and is used equally in both languages) and it has exactly the functionality that I mentioned.

4. I hope that today you have learned something, at least regarding your manners, which are not usually the most appropriate.



Regards.

Documentation on MQL5: Chart Operations / ChartIndicatorGet
Documentation on MQL5: Chart Operations / ChartIndicatorGet
  • www.mql5.com
INDICATOR_SHORTNAME property using the IndicatorSetString() function. It is recommended that a short name should contain the values of input parameters of the indicator, since the indicator is identified in the ChartIndicatorGet...
Fernando Carreiro
3952
Fernando Carreiro  

Jose Francisco Casado Fernandez: Why not ???.  For example, you can use ChartIndicatorGet() to retrieve the indicator's own handle, from within its own code. There are also other ways to do it.

The fact that you did not know how to do it,  does not mean that it is not possible.

Well, I did not plan to code, but since you challenged me, here's an example:

As you can see, the indicator can retrieve the handle of itself, and use the BarsCalculated() function with it, and it can also use the CopyBuffer() function to obtain its own values.

Imagine that we want the indicator to do something every time a new candle appears, and only once for each candle (for example, to print indicator values for the newly closed candle in the log). Well, this is the result:

As you can see, everything is correct, we have obtained what we wanted. For a better visual appreciation, I highlighted the printed data for each candle in a different color.

Now imagine that we want to do something similar with the method you proposed (store the values of rates_total and prev_calculated in global variables), and use them in another part of the code (inside the OnTimer () function, for example). For this we use an indicator similar to the previous one:

First, from the code you showed above, I had to remove the line 'prev_calculated_global = rates_total;'  that was just above 'return (rates_total);',  because otherwise the condition configured inside OnTimer() was never fulfilled.

Removing this line, the condition is met, but not only once for each candle, but many times for each candle. Here are the results:

As you can see, inside OnTimer(), the condition 'if (rates_total_global > prev_calculated_global)'  is fulfilled many times for each candle (not all fit in the image). Therefore, with the method you proposed, we have not achieved the goal we wanted.

These are just examples. Prev_calculated is useful (I use it a lot) for normal indicators that only use the OnCalculate() function and only take into account the current symbol and timeframe candles. But storing these values in global variables and trying to use them in other functions handled by other events (such as OnTimer ()) can lead to desynchronization problems.
Depending on what you want to develop, one or the other is more appropriate.

Conclusions:

1. If you do not know something with certainty, please do not affirm categorically that it is not possible, that it is false, (do not use uppercase words such as NOT, NEVER, etc.), much less even challenge someone who does.

2. I said that BarsCalculated () is the equivalent (extended and universalized) of IndicatorCounted (), because both are functions (prev_calculated is not, but it is a variable of constant type passed to the function that handles the OnCalculate event), also because both can be used anywhere in the indicator code (which is what OP requested) and because they serve the same functionality, with the difference that BarCalculated () is universal and IndicatorCounted () could only be used from within the code of the indicator itself.
Exactly as I mentioned. This unique difference is motivated by the way in which the indicators are managed in MT5 (that is, by handles).

3. And yes, as you see, BarsCalculated() is universal, whereas prev_calculated is not the equivalent of IndicatorCounted(), but it is another way of doing things, initially implemented in mql5 and later incorporated also in mql4 (currently it exists and is used equally in both languages) and it has exactly the functionality that I mentioned.

4. I hope that today you have learned something, at least regarding your forms, which are not usually the most appropriate.

I stand corrected!

EDIT: After looking at your code again and how you "invent" a unique shortname based on time, in order to circumvent the limitations of finding the the handle, I am reconsidering my previous comment.

Sorry, but I can no longer agree as I believe it to be a "forced hack" to get around the situation and I do not consider it a clear, efficient universal solution.

12
To add comments, please log in or register