Libraries: OnTickMulti - page 4

 
fxsaber #:

There will be no more ticks with the last known time.

The millisecond OnTimer ensures that all ticks prior to this timer event have elapsed. In other words, the ticks are up to date for all symbols.

If the concern is that a spy indicator might, for some technical reason, delay an ‘old’ tick and send it after a more recent one for a different instrument, then this is indeed a possibility. Otherwise, I don’t see any issues directly in the code.

I don’t think the timer guarantees anything beyond ensuring that all ticks have elapsed BEFORE the new ‘event’ (the time unit count). The timer operates in local time, whilst the timestamps in the ticks contain server time. Therefore, it is better not to rely on the timer for synchronising instruments.

 
Stanislav Korotky #:

Right, that’s acceptable for ticks, given the complexity of synchronisation, although we could introduce a millisecond timeframe and synchronise the ticks.

But the same applies to opening prices, even though the opening time is the same for all symbols.

And because of this behaviour, it is impossible to test a number of systems properly.

 

Demonstration of the problem.

#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // https://www.mql5.com/en/code/47647

#include <MT4Orders.mqh> // https://www.mql5.com/en/code/16006

input bool inTimer = false; // false – OnTick, true – OnTimer

ulong TimeMsc = TimeTradeServer() * 1000 + (inTimer && EventSetMillisecondTimer(1));

void PositionOpen()
{
  for (uint i = ArraySize(OnTickMultiObject.Symbols); (bool)i--;)
  {
    const string SymbName = OnTickMultiObject.Symbols[i];
    
    OrderSend(SymbName, OP_BUY, 1, SymbolInfoDouble(SymbName, SYMBOL_ASK), 0, 0, 0);
  }
}

void OnTimer()
{
  if (TimeMsc++ == 1759280400081) // 1 October 2025 01:00:00.081
    PositionOpen();
}

// Multi-character OnTick.
void OnTickMulti( const string &Symb, const uint &Index )
{  
  MqlTick Tick;
  
  if (!inTimer && SymbolInfoTick(Symb, Tick) && (Tick.time_msc == 1759280400081) && // 1 October 2025 01:00:00.081
      !OrdersTotal())
    PositionOpen();
}

The screenshot shows all the data required to reproduce the issue on MetaQuotes Demo. It is clearly visible that the ticks are not synchronised via OnTick, whereas they are synchronised via OnTimer (which is terribly slow).

 
fxsaber #:

With OnTick, the ticks are not synchronised, whereas with OnTimer (which is terribly slow), they are synchronised.

It seems the only way to speed up calculations in synchronised mode is to use a mathematical mode similar to EAToMath.


Alternatively, you could pre-save the data from a single pass to a file.

#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // https://www.mql5.com/en/code/47647

// Multi-character OnTick.
void OnTickMulti( const string &Symb, const uint &Index )
{  
  static MqlTick Ticks[];
  static const int Size = ArrayResize(Ticks, ArraySize(OnTickMultiObject.Symbols));  
  
  bool Res = SymbolInfoTick(Symb, Ticks[Index]);

  for (int i = 1; Res && (i < Size); i++)
    Res = (Ticks[i].time_msc == Ticks[i - 1].time_msc);
    
  if (Res)
    ArrayPrint(Ticks);  
}
2025.10.01 01:00:00                    [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
2025.10.01 01:00:00   [0] 2025.10.01 01:00:00 1.17345 1.17363 0.0000        0 1759280400081     134       0.00000
2025.10.01 01:00:00   [1] 2025.10.01 01:00:00 1.34417 1.34501 0.0000        0 1759280400081     134       0.00000
2025.10.01 01:00:00   [2] 2025.10.01 01:00:00 0.66103 0.66122 0.0000        0 1759280400081     134       0.00000
2025.10.01 06:07:02                    [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
2025.10.01 06:07:02   [0] 2025.10.01 06:07:02 1.17388 1.17390 0.0000        0 1759298822726     134       0.00000
2025.10.01 06:07:02   [1] 2025.10.01 06:07:02 1.34417 1.34422 0.0000        0 1759298822726     130       0.00000
2025.10.01 06:07:02   [2] 2025.10.01 06:07:02 0.65959 0.65967 0.0000        0 1759298822726     134       0.00000
2025.10.01 07:30:23                    [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
2025.10.01 07:30:23   [0] 2025.10.01 07:30:23 1.17467 1.17469 0.0000        0 1759303823965       4       0.00000
2025.10.01 07:30:23   [1] 2025.10.01 07:30:23 1.34486 1.34490 0.0000        0 1759303823965     134       0.00000
2025.10.01 07:30:23   [2] 2025.10.01 07:30:23 0.65970 0.65978 0.0000        0 1759303823965       4       0.00000

And in your expert advisor, use the data from this file for synchronisation in OnTick. It will work quickly and correctly.

Подробнее о способах ускорения оптимизации советников в MT5.
Подробнее о способах ускорения оптимизации советников в MT5.
  • 2025.09.02
  • www.mql5.com
Классификация советников. Все советники, запускаемые в Оптимизаторе, делятся на два типа. Торговые. Статистические: "обучение", обработка котировочных данных. Каждый из них тоже делится на два типа
 
fxsaber #:

Demonstration of the problem.

The screenshot shows all the data required to reproduce the issue on MetaQuotes Demo. It is clearly visible that the ticks are not synchronised via OnTick, whereas they are synchronised via OnTimer (which is terribly slow).

Well, you’ve used your own code with a trade entry condition using ==. As I mentioned above, the condition must be strictly >, without the equals sign. To execute synchronised trades at the latest prices known up to 01:00:00.081 on 1 October 2025 across all instruments, you must start monitoring ticks before that time; in other words, use a demonstration constant such as for example, >1759280400080. The logic needs to be modified for each algorithm – simply swapping one handler type for another won’t work.

PS. By ‘synchronisation’, I mean trading at the latest known prices. Synchronisation to the nearest millisecond would, of course, require additional checks, but the probability of such situations (where the millisecond ticks of different instruments coincide) is low, which means potential signals would be missed. I’m not sure that such synchronisation is of any practical interest.

 
Stanislav Korotky #:

To execute synchronised trades at the latest prices known up to 01:00:00 on 1 October 2025.081 across all instruments, you must start monitoring ticks before that time, i.e. take a demonstration constant such as >1759280400080.

I’d be happy to take a look at your implementation in the code.
 

The simplest way to synchronise is to create a set of the tick times for the characters being used.

It is difficult to achieve synchronisation on the fly, in a single pass.

The difficulty lies in the uncertainty of the delay. It is not known which symbol will be the master.

 
fxsaber #:
I’d be happy to take a look at your implementation in the code.

For a comprehensive test case, I’d need to understand the practical use case – are we trading only on ticks whose times match to the nearest millisecond?

For an artificial example involving a single trade at a predetermined moment with synchronised ticks across all instruments – one could devise an artificial optimal algorithm, but what’s the point?

 
Rorschach #:

But the opening prices are the same, even though the opening times are the same for all shares.

We need to clarify the problem. For opening prices, if the algorithm requires bars to be present for all symbols, we wait until iTime(,,0) matches for all symbols. With this approach, there is usually no logical problem for bars, because bars (even M1) are rarely missing; however, for seconds and finer time intervals, synchronisation gaps can be frequent. What should we do in such situations?

I believe that, in practice, synchronisation should be based on the presence of any price not older than a certain specified timeout, rather than strict equality of tick timestamps.

 
Stanislav Korotky #:

We need to clarify the task. Based on the opening prices, if the algorithm requires bars to be present for all symbols, we wait until iTime(,,0) matches for all symbols. With this approach, there is usually no logical problem with bars, because bars (even M1) are rarely missing

This refers to the tester mode using opening prices.

Stanislav Korotky #:
– for seconds and finer time intervals, synchronisation issues can be frequent. What should be done in such situations?

Use the last known value.