Direction of OnCalculate() in MQL4 and MQL5

 

Hi,

thinking about being forced to switch from MQL4 to MQL5 I would like if someone can confirm this.

In MQL4:

int OnCalculate(const int rates_total, // oldest: time[rates_total-1] .. most recent: time[0]
                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[])
  {

As the 'new' (from MQL5) CopyRates() are ordered in the contrary direction (= the lower the index the older the time stamp) how is the order in OnCalculate() in MQL5:

a) rates_total has the oldest time stamp in MQL5-indicators - or

b) rates_total has the most recent time stamp (and 0 'points' to the oldest bar) - in MQL5-indicators.

 
Carl Schreiber: thinking about being forced to switch from MQL4 to MQL5 I would like if someone can confirm this.

In MQL4:

As the 'new' (from MQL5) CopyRates() are ordered in the contrary direction (= the lower the index the older the time stamp) how is the order in OnCalculate() in MQL5:

a) rates_total has the oldest time stamp in MQL5-indicators - or

b) rates_total has the most recent time stamp (and 0 'points' to the oldest bar) - in MQL5-indicators.

The order of the arrays open[], high[], etc. are different between the two, so I always set them explicitly, with ArraySetAsSeries(), to prevent any problems and so that the code is compatible to both versions.

If you have a look at that indicator I sent you some time back, you will see this, as my code compiles both on MQL4 and MQL5. You can use that as a reference to make your own code compile and run on both as well, instead of coding two separate versions.

 

Carl Schreiber:

a) rates_total has the oldest time stamp in MQL5-indicators - or

b) rates_total has the most recent time stamp (and 0 'points' to the oldest bar) - in MQL5-indicators.

  1. Rates_total is a count of bars, same as MT4's Bars in MT4. There is no timestamp.
  2. For the arrays, you must set the direction on how you will use them. The MT4 predefined arrays are still available as series, as is CopyRates.
  3. See How to do your lookbacks correctly.
 
whroeder1:
  1. Rates_total is a count of bars, same as MT4's Bars in MT4. There is no timestamp.
  2. For the arrays, you must set the direction on how you will use them. The MT4 predefined arrays are still available as series, as is CopyRates.
  3. See How to do your lookbacks correctly.

WHRoeder, I don't totally agree with you and just to be clear for the OP:

2. The MT4 predefined arrays are NOT available under MQL5!

3. The example code for Lookbacks provided, using Bars instead of rates_total is not considered correct in MQL5, not even in the modern MQL4+. One should always use rates_total with the OnCalculate() handler and there is no predefined Bars variable in MQL5.

 
Carl Schreiber: how is the order in OnCalculate() in MQL5?

Also, according to the documentation, and I quote:

Arrays passed as a parameter to the OnCalculate() function must be checked for the order of accessing the array elements by ArrayGetAsSeries().

... or set explicitly as I do it in my code, for example.
 

Hmm - let me ask the question again:

As in MQL4 and OnCalculate( ..., const datetime &time[], ...)

time[rates_total-1] is the oldest available time stamp and time[0] the most recent one

is in MQL5 as well time[rates_total-1] is the oldest available time stamp and time[0] the most recent one.

(I don't have a mt5 yet, so I cannot check that myself! And the example code of the help is in this case no help at all:

//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//--- bekommen die Anzahl der zugänglichen Bars für laufendes Symbol und laufende Periode auf dem Chart.    
   int bars=Bars(Symbol(),0);
   Print("Bars = ",bars,", rates_total = ",rates_total,", prev_calculated = ",prev_calculated);
   Print("time[0] = ",time[0]," time[rates_total-1] = ",time[rates_total-1]);
//--- return value of prev_calculated for next call
   return(rates_total);
;}
//+------------------------------------------------------------------+


)

It is only about how it is in MQL5 (MQL4 I can check myself!!).

PS: If I do know how this is treated I may not need the function call ArrayGetAsSeries() on each array and at every new tick
 
Carl Schreiber:

Hmm - let me ask the question again:

As in MQL4 and OnCalculate( ..., const datetime &time[], ...)

time[rates_total-1] is the oldest available time stamp and time[0] the most recent one

is in MQL5 as well time[rates_total-1] is the oldest available time stamp and time[0] the most recent one.

(I don't have a mt5 yet, so I cannot check that myself! And the example code of the help is in this case no help at all)

It is only about how it is in MQL5 (MQL4 I can check myself!!).

PS: If I do know how this is treated I may not need the function call ArrayGetAsSeries() on each array and at every new tick

As I usually "force" the order to be the way I want, I am not absolutely sure but believe that for OnCalculate() in MQL4, the default oldest index is [0] (i.e. defined as a non-series array) and in MQL5 the oldest index is [rates_total-1] (i.e. defined as a series array).

EDIT: Please see correct order as confirmed below by @honest_knave.

However, as posted before, you should never assume that, because it can change in future. So you should always check the series order in your code or force it into the order you want.

 
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[])
  {
   static bool HasRun=false;
   if(!HasRun)
     {
      printf("Default: time[0]=%s time[rates_total-1]=%s",
             TimeToString(time[0]),TimeToString(time[rates_total-1]));

      ArraySetAsSeries(time,true);
      printf("ArraySetAsSeries(true): time[0]=%s time[rates_total-1]=%s",
             TimeToString(time[0]),TimeToString(time[rates_total-1]));

      ArraySetAsSeries(time,false);
      printf("ArraySetAsSeries(false): time[0]=%s time[rates_total-1]=%s",
             TimeToString(time[0]),TimeToString(time[rates_total-1]));

      HasRun=true;
     }
   return(rates_total);
  }

In MT5:

 

In MT4:

 

Conclusion:

In MT5 default oldest index is [0]

In MT4 default oldest index is [rates_total-1]

 
Fernando Carreiro:

but believe that for OnCalculate() in MQL4, the default oldest index is [0] (i.e. defined as a non-series array) and in MQL5 the oldest index is [rates_total-1] (i.e. defined as a series array).

Other way around
 
honest_knave: Other way around
OK! Thank you for confirming that! As I said, I force the array order, so don't just use the default.
 
Fernando Carreiro:
As I said, I force the array order, so don't just use the default.
The best way, given MetaQuotes propensity for inconsistent default behaviour between platforms.
Reason: