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

 
fxsaber:

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

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

В самом простейшем виде:

OnXXX( параметры )
{
        запомнить параметры (поместить в очередь)
        OnMain();
}
On2XX( параметры )
{
/*вычисления*/
        поменять приоритет обработки событий (если нужно)
/*вычисления*/
        промежуточный return (если нужно) 
/*вычисления*/
}
void OnMain()
{
        прочитать приоритет обработки событий
        для каждой группы событий
                извлечь параметры из очереди
                OnTradeXXX( параметры )
                удалить событие из очереди
}

Просто нужно изменить подход к самим вычислениям (делайте промежуточный return так часто как это требует задача). Но если это сложно, то считайте на 1ом этапе, что OnMain для Вас как бы и нет (Вы же основной код переносите не в OnMain, а в On2XX) соответственно в OnMain не нужно ничего узнавать

 
A100:

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

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

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

Вы не о том пишите.
Проблема в том что функционал заполнения полей у входных переменных  функции "OntaredeTransaction" не соответствует описанию, данному в  Справке, в худшую сторону:
т.е. множество полей не заполняются в вызовах, и даже в конечном вызове TRADE_TRANSACTION_HISTORY_ADD.
Соответственно все трейдеры мучаются тут чтобы в момент прихода как-то эти недостающие параметры определить.
Тут была масса обсуждений, просто сделайте поиск по форуму - кривой функционал "OntaredeTransaction" порождает доп. затраты при обработке. как по времени, так и "грузит" алготрейдеров лишними трудозатратами времени на разрабоку  адекватно работающего кода (т.е. массовая потери времени и колоссальная неэффективность на уровне всего сообщества).
Теущие отписки разрабов типа "Если у вас по символу Market execution, то будет нулевое значение цены; Так и должно быть." (Ссылка) - это НЕНОРМАЛЬНО, еще раз -
отсутствие исчерпывающих значений в последнем вызовах функции приводит к массе доп. трудозатрат.

Новая версия платформы MetaTrader 5 build 2450: Сервис "Подписки", улучшения в интерфейсе и удобные функции в MetaEditor
Новая версия платформы MetaTrader 5 build 2450: Сервис "Подписки", улучшения в интерфейсе и удобные функции в MetaEditor
  • 2020.05.18
  • www.mql5.com
В пятницу 22 мая 2020 года будет выпущена обновленная версия платформы MetaTrader 5...
 
fxsaber:

HistorySelect.


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


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

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


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


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


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

У вас есть доказательства про " такой вызов HistorySelect длится 5-30 миллисекунд"?

Если я правильно понял вышу мысль, то тестовый код должен выглядеть так:

void OnStart()
  {
   MqlTick Tick;
   SymbolInfoTick(_Symbol, Tick);
   ulong start=GetMicrosecondCount();
   for(int i=0; i<100000; i++)
     {
      HistorySelect(Tick.time, INT_MAX);
     }
   ulong end=GetMicrosecondCount()-start;
   Print("100000 HistorySelect = ",DoubleToString(end/1000.0,2)," ms");
  }

Вот так отрабатывают 100000 запросов:

100000 HistorySelect = 141.63 ms
 
Anton:

У вас есть доказательства про " такой вызов HistorySelect длится 5-30 миллисекунд"?

Если я правильно понял вышу мысль, то тестовый код должен выглядеть так:

Вот так отрабатывают 100000 запросов:

А один запрос? Не удивлюсь, если компилятор, при оптимизации, именно так и поступил)))
 
Anton:

У вас есть доказательства про " такой вызов HistorySelect длится 5-30 миллисекунд"?

Если я правильно понял вышу мысль, то тестовый код должен выглядеть так:

Вот так отрабатывают 100000 запросов:

Запуск Вашего скрипта.

        100000 HistorySelect = 19493.96 ms


Запуск другого скрипта.

#define PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{
  if (HistorySelect(0, INT_MAX))
  {
    PRINT(HistoryDealsTotal());
    PRINT(HistoryOrdersTotal());
  }
}


HistoryDealsTotal() = 17828
HistoryOrdersTotal() = 22142


Обычный боевой счет. Не HFT.


ЗЫ Кстати, Ваш скрипт показал, что HistorySelect каждый раз заново все вычисляет. А ведь входные параметры не менялись, таблица истории не обновлялась, другие HistorySelect-функции не вызывались.

 
fxsaber:

Запуск Вашего скрипта.

Значит нужны подробности.

Мой тест запускался на не самом быстром "Intel Xeon  E5-2630 v4 @ 2.20GHz" с массой других процессов в фоне.

На тестовом счете в истории было 31315 ордеров более-менее равномерно начиная с 2009 года, втч 8 ордеров за сегодняшний день.

Возможно у вас одновременно работал какой-то скрипт или эксперт радикально нагружающий базы терминала. Попробуйте на "чистом" терминале.

Более информативный тест:

void OnStart()
  {
   MqlTick Tick;
   SymbolInfoTick(_Symbol, Tick);
//---   
   ulong start=GetMicrosecondCount();
   int count=100000;
   for(int i=0; i<count; i++)
     {
      HistorySelect(Tick.time, INT_MAX);
     }
   ulong end=GetMicrosecondCount()-start;

   Print(count," HistorySelect = ",DoubleToString(end/1000.0,2)," ms");
   Print("Selected = ",HistoryOrdersTotal());
//---   
   Tick.time=(Tick.time/86400)*86400;
   
   start=GetMicrosecondCount();
   count=1000;
   for(int i=0; i<count; i++)
     {
      HistorySelect(Tick.time, INT_MAX);
     }
   end=GetMicrosecondCount()-start;

   Print(count," HistorySelect = ",DoubleToString(end/1000.0,2)," ms");
   Print("Selected = ",HistoryOrdersTotal());
//---   
   HistorySelect(0, INT_MAX);
   Print("Selected = ",HistoryOrdersTotal());
  }

Три запуска:

2020.05.29 13:53:14.281 TestHistorySelect (EURUSD,H1)   100000 HistorySelect = 141.76 ms
2020.05.29 13:53:14.281 TestHistorySelect (EURUSD,H1)   Selected = 0
2020.05.29 13:53:14.284 TestHistorySelect (EURUSD,H1)   1000 HistorySelect = 2.82 ms
2020.05.29 13:53:14.284 TestHistorySelect (EURUSD,H1)   Selected = 8
2020.05.29 13:53:15.566 TestHistorySelect (EURUSD,H1)   Selected = 31315
2020.05.29 13:53:16.930 TestHistorySelect (EURUSD,H1)   100000 HistorySelect = 138.30 ms
2020.05.29 13:53:16.930 TestHistorySelect (EURUSD,H1)   Selected = 0
2020.05.29 13:53:16.933 TestHistorySelect (EURUSD,H1)   1000 HistorySelect = 2.61 ms
2020.05.29 13:53:16.933 TestHistorySelect (EURUSD,H1)   Selected = 8
2020.05.29 13:53:18.176 TestHistorySelect (EURUSD,H1)   Selected = 31315
2020.05.29 13:53:22.217 TestHistorySelect (EURUSD,H1)   100000 HistorySelect = 142.94 ms
2020.05.29 13:53:22.217 TestHistorySelect (EURUSD,H1)   Selected = 0
2020.05.29 13:53:22.220 TestHistorySelect (EURUSD,H1)   1000 HistorySelect = 2.57 ms
2020.05.29 13:53:22.220 TestHistorySelect (EURUSD,H1)   Selected = 8
2020.05.29 13:53:23.498 TestHistorySelect (EURUSD,H1)   Selected = 31315
 
Anton:

Значит нужны подробности.

Мой тест запускался на не самом быстром "Intel Xeon  E5-2630 v4 @ 2.20GHz" с массой других процессов в фоне.

На тестовом счете в истории было 31315 ордеров более-менее равномерно начиная с 2009 года, втч 8 ордеров за сегодняшний день.

Возможно у вас одновременно работал какой-то скрипт или эксперт радикально нагружающий базы терминала. Попробуйте на "чистом" терминале.

Пустой Терминал на этом же счете и машине.

        100000 HistorySelect = 19367.01 ms


На других счетах и Терминалах подобная же картина. Конфигурация.

2020.05.29 13:53:44.766 Terminal        ICMarkets - MetaTrader 5 x64 build 2453 started for International Capital Markets Pty Ltd.
2020.05.29 13:53:44.766 Terminal        Windows 7 Service Pack 1 build 7601, Intel Core i7-2700K  @ 3.50GHz, 6 / 15 Gb memory, 4 / 29 Gb disk, IE 11, Admin, GMT+2


Просьба читателей привести свои результаты этого скрипта.

void OnStart()
{
  // https://www.mql5.com/ru/forum/342090/page2#comment_16607997
#define PRINT(A) Print(#A + " = " + (string)(A))
  
  if (HistorySelect(0, INT_MAX))
  {
    PRINT(HistoryDealsTotal());
    PRINT(HistoryOrdersTotal());
  }

   // https://www.mql5.com/ru/forum/342090/page2#comment_16607922
   MqlTick Tick;
   SymbolInfoTick(_Symbol, Tick);
   ulong start=GetMicrosecondCount();
   for(int i=0; i<100000; i++)
     {
      HistorySelect(Tick.time, INT_MAX);
     }
   ulong end=GetMicrosecondCount()-start;
   Print("100000 HistorySelect = ",DoubleToString(end/1000.0,2)," ms");
}
 
Anton:

Более информативный тест:

Три запуска:

        100000 HistorySelect = 18344.01 ms
        Selected = 0
        1000 HistorySelect = 602.77 ms
        Selected = 1169
        Selected = 22142
        100000 HistorySelect = 18331.15 ms
        Selected = 0
        1000 HistorySelect = 446.45 ms
        Selected = 1169
        Selected = 22142
        100000 HistorySelect = 18495.35 ms
        Selected = 0
        1000 HistorySelect = 549.40 ms
        Selected = 1169
        Selected = 22142

Пустой Терминал 2460.


ЗЫ Запуск на пустом счете.

        100000 HistorySelect = 28.30 ms
        Selected = 0
        1000 HistorySelect = 0.28 ms
        Selected = 0
        Selected = 0


Похоже, на скорость сильно влияет количество сделок, не ордеров.

 
fxsaber:

Пустой Терминал на этом же счете и машине.


На других счетах и Терминалах подобная же картина. Конфигурация.


Просьба читателей привести свои результаты этого скрипта.

Это ничего не доказывает, но то, что с каждым новым запуском (на другом символе), время увеличивается - настораживает...

2020.05.29 13:59:36.625 test1 (USDJPY,H1)       HistoryDealsTotal() = 1
2020.05.29 13:59:36.626 test1 (USDJPY,H1)       HistoryOrdersTotal() = 0
2020.05.29 13:59:36.642 test1 (USDJPY,H1)       100000 HistorySelect = 16.00 ms
2020.05.29 13:59:53.522 test1 (EURUSD,H1)       HistoryDealsTotal() = 1
2020.05.29 13:59:53.522 test1 (EURUSD,H1)       HistoryOrdersTotal() = 0
2020.05.29 13:59:53.546 test1 (EURUSD,H1)       100000 HistorySelect = 24.36 ms
2020.05.29 14:00:03.640 test1 (USDCHF,H1)       HistoryDealsTotal() = 1
2020.05.29 14:00:03.640 test1 (USDCHF,H1)       HistoryOrdersTotal() = 0
2020.05.29 14:00:03.669 test1 (USDCHF,H1)       100000 HistorySelect = 29.25 ms
2020.05.29 14:00:14.994 test1 (GBPUSD,H1)       HistoryDealsTotal() = 1
2020.05.29 14:00:14.994 test1 (GBPUSD,H1)       HistoryOrdersTotal() = 0
2020.05.29 14:00:15.026 test1 (GBPUSD,H1)       100000 HistorySelect = 31.76 ms
 
Сергей Таболин:

Нужно запустить на счете с большой историей торговли.

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