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

 
Когда-то писал примитивный индикатор лагов. Он отлично показывает, например, массированную torrent-качалку.
Ping
Ping
  • www.mql5.com
Для торговли важным параметром является актуальность текущей цены. На него влияет множество факторов, самый популярный из которых - сетевой пинг между терминалом и торговым сервером. Но часто из виду упускается другой параметр: так называемый "внутренний пинг терминала" - дополнительный лаг котировок внутри самого терминала (платформы) . Даже...
 
fxsaber:

Неверно поняли. Нужно понять, есть затыки у MT или нет. Разбирали логи сервера, когда отложки модифицировались десятки секунд. На сервере все идеально.

Значит проблема где-то в другом месте.

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

Вот купил VPS. Как понять, что он подходит идеально? Какой-то числовой показатель должен же быть. Ретрансмитам верить, как оказалось, нельзя. В полночь - десятки процентов.


ЗЫ Возможно, получится развернуть виртуалку на той же физической машине, где стоит торговый сервер. И оттуда запустить боевой Терминал. Наверное, затыков станет меньше.

Мне кажется трассировать, пинговать из консоли, или спец. софта, проблему не выявить.
Нужно же как то регистрировать участие МТ. Мне кажется нужно бить челом, и просить разработчиков, чтоб сделали свой счётчик на TERMINAL_RETRANSMISSION

 
fxsaber:

Неверно поняли. Нужно понять, есть затыки у MT или нет. Разбирали логи сервера, когда отложки модифицировались десятки секунд. На сервере все идеально.
Значит проблема где-то в другом месте.
Выснили, что я очень часто бью по прошлым ценам. Т.е. серьезный лаг в Терминале на самом деле. Возник вопрос, как его идентифицировать.

Как-то не очень ясно, что именно означает "на сервере все идеально":
1) На сервер не приходили запросы на модификацию, или все запросы в течении 10 секунд имели устаревшую цену?
2) А сколько секунд разницы между "текущей" и "устаревшей" ценой?
3) Кто определяет, что цена устарела: сервер МТ или третья сторона, может какая-то биржа?


Если проблема часто повторяемая, можно было бы проанализировать трафик модификации ордеров с помощью Wireshark на пару с Process Monitor (Network Activity) из Sysinternals.

 
Sergey Dzyublik:

Как-то не очень ясно, что именно означает "на сервере все идеально":
1) На сервер не приходили запросы на модификацию, или все запросы в течении 10 секунд имели устаревшую цену?
2) А сколько секунд разницы между "текущей" и "устаревшей" ценой?
3) Кто определяет, что цена устарела: сервер МТ или третья сторона, может какая-то биржа?

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

Если проблема часто повторяемая, можно было бы проанализировать трафик модификации ордеров с помощью Wireshark на пару с Process Monitor (Network Activity) из Sysinternals.

В этом я полный ноль.

 

Получилось воспроизвести тормоза HistorySelect-функций.

  1. Зайти на демо-счет MetaQuotes-Demo с относительно большой торговой историей. 
    1. Если на демо-счете небольшая торговая история, то разрешить авто-торговлю и параллельно запустить скрипт OrderSend-Test2.ex5 (в приложении, исходник).
  2. Открыть два чарта EURUSD и запустить на каждом советник ниже (желтым в исходнике показаны дополнительные изменения).

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

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

    fxsaber, 2020.06.04 14:38

    Набросал такой советник-мониторинг.

    // Мониторинг длительных пиков выполнения важных функций для торговли.
    #include <fxsaber\Benchmark.mqh> // https://c.mql5.com/3/321/Benchmark.mqh
    
    input int inCycle = 10;    // Циклов проверки в одном OnTick
    input int inAlertTime = 1; // Нижний порог в миллисекундах
    
    #define _B2(A) _B(A, AlertTime)
    
    void Check( const string Symb, const int AlertTime = 1 )
    {
      MqlTick Tick;
      
      if (_B2(SymbolInfoTick(Symb, Tick)))
      {
        MqlTick Ticks[];
        
        _B2(CopyTicks(Symb, Ticks, COPY_TICKS_ALL, 0, 1));
        _B2(CopyTicks(Symb, Ticks, COPY_TICKS_ALL, Tick.time_msc));
        _B2(CopyTicksRange(Symb, Ticks, COPY_TICKS_ALL, Tick.time_msc));
    
        HistorySelect(MathRand(), INT_MAX);
        _B2(HistorySelect(Tick.time, INT_MAX));
        
        _B2(HistoryDealsTotal());
        _B2(HistoryDealGetTicket(0));
        _B2(HistoryDealGetInteger(0, DEAL_MAGIC));
        _B2(HistoryDealGetDouble(0, DEAL_PRICE));
        _B2(HistoryDealSelect(0));
    
        _B2(HistoryOrdersTotal());
        _B2(HistoryOrderGetTicket(0));
        _B2(HistoryOrderGetInteger(0, ORDER_MAGIC));
        _B2(HistoryOrderGetDouble(0, ORDER_PRICE_CURRENT));
        _B2(HistoryOrderSelect(0));
        
        _B2(GetLastError());
        _B2(IsStopped());
        
        _B2(SymbolInfoDouble(Symb, SYMBOL_ASK));
        _B2(SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_VALUE));
        _B2(SymbolInfoDouble(Symb, SYMBOL_POINT));
        _B2(SymbolInfoInteger(Symb, SYMBOL_DIGITS));
    
        _B2(TimeCurrent());
        _B2(TimeLocal());
        _B2(TimeTradeServer());
        
        _B2(OrdersTotal());
        _B2(OrderSelect(0));
        _B2(OrderGetDouble(ORDER_PRICE_CURRENT));
        _B2(OrderGetInteger(ORDER_MAGIC));
        _B2(OrderGetString(ORDER_SYMBOL));
        
        _B2(PositionsTotal());
        _B2(PositionSelect(Symb));
        _B2(PositionSelectByTicket(0));
        _B2(PositionGetDouble(POSITION_PRICE_CURRENT));
        _B2(PositionGetInteger(POSITION_MAGIC));
        _B2(PositionGetString(POSITION_SYMBOL));
        
        _B2(AccountInfoDouble(ACCOUNT_EQUITY));
        _B2(AccountInfoInteger(ACCOUNT_MARGIN_MODE));
        
        MqlTradeRequest Request = {0};
        MqlTradeCheckResult CheckResult;
    
        _B2(OrderCheck(Request, CheckResult));
        
        _B2(MQLInfoInteger(MQL_TRADE_ALLOWED));
        _B2(AccountInfoInteger(ACCOUNT_TRADE_EXPERT));
        _B2(AccountInfoInteger(ACCOUNT_TRADE_ALLOWED));
        _B2(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED));
        
        _B2(SymbolsTotal(true));
        _B2(SymbolName(0, true));
        _B2(Symbol());
        
        _B2(GlobalVariableCheck(NULL));
        _B2(GlobalVariableGet(NULL));
        
        _B2(ResourceFree(NULL));
      }
    }
    
    void OnTick()
    {
      for (int i = 0; i < inCycle; i++)
        Check(_Symbol, inAlertTime);      
    }

MT5 b2572 сыпет такими сообщениями.

2020.08.13 05:28:00.143 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 6 ms.
2020.08.13 05:28:00.148 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 3 ms.
2020.08.13 05:28:00.153 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 4 ms.
2020.08.13 05:28:00.162 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 5 ms.
2020.08.13 05:28:00.167 Alert: Time[Test6.mq5 34: HistoryOrderSelect(0)] = 2 ms.
2020.08.13 05:28:00.174 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 4 ms.
2020.08.13 05:28:00.180 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 5 ms.
2020.08.13 05:28:00.186 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 4 ms.
2020.08.13 05:28:00.194 Alert: Time[Test6.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 6 ms.


Просьба написать о своих результатах, кто будет пробовать. Воспроизводятся тормоза?


ЗЫ Долго пытался въехать, почему на боевых счетах тормоза. Похоже, нашел проблемное место.

Файлы:
 
fxsaber:

ЗЫ Долго пытался въехать, почему на боевых счетах тормоза. Похоже, нашел проблемное место.

Так удручающе выглядит боевая ситуация.

2020.08.13 10:20:09.074 Expert (EURAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 59 ms.
2020.08.13 10:20:09.074 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 59 ms.
2020.08.13 10:20:09.074 Expert (GBPNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 59 ms.
2020.08.13 10:20:09.074 Expert (GBPAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 59 ms.
...
2020.08.13 11:31:58.559 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 34 ms.
2020.08.13 11:31:58.559 Expert (GBPNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 35 ms.
2020.08.13 11:31:58.624 Expert (EURAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 99 ms.
2020.08.13 11:32:12.483 Expert (GBPNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 7 ms.
2020.08.13 11:33:44.877 Expert (EURAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 27 ms.
2020.08.13 11:33:44.877 Expert (GBPNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 21 ms.
2020.08.13 11:33:44.879 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 27 ms.
2020.08.13 11:33:47.911 Expert (GBPAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 18 ms.
2020.08.13 11:33:47.911 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 18 ms.
2020.08.13 11:33:47.912 Expert (GBPNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 29 ms.

2020.08.13 11:33:49.312 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 22 ms.
2020.08.13 11:33:49.312 Expert (EURAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 22 ms.

2020.08.13 11:34:02.612 Expert (EURAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 63 ms.
2020.08.13 11:34:02.613 Expert (GBPNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 63 ms.

2020.08.13 11:34:02.616 Expert (GBPAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 56 ms.
2020.08.13 11:34:12.057 Expert (GBPAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 12 ms.

2020.08.13 11:34:30.643 Expert (EURAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 32 ms.
2020.08.13 11:34:30.643 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 32 ms.

2020.08.13 11:34:30.643 Expert (GBPAUD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 8 ms.
2020.08.13 11:37:17.059 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 24 ms.
2020.08.13 11:38:30.360 Expert (EURNZD,M1)      Alert: Time[NewTicks.mqh 116: ::HistorySelect(TimeMsc/1000,INT_MAX)] = 13 ms.

Если присмотреться, то можно заметить, что независимые друг от друга советники тормозят одинаково (время и длительность лага). Т.е. когда несколько советников делают вызов HistorySelect, то MT5 останавливает выполнение всех советников на какое-то время, а потом возвращает советникам свои результаты.


По какой причине архитектурно выбран столь странный (по сравнению с напрашивающимися) API работы с торговой историей? Где подводные камни в таком подходе?

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

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

fxsaber, 2020.05.28 15:27

HistorySelect.

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


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

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

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


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


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

Пожалуйста, уберите тормоза из торгового Терминала!

 
1000 сделок в истории достаточно?
 
Rorschach:
1000 сделок в истории достаточно?

Тестил с такими показателями.

        : HistoryDealsTotal() = 11045
        : HistoryOrdersTotal() = 11518
 

Orders 20990

Deals 10277

Лог за 20 минут

Файлы:
20200813.log  4817 kb
 
Rorschach:

Orders 20990

Deals 10277

Лог за 20 минут

Супер, Спасибо! Наконец, полное подтверждение печальных лагов MT5. И это без каких-либо торговых функций. Проблемы чуть ли не везде.

KD      0       16:00:33.382    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 34: HistoryOrderSelect(0)] = 25 ms.
PE      0       16:00:44.913    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 17: CopyTicks(Symb,Ticks,COPY_TICKS_ALL,0,1)] = 24 ms.
DP      0       16:00:44.888    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 22: HistorySelect(Tick.time,INT_MAX)] = 46 ms.
FI      0       16:00:49.579    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 28: HistoryDealSelect(0)] = 22 ms.
EE      0       16:01:03.287    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 33: HistoryOrderGetDouble(0,ORDER_PRICE_CURRENT)] = 1 ms.
KE      0       16:01:07.013    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 50: OrderGetDouble(ORDER_PRICE_CURRENT)] = 1 ms.
JM      0       16:01:12.189    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 44: TimeCurrent()] = 39 ms.
MD      0       16:01:13.067    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 81: ResourceFree(NULL)] = 1 ms.
RS      0       16:01:13.572    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 41: SymbolInfoDouble(Symb,SYMBOL_POINT)] = 7 ms.
GL      0       16:01:27.816    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 79: GlobalVariableGet(NULL)] = 22 ms.
PD      0       16:01:33.892    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 58: PositionGetInteger(POSITION_MAGIC)] = 1 ms.
KP      0       16:01:39.864    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 67: OrderCheck(Request,CheckResult)] = 3 ms.
ML      0       16:01:39.970    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 62: AccountInfoInteger(ACCOUNT_MARGIN_MODE)] = 1 ms.
KM      0       16:01:41.045    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 55: PositionSelect(Symb)] = 2 ms.
NS      0       16:01:46.832    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 78: GlobalVariableCheck(NULL)] = 1 ms.
JP      0       16:01:49.211    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 75: SymbolName(0,true)] = 1 ms.
EL      0       16:01:59.101    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 19: CopyTicksRange(Symb,Ticks,COPY_TICKS_ALL,Tick.time_msc)] = 32 ms.
IM      0       16:02:07.462    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 70: AccountInfoInteger(ACCOUNT_TRADE_EXPERT)] = 7 ms.
PJ      0       16:02:11.735    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 37: IsStopped()] = 4 ms.
OG      0       16:03:08.178    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 32: HistoryOrderGetInteger(0,ORDER_MAGIC)] = 14 ms.
JH      0       16:03:16.385    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 40: SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_VALUE)] = 5 ms.
FM      0       16:03:16.601    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 59: PositionGetString(POSITION_SYMBOL)] = 1 ms.
GH      0       16:03:21.841    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 72: TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)] = 1 ms.
FJ      0       16:03:25.782    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 46: TimeTradeServer()] = 1 ms.
EO      0       16:03:26.772    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 45: TimeLocal()] = 10 ms.
HD      0       16:03:36.595    fxstest (EURUSD,M1)     Alert: Time[fxstest.mq5 13: SymbolInfoTick(Symb,Tick)] = 13 ms.
...

Удручающе. Интересно было бы посмотреть результат под Linux. Под Win говорить о реал-тайме не приходится.

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