Библиотеки: MT4Orders - страница 86

 
Спасибо, что поделились.
 
Спасибо большое!!! Это просто супер-ЗАМЕЧАТЕЛЬНО
 
Иногда нужно по закрытому тикету найти его позицию в истории торгов.
// Возвращает позицию тикета в таблице исторических ордеров.
int OrderSelectPos( const long Ticket = -1 )
{
#ifdef MT4ORDERS_ORDERS_SORT
  #ifdef __MQL5__
    #ifdef __VIRTUAL__
      if (!VIRTUAL::GetHandle())
    #endif // #ifdef __VIRTUAL__
    
    return(-1);  
  #endif // #ifdef __MQL5__  
#else // #ifdef MT4ORDERS_ORDERS_SORT
  #ifdef __VIRTUAL__
    if (VIRTUAL::GetHandle())
      return(-1);  
  #endif // #ifdef __VIRTUAL__  
#endif // #ifdef MT4ORDERS_ORDERS_SORT #else

  int Pos = -1;
  
  if (::OrderSelect(Ticket, SELECT_BY_TICKET, MODE_HISTORY) && ::OrderCloseTime())
  {
    static int PrevHistoryTotal = 0;
    static CHashMap<long, int> Tickets;
        
    const long SearchTicket = (::OrderType() <= OP_SELL) ? ::OrderTicket() : -::OrderTicket();    
    const int Total = ::OrdersHistoryTotal();
    
    while (PrevHistoryTotal < Total)
    {
      if (::OrderSelect(PrevHistoryTotal, SELECT_BY_POS, MODE_HISTORY))        
      {
        const long NewTicket = (::OrderType() <= OP_SELL) ? ::OrderTicket() : -::OrderTicket();
        
        if (NewTicket == SearchTicket)
          Pos = PrevHistoryTotal;
          
        Tickets.Add(NewTicket, PrevHistoryTotal);       
      }
      
      PrevHistoryTotal++;      
    }
    
    if ((Pos == -1) && !Tickets.TryGetValue(SearchTicket, Pos))
      Pos = -1;
  }
  
  return(Pos);
}


Проверка.

void OnStart()
{  
  long Tickets[];
  
  // Корректность.
  for (uint i = ArrayResize(Tickets, OrdersHistoryTotal()); (bool)i--;)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
    {
      Tickets[i] = OrderTicket();
      
      if (OrderSelectPos(OrderTicket()) != i)
        Print(i);
    }

  const ulong StartTime = GetMicrosecondCount();

  // Производительность.
  for (uint i = ArraySize(Tickets); (bool)i--;)
    if (OrderSelectPos(Tickets[i]) == -1)
      Print(i);
      
  Print(DoubleToString((double)(GetMicrosecondCount() - StartTime) / ArraySize(Tickets), 2) + " mcs/unit.");
}


Результат.

1.62 mcs/unit.
 

При большом количестве MT5-сделок/ордеров в ByPass-режиме (использую, например, в CustomReport) первое обращение к истории может занимать много времени.

#define MT4ORDERS_BYPASS_MAXTIME 1000000 // Максимальное время (в мкс.) на ожидание синхронизации торгового окружения  
#include <MT4Orders.mqh>

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

void OnStart()
{  
  for (int i = 0; i < 3; i++)
  {
    const ulong StartTime = GetMicrosecondCount();
    PRINT(OrdersHistoryTotal());
    PRINT(GetMicrosecondCount() - StartTime);
  }
  
  PRINT(HistoryDealsTotal());
  PRINT(HistoryOrdersTotal());
}
OrdersHistoryTotal() = 235627
GetMicrosecondCount() - StartTime = 14831029

HistoryDealsTotal() = 259381
HistoryOrdersTotal() = 619850

14 секунд!


Оказалось, что тормоза исходят от ArrayCopy-функции.


Такая правка в Include\fxsaber\TradesID\ByPass.mqh

  bool IsPosDeal( const ulong Ticket )
  {
    bool Res = true;

    const ulong PositionID = ::HistoryDealGetInteger(Ticket, DEAL_POSITION_ID);

    if (PositionID)
    {
      static ulong Deals[];
// .....

  bool IsPosOrder( const ulong Ticket )
  {
    bool Res = true;

    const ulong PositionID = ::HistoryOrderGetInteger(Ticket, ORDER_POSITION_ID);

    if (PositionID)
    {
      const long TicketTime = ::HistoryOrderGetInteger(Ticket, ORDER_TIME_DONE_MSC);

      static ulong OldOrders[];
// .....

увеличивает производительность в 4.5 раза - ~3 секунды.

OrdersHistoryTotal() = 235627
GetMicrosecondCount() - StartTime = 3307875


Наглядный пример, что частая работа с массивами должна быть с умом. В данном случае static позволяет не выделять в ArrayCopy каждый раз память под массив. И получаем кратный рост производительности в реальной задачи, который ощущается невооруженным взглядом.

Проверь своего брокера!
Проверь своего брокера!
  • 2021.11.12
  • www.mql5.com
На просторах интернета можно видеть довольно частые сценарии торговли. Управляющий ПАММ-счетом набрал инвесторов. Хорошо торговал, но с какого-то момента прибыльность сильно уменьшилась, вплоть до
 
fxsaber #:

При большом количестве MT5-сделок/ордеров в ByPass-режиме (использую, например, в CustomReport) первое обращение к истории может занимать много времени.

Обновленный ByPass.mqh позволил ускорить эту процедуру в 15 раз на тестах.
 

Hello author, while using the OrderSendAsync function, I noticed that MT4ORDERS::LastTradeResult.retcode equals TRADE_RETCODE_DONE . However, in your code, it checks whether MT4ORDERS::LastTradeResult.retcode == TRADE_RETCODE_PLACED . Could this be a mistake, or is it my misunderstanding?

#define RETURN_ASYNC(A) return((A) && ::OrderSendAsync(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) &&                        \
                               (MT4ORDERS::LastTradeResult.retcode == TRADE_RETCODE_PLACED) ? MT4ORDERS::LastTradeResult.request_id : 0);
 
hini #:

while using the OrderSendAsync function, I noticed that MT4ORDERS::LastTradeResult.retcode equals TRADE_RETCODE_DONE

Server name?
 
fxsaber #:
Server name?
I forgot to mention that I am using the MT5 tester. It should have nothing to do with the server, right?
 
hini #:
I forgot to mention that I am using the MT5 tester. It should have nothing to do with the server, right?
In live trading, MT4ORDERS::LastTradeResult.retcode == TRADE_RETCODE_PLACED is indeed correct, while in the MT5 tester it is TRADE_RETCODE_DONE . This was my mistake.
 
hini #:
I forgot to mention that I am using the MT5 tester. It should have nothing to do with the server, right?

В Тестере для первого удачного выполнения MT5-OrderSend/OrderSendAsync всегда MqlTradeResult.request_id == 0.

Считаю это поведение недоработкой со стороны MQ, т.к. request_id должен начинаться с единицы.


Это одна из причин, почему в MT4Orders реализация OrderSendAsync для Тестера не сделана. Есть и другая менее веская причина (из книги).

Внимание! В тестере функция OrderSendAsync работает как OrderSend. Это затрудняет отладку отложенной обработки асинхронных запросов.
Учебник по MQL5: Автоматизация торговли / Создание экспертов / Отправка торгового запроса: OrderSend и OrderSendAsync
Учебник по MQL5: Автоматизация торговли / Создание экспертов / Отправка торгового запроса: OrderSend и OrderSendAsync
  • www.mql5.com
Для выполнения торговых операций MQL5 API предоставляет две функции: OrderSend и OrderSendAsync . Они, также как и OrderCheck , выполняют в...