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

 

MT5 - шустрая платформа. Но есть узкие горлышки, которые сводят на нет все старания быстрой торговли.

Хотелось бы собрать проблемы здесь, обсудить и решить их где-то своими силами, где-то с помощью Разработчиков.

 

HistorySelect.


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


Например, в боевых советниках важно работать с актуальными данными. В частности, чтобы тики из Обзора рынка и CopyTicks по возможности не были устаревшими.

Для этого имеются не очень хорошие, но вынужденные механизмы проверки актуальности текущих ценовых данных. Одной из частей такого механизма является детектирование ситуаций, когда сделка по символу прошла позже последнего тика. Такое случается не редко, поэтому важно знать, является ли текущий тик еще актуальным или нет.


Для подобного детектирования нужно иметь возможность обращения к истории последних сделок. Делается это через HistorySelect следующим схематичным образом.

void OnTick()
{
  MqlTick Tick;

  if (SymbolInfo(_Symbol, Tick) && HistorySelect(Tick.time, INT_MAX)) // Взяли история торгов со времени текущего тика.
    // Проверяем актуальность тика через сравнение Tick.time_msc и DEAL_TIME_MSC.
}


К огромному сожалению, такой вызов HistorySelect длится 5-30 миллисекунд (самостоятельно замерял в Release-EX5). Когда в советнике в OnTick делается несколько подобных актуализаций (по-хорошему, нужно делать после любой паузы. Например, после каждого OrderSend.), то все становится безумно дорогим/долгим. HistorySelect может суммарно в одном OnTick съедать несколько секунд.


Уважаемые разработчики, почему так дорого? Эта функция может выполняться мгновенно при должной реализации.


Просьба подумать над вводом таких функций по работе с историей.

HistoryDealsSelect( const int Index, const int Count = WHOLE_ARRAY );  // Из внутренней таблицы сделок взять сделки, начиная с заданного индекса в таблице.
HistoryOrdersSelect( const int Index, const int Count = WHOLE_ARRAY ); // Из внутренней таблицы ордеров взять ордера, начиная с заданного индекса в таблице.

Они бы полностью закрыли тормоза HistorySelect. Потому что очень дешево решали бы задачу получения последних сделок. Сейчас одно мучение в боевом исполнении.


Не всегда возможно контролировать последние сделки через OnTradeTransaction. Поэтому быстрая работа с историей актуальна.

 

Доступ к ChartEvent и TradeTransaction-событиям.


Идея и один из вариантов возможной реализации был предложен. Поэтому просто копирую сюда.

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

Ошибки, баги, вопросы

Sergey Dzyublik, 2020.05.20 00:47

Предложение разработчикам.
Прошу рассмотреть возможность добавления в MQL функции, которая позволит пользователям самостоятельно вызывать обработку накопившихся "сообщений" в OnChartEvent из пользовательского кода.
1) Это позволит вызывать обработку OnChartEvent между итерациями продолжительного во времени расчета, делая пользовательскую графическую панель хоть как-то отзывчивой без сооружая огорода из: пула задач, передачи данных, синхронизации состояний, сохранения и восстановления контекста...
2) Это позволит использовать OnChartEvent в скриптах.

Спасибо.

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

Ошибки, баги, вопросы

Sergey Dzyublik, 2020.05.20 13:39

Не совсем, скорее бы назвал данную функцию как HandleNextEvent, возможная сигнатура:

bool HandleNextEvent (ENUM_EVENT_TYPE);


При вызове, аналогично GetNextEvent, проверяет наличие указанного ENUM_EVENT_TYPE в очереди,
и при наличии данного события, автоматически передает управление на пользовательский код соответствующего обработчика (OnChartEvent, OnTrade, OnTradeTransaction, ... (спасибо fxsaberза дополнение)). 
Возвращает true, если в очереди было событие, в ином случаи - false.


Возможен вариант использования:

//....
for(int i = 0; i < 10^6; ++i){
   // .... Data Calculations

   if((i % 10^3) == 0){
       while(HandleNextEvent(EVENT_TYPE_ALL));
   }
}
//....

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

Ошибки, баги, вопросы

Sergey Dzyublik, 2020.05.20 14:38

2) Все верно. Если меня интересует обработка конкретного события, а не всех имеющихся в системе, было бы не плохо предоставить возможность обработать только данный тип событий, оставив обработку остальных событий в обычном режиме.
3) Если во время обработки опять будет вызов HandleNextEvent - вызвать и обработать. Единственное что может быть - это переполнение стека, но это проблема пользователя и его кода, а не разработчиков.
4) События, которые не попадают под фильтр, остаются в той же последовательности и будут вызваны, когда пользователь вернет управление в систему, как обычно.


Сейчас, чтобы достучаться до тех же TradeTransaction-событий внутри выполняющегося кода, приходится городить костыли.

Для боевого применения советникам очень нужна такая возможность.

 
fxsaber:

Не всегда возможно контролировать последние сделки через OnTradeTransaction. Поэтому быстрая работа с историей актуальна.

Пожалуйста, приведите пример, когда нет возможности контролировать? 

 
prostotrader:

Пожалуйста, приведите пример, когда нет возможности контролировать? 

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

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2020.04.23 19:51

Стрелочки открытия/закрытия позиций, которые MT5 автоматически расставляет в реал-тайме, основываются на TradeTransaction-событиях.


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


И, как тут говорили иногда, нельзя полагаться на OnTradeTransaction в боевых советниках. Жаль, надежного публичного механизма работы с OrderSendAsync нет. 


А также при выставлении нескольких OrderSend внутри кода. Когда один OrderSend зависит от предыдущего.

 
fxsaber:

А также при выставлении нескольких OrderSend внутри кода. Когда один OrderSend зависит от предыдущего.

Если происходит обрыв связи, то и в историю ничего не добавится!

Я более 5 лет использую OrderSendAsync (тогда с OrderSend были проблемы) + OnTradeTransaction() как раз в боевом режиме - проблем нет!

Если происходит обрыв связи, то выяснение происходит по магику, который присваивается каждому ордеру (на ФОРЕКС это трудно сделать т.к имена символов не стандартизированы).

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
В языке MQL5 предусмотрена обработка некоторых предопределенных событий. Функции для обработки этих событий должны быть определены в программе MQL5: имя функции, тип возвращаемого значения, состав параметров (если они есть) и их типы должны строго соответствовать описанию функции-обработчика события. Именно по типу возвращаемого значения и по...
 
prostotrader:

Если происходит обрыв связи, то и в историю ничего не добавится!

Я более 5 лет использую OrderSendAsync (тогда с OrderSend были проблемы) + OnTradeTransaction() как раз в боевом режиме - проблем нет!

Невозможно не заметить, как вы годами топите за Async+OnTrade. Вы и актуализацию данных делаете через этото механизм и все остальное, ведь проблем нет.

Просьба хоть здесь не заявлять "вы просто готовить не умеете".

 
fxsaber:

Невозможно не заметить, как вы годами топите за Async+OnTrade. Вы и актуализацию данных делаете через этото механизм и все остальное, ведь проблем нет.

Просьба хоть здесь не заявлять "вы просто готовить не умеете".

Вы "сражаетесь" за микросекунды, при этом наворачиваете тонны кода, который тоже кушает время,

да и в 99% случаев он не нужен.

 
Призываю высказываться только конструктивно.
 
fxsaber:

Доступ к ChartEvent и TradeTransaction-событиям.

Идея и один из вариантов возможной реализации был предложен. Поэтому просто копирую сюда.

Сейчас, чтобы достучаться до тех же TradeTransaction-событий внутри выполняющегося кода, приходится городить костыли.

Костыли не в том направлении делаете:

Оставьте в OnXXX функциях только копирование событий (параметров) в очереди и вызова основной OnMain функции. Перенесите весь их код в дублирующие On2XX функции. И вызывайте из OnMain эти дублирующие On2XX функции в той последовательности, в которой Вам нужно, в свою очередь передавая им в качестве параметров данные из очередей

Далее проведите замеры - покажите выигрыш в скорости и тогда уже можно будет предлагать дополнить MQL соответствующим функционалом. Но зачем дополнять, если Вы и так уже все сделали сами здесь и сейчас?!

 
A100:

Оставьте в OnXXX функциях только копирование событий (параметров) в очередь и вызова основной OnMain функции. Перенесите весь код в дублирующие On2XX функции. И вызывайте из OnMain эти дублирующие On2XX функции в той последовательности, в которой Вам нужно, в свою очередь передавая им в качестве параметров данные из очереди

Пожалуйста, приведите элементарную схему-код этой идеи. На первый взгляд звучит, как полное непонимание.

Во время выполнения OnMain-функции нет возможности узнать состояние текущей реальной очереди. Единственный обходный вариант это сделать - программа шпион, как приводил по ссылке.