Is it possible to work with live ticks in MQL5 indicators? - page 5

 
Fernando Carreiro #:

Yes, I am beginning to see that this may indeed be the case, and it also explains why the indicators stall/freeze so much during high impact news.

I suppose, maybe we could enhance the testing code even further.

But one thing is for sure, it is completely different than we have anticipated...

MQL stays a box of surprises...
 
phade #:

Hm ok, but I thought OnCalculate is per-bar data. I assumed that to gather tick data, we have to go back in time until after a bar (of minimum 1 minute) has occurred. Let me know if I'm mistaken here, and if so, I'd like to see a small example of a for loop capturing ticks in OnCalculate (nested for loop I'm guessing)

For an actual example, see my second test indicator code. It retrieves all ticks coming in on live markets.

Should give you an idea on how to get tick data as you require.
 
Dominik Egert #:
For an actual example, see my second test indicator code. It retrieves all ticks coming in on live markets.

Should give you an idea on how to get tick data as you require.

Thanks Dominik, I will take a look at this

 

@Dominik Egert was correct in his inital stament. It is called for all live tick.

This is my test. I tested with and without delay. Even when the chart freezes the result is the same.

//+------------------------------------------------------------------+
//|                                             OnCalculateCheck.mq5 |
//|                           Copyright 2023, Samuel Manoel De Souza |
//|                          https://www.mql5.com/en/users/samuelmnl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Samuel Manoel De Souza"
#property link      "https://www.mql5.com/en/users/samuelmnl"
#property version   "1.00"
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

//---
   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[])
  {
//---
   static int calls = 0, copied = 0;
   static datetime time_open = 0, time_close = 0;
   if(prev_calculated == 0)
     {
      calls = 0;
      time_open = 0;
      time_close = 0;
      copied = 0;
      Print("Test started.");
     }

   ArraySetAsSeries(time, true);
   if(time_open == 0 && rates_total - prev_calculated == 1)
     {
      time_open = time[0];
      Print("range start set to ", (string)time_open);
     }

   if(time_open == time[0])
      calls++;

   if(time_close == 0 && rates_total > 1 && time_open == time[1])
     {
      time_close = time[0];
      Print("range end set to ", (string)time_close);
     }

   if(time_close > 0 && copied <= 0)
     {
      MqlTick ticks[];
      copied = CopyTicksRange(_Symbol, ticks, COPY_TICKS_ALL, 1000 * (long)time_open, 1000 * (long)time_close);
      if(copied > 0)
        {
         while(copied > 0 && ticks[copied-1].time >= time_close)
            copied--;
         Print("In the period from  ", (string)time_open, " to ", (string)time_close,
               " the OnCalculate was called ", (string)calls, " times, and CopyTicksRanges copied ", (string)copied, " ticks.");
        }
     }
   
   uint tick_count = GetTickCount();
   while(GetTickCount() - tick_count < 10)
     {
      
     }
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Samuel Manoel De Souza #:

@Dominik Egert was correct in his inital stament. It is called for all live tick. i don't know for historical.

This is my test. I tested with and without delay. Event when the chart freezes the result is the same.

Actually, OnCalculate is only called by new ticks.

Even the initial run is first triggered by a tick arrival.

So you get the first live tick, then you calculate all historical periods in your loop, you return rates_total, then you get tick updates.

Even if you are not done with the history, and return a value lower than rates_total, your next call will be triggered only by a new tick arrival.

That's why I have the split calculations called step interval in my testing code, to show this. And to show how to make sure, the terminal does not complain about slow indicator calculations.
 
Dominik Egert #:
Actually, OnCalculate is only called by new ticks.

Even the initial run is first triggered by a tick arrival.

So you get the first live tick, then you calculate all historical periods in your loop, you return rates_total, then you get tick updates.

Even if you are not done with the history, and return a value lower than rates_total, your next call will be triggered only by a new tick arrival.

That's why I have the split calculations called step interval in my testing code, to show this. Andto show how to make sure, the terminal does not complain about slow indicator calculations.

yeah, i did edit my post. i remember it is called only once after in the initialization and for new ticks.

 
Samuel Manoel De Souza #:

@Dominik Egert was correct in his inital stament. It is called for all live tick.

This is my test. I tested with and without delay. Even when the chart freezes the result is the same.

More than 5,000 ticks in 1 minute, what symbol is that ?
 
Alain Verleyen #:
More than 5,000 ticks in 1 minute, what symbol is that ?

WINV23, exchange is B3 in Brazil.

 
Samuel Manoel De Souza #:
WINV23

I see, there is a tick on each transaction (BUY/SELL) with last/volume changes, which gives a lot more ticks than just change with Bid/Ask.

So depending of the indicator it could be useful to filter the ticks to avoid useless update.

 
CopyTicksRange(_Symbol, ticks, COPY_TICKS_ALL, 1000 * (long)time_open, 1000 * (long)time_close);


Why is it that we multiply 1000 by the time? I've seen this in other codebase codes as well and I'm confused about this

Reason: