MQL5 processing model on historical bars

 
Hello dears,
I'm new with MQL5, and i was a professional pine  script coder.

Im sorry im relating pine concepts to MQL5, but i need to DEEPLY understand this language.

In pine, when the script runs, it starts processing from the far left bar to the far right bar and reach the current bar,

How is the processing model MQL5?
In what sequence/order does the bars proceed?


I couldn't find ANY article or discussion about this on the whole internet. Please help 🙏🙏
 
Mostafa: Hello dears, I'm new with MQL5, and i was a professional pine  script coder. Im sorry im relating pine concepts to MQL5, but i need to DEEPLY understand this language. In pine, when the script runs, its starts executing from the far left bar to the far right bar and reach the current bar, How is the execution model in MQL5? In what sequence/order does the bars proceed?
I couldn't find ANY article or discussion about this on the whole internet. Please help 🙏🙏

In MQL programs, there is no predetermined way in which it runs (in terms of the way you have described the PineScript concept). It simply runs like normal programs written in a similar architecture as C/C++ and other similar languages, but in MQL it is event driven instead of a "main" starting point.

It is up to your code to determine how it wishes to process the current and historical data.

The three main event handling functions are OnStart() for Scripts, OnCalculate() for indicators and OnTick() for EAs.

Documentation on MQL5: MQL5 programs / Program Running
Documentation on MQL5: MQL5 programs / Program Running
  • www.mql5.com
Program Running - MQL5 programs - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
Fernando Carreiro #:

In MQL programs, there is no predetermined way in which it runs (in terms of the way you have described the PineScript concept). It simply runs like normal programs written in a similar architecture as C/C++ and other similar languages, but in MQL it is event driven instead of a "main" starting point.

It is up to your code to determine how it wishes to process the current and historical data.

The three main event handling functions are OnStart() for Scripts, OnCalculate() for indicators and OnTick() for EAs.

Can you please give me small code example of how i can control the program to process from leftest to rightes candle?

 
Mostafa #: Can you please give me small code example of how i can control the program to process from leftest to rightes candle?

There are hundreds of examples of how to process the historical bar data for Indicators and EAs in the CodeBase.

Most indicators will process the data from oldest bars to newest bars, so search there for something similar to what you want to accomplish and then study the code.

 
Mostafa #:

Here is a small example for an indicator , with comments of what is going on .

To start it go to New>>CustomIndicator ,go through the wizard , and when you have the code in front of you select all and delete.

Paste the following inside and play around . 

Cheers and welcome .

#property version   "1.00"
#property indicator_separate_window //<<<<<WHERE IT DRAWS 
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Plot
#property indicator_label1  "Plot"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrWhite
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- indicator buffers
double         Plot[];

int OnInit()
  {
//--- indicator buffers mapping
   /*
   This instructs the program to handle the size of the array Plot[] automatically according to how many bars 
   exist on the chart (new or old)  
   */
   SetIndexBuffer(0,Plot,INDICATOR_DATA);
//---
  return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
  /*
  There are several ways to access data in mt5 
  Imagine for a second T is the total number of bars on the chart 
          in arrays you can access elements from [0] till [T-1]
  So for indicators the constant arrays provided above (in the function) are mapped :
          with [0]   being the oldest bar in time (the leftmost) and
          with [T-1] being the newest bar in time (or the live bar if the market is open)
          example : high[0] is the first bar's high
  But there are also the iSeries arrays to access data and are mapped : 
          with [T-1] being the oldest bar in time 
          with [0]   being the newest bar in time 
          example : iHigh(_Symbol,_Period,0)
  For this example let's use the arrays above 
  
  Now , in indicators you have the value rates_total which is self explanatory , it is the "T" value from above
        and 
        the prev_calculated value which tells you how many bars have been processed in the previous call 
  This is the reason we use the arrays above for the first example , we can conveniently know where to start 
       our processing since the prev_calculated can also be used to point to a position in these arrays since
       they are mapped from left[0] to right[T-1] (right[rates_total-1])
  So what do we need ? we need to run calculations from the last calculated bar -1 but we cannot go below zero in 
       the arrays index . 
       So our formula is :       
  */
  int from=(int)MathMax(0,prev_calculated-1);//so that we don't start from -1 
  /*
  what are we doing above ?
  the first time the OnCalculate runs it will have 0 as prev_calculated (prev_calculated = previously_calculated btw)
  so if we start from prev_calculated-1 we hit -1 . 
  We choose the biggest number , 0 , -1 => 0 so we will go through all the bars 
  and here is our loop
  */
  for(int i=from;i<rates_total;i++)
  {
  /*
  this will go from the leftmost bar to the rightmost bar , and 
  ,if we have calculated up to rates_total (i.e. rates_total==prev_calculated) we will 
   calculate (or update) the live bar because from is prev_calculated-1 and we loop until rates_total-1 (< instead of <=)
  So , let's do an easy a** calculation the high - low 
  We fill the buffer we are ploting directly in the same position 
  */
  Plot[i]=high[i]-low[i];
  
  }
//--- return value of prev_calculated for next call
  return(rates_total);
  }
//+------------------------------------------------------------------+

Also you may wonder about the following : "What happens to rates_total and prev_calculated when new data comes in ?"

it depends :

  • If a new bar forms live then the prev_calculated stays as it was , rates total increases by one ,so when you access oncalculate after the rates_total-prev_calculated = 1 
  • If the user scrolls back past your initial rates_total value (in bars) then prev_calculated becomes 0 again , and rates_total gets the new amount of bars
  • If the terminal gets data missing between the existing data in some place (sandwich) , this one i don't know (and it is not handled on the code above)
 
Reason: