MT5 и скорость в боевом исполнении - страница 48

 
fxsaber:

Print и Alert не асинхронные?

Захотел эти функции сделать асинхронными. Попробовал реализацию через ChartEvent - работает. Но тормозит. Откопалось это.

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

void OnTick()
{
  _B(EventChartCustom(ChartFirst(), 123, 0, 0, NULL), 1);
}


2020.10.07 12:38:04.579 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 100 mсs.
2020.10.07 12:38:06.842 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 170 mсs.
2020.10.07 12:38:07.924 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 765 mсs.
2020.10.07 12:38:08.359 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 377 mсs.
2020.10.07 12:38:09.246 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 66 mсs.
2020.10.07 12:38:14.645 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 692 mсs.
2020.10.07 12:38:14.729 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 6427 mсs.
2020.10.07 12:38:15.140 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 479 mсs.
2020.10.07 12:38:15.222 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 125 mсs.
2020.10.07 12:38:15.373 Alert: Time[Test9.mq5 5 in OnTick: EventChartCustom(ChartFirst(),123,0,0,NULL)] = 606 mсs.


Отказался от столь дорогой функции в критических местах. EventChartCustom - дорогая.


На тему Alert.

Пока точно можно сказать, что Алертить в критических местах нельзя. Нужна асинхронность.

 

Воспроизвел тормоза SymbolInfoTick. И никакого стресс-теста. Практическая нужда заставляет так писать.

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

// Возвращает время Обзора рынка в миллисекундах.
long TimeCurrentMsc()
{
  long Res = 0;
  
  MqlTick Tick;
  
  for (int i = SymbolsTotal(true); i >= 0; i--) 
  {
    const string Symb = SymbolName(i, true);
    
    if (_B(SymbolInfoTick(Symb, Tick), 10) && (Tick.time_msc > Res))
      Res = Tick.time_msc;
  }

  return(Res);
}

void OnTick()
{ 
  TimeCurrentMsc();
}


Следуем этой инструкции для быстрого воспроизведения.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Синхронный OrderSend сообщает об успешном выполнении быстрее, чем пинг до торгового сервера

fxsaber, 2020.09.30 20:36

  1. Открыть демо-счет на RannForex-Server.
  2. В обзоре рынка открыть Forex-символы и разрешить автоторговлю.
  3. На одном чарте запустить этот советник.
  4. Кинуть на этот же чарт этот скрипт - клонирует советник на другие символы. Запускал с inAmount = 15.
  5. Ждать такие сообщения и смотреть лог.


На быстрой машине результат с 30 символами в Обзоре рынка.

2020.10.07 13:28:01.931 Test9 (NZDCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 65 mсs.
2020.10.07 13:28:02.344 Test9 (EURAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 11 mсs.
2020.10.07 13:28:02.730 Test9 (EURAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 15 mсs.
2020.10.07 13:28:02.800 Test9 (AUDCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 11 mсs.
2020.10.07 13:28:05.471 Test9 (GBPAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 30 mсs.
2020.10.07 13:28:08.675 Test9 (NZDCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 28 mсs.
2020.10.07 13:28:08.675 Test9 (GBPAUD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 120 mсs.
2020.10.07 13:28:09.697 Test9 (CADCHF,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 13 mсs.
2020.10.07 13:28:10.063 Test9 (EURCAD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 29 mсs.
2020.10.07 13:28:11.741 Test9 (CADJPY,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 32 mсs.
2020.10.07 13:28:12.597 Test9 (EURCAD,H1)       Alert: Bench_Stack = 0, Time[Test9.mq5 14 in TimeCurrentMsc: SymbolInfoTick(Symb,Tick)] = 33 mсs.


Надеюсь, не только у меня воспроизводится. Конечно, лаг не такой большой, как показывал ранее. Но тут можно будет докопаться гораздо быстрее до причин.


ЗЫ TimeCurrentMsc почему-то не вводится в MQL5, несмотря на неоднократные просьбы.

 
fxsaber:

Отказался от столь дорогой функции в критических местах. EventChartCustom - дорогая.

Это существенный недостаток. Потому что событийная модель MQL неполная - отсутствует нулевое событие, т.е. событие, которое вызывается, когда в очереди нет других событий. Его можно эмулировать через пользовательское событие. Но с учётом указанного недостатка для тех кому важна скорость событийная модель становится бессмысленной

 
fxsaber:

EventChartCustom - дорогая.

А если без ChartFirst()?

 
Andrey Khatimlianskii:

А если без ChartFirst()?

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

long GetAnotherChart()
{
  long Chart = ::ChartFirst();
  
  while (Chart == ChartID())
    Chart = ChartNext(Chart);
 
  return(Chart);     
}


void OnTick()
{  
  const long Chart = GetAnotherChart();
  
  if (Chart)
    _B(EventChartCustom(Chart, 123, 0, 0, NULL), 1);
  
  _B(EventChartCustom(0, 123, 0, 0, NULL), 1);
}


2020.10.07 14:49:09.786 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 349 mсs.
2020.10.07 14:49:09.786 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 81 mсs.
2020.10.07 14:49:09.866 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 248 mсs.
2020.10.07 14:49:09.866 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 24 mсs.
2020.10.07 14:49:10.095 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 163 mсs.
2020.10.07 14:49:10.095 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 116 mсs.
2020.10.07 14:49:10.810 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 600 mсs.
2020.10.07 14:49:10.811 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 53 mсs.
2020.10.07 14:49:10.870 Alert: Bench_Stack = 0, Time[Test9.mq5 19 in OnTick: EventChartCustom(Chart,123,0,0,NULL)] = 137 mсs.
2020.10.07 14:49:10.870 Alert: Bench_Stack = 0, Time[Test9.mq5 21 in OnTick: EventChartCustom(0,123,0,0,NULL)] = 54 mсs.

На чужой чарт отправлять дороже, чем на свой.

 
A100:

Это существенный недостаток. Потому что событийная модель MQL неполная - отсутствует нулевое событие, т.е. событие, которое вызывается, когда в очереди нет других событий. Его можно эмулировать через пользовательское событие. Но с учётом указанного недостатка для тех кому важна скорость событийная модель становится бессмысленной

OnTimer позволяет делать фоновые вызовы с частотой вплоть до 16 мс.
 
Renat Fatkhullin:
OnTimer позволяет делать фоновые вызовы с частотой вплоть до 16 мс.

Правильно, т.е. мы теряем на пустом месте (вернуться можем не ранее, чем через) минимум 16 мс. А могли бы их и не терять, если бы было бесплатное нулевое событие или бесплатные пользовательские события. А сейчас событийная модель в нижеприведенном случае ограниченно работает:

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

MT5 и скорость в боевом исполнении

fxsaber, 2020.10.06 01:27

Вы совсем не в теме. Допустим, надо открыть две позиции в OnTick. Первый OrderSend - это несколько миллисекунд. После него надо делать снепшот. И тогда вызывать второй OrderSend.

Один только OnTick может выполняться сотни миллисекунд. А вы предлагаете в каком-то OnTimer снепшотиться.

Да еще и OnTimer был освободился для других целей
 
И кроме того OnTimer не позволяет достоверно убедится в том, что мы с помощью него получили именно нулевое событие, поскольку и него приоритет по всей видимости больше (при прочих равных условиях), чем у других обработчиков и это наверное главный контраргумент.
 
fxsaber:

На тему Alert.

Пока точно можно сказать, что Алертить в критических местах нельзя. Нужна асинхронность.

Алерт с принтом, можно попробовать заменить быстрой записью куда нибудь.
На ум приходит нативный sql в памяти

 
Renat Fatkhullin:
Я не предлагал снепшотиться, а ответил на прямой вопрос о миллисекундном таймере.

Он есть, хотя в текущем тестере он все равно срабатывает с частотой 1 сек. В новом тестере, который пишем, постараемся это изменить.

Частенько пользуюсь тем, что Тестер имеет именно миллисекундный таймер, а не секундный. Доказательство.

// Демонстрация корректной работы миллисекундного таймера в Тестере.
#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006
#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun)
  {
    MqlTick Tick;
    
    if (SymbolInfoTick(_Symbol, Tick) && Tick.bid && Tick.ask)
      FirstRun = !EventSetMillisecondTimer(29); // 29 мс таймер.
  }
}

void OnTimer()
{
  static int Count = 0;
  
  if (Count < 10)
  {
    if ((bool)((++Count) & 1)) // Попеременно
      OrderSend(_Symbol, OP_BUY, 0.1, Ask, 0, 0, 0); // Открываем позицию
    else if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0); // Закрываем позицию
  }
}

void OnDeinit( const int )
{
  // Распечатали историю в конце бэктеста.
  for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
      OrderPrint();
}


Результат.

2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #11 2020.10.06 00:00:00.320 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.349 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #9 2020.10.06 00:00:00.262 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.291 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #7 2020.10.06 00:00:00.204 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.233 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #5 2020.10.06 00:00:00.146 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.175 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #3 2020.10.06 00:00:00.088 buy 0.10 EURUSD 1.17859 0.00000 0.00000 2020.10.06 00:00:00.117 1.17827 0.00 0.00 -3.20 0
2020.10.07 19:17:59.232 Core 1  2020.10.06 23:59:57   #1 2020.10.06 00:00:00.000 balance 0.00 0.00000 0.00000 0.00000 2020.10.06 00:00:00.000 0.00000 0.00 0.00 100000000.00 0

Между временем открытия и временем закрытия позиции ровно 29 мс.

Причина обращения: