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

 
Enrique Dangeroux:

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

В настоящее время DEAL_ENTRY_OUT от MT4OrderClose будет иметь магию == 0.

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

В OrderClose можно задать MagicNumber, если есть желание.

В MT5 при частичном закрытии позиции можно менять MagicNumber открытой позиции, поэтому дается выбор.

Например, если у Вас открыта позиция с MagicNumber = 5 и Вы закрываете позицию руками, то DEAL_ENTRY_OUT_MAGIC = 0. При этом библиотека все равно вернет OrderMagicNumber() = 5.

 
// Список изменений:
// 12.01.2020
//   Fix: OrderTicketID() для балансовых сделок возвращает теперь правильное значение.
//   Fix: Скорректирован SELECT_BY_TICKET-выбор по OrderTicketID() (MT5-PositionID).
//   Fix: Изменено название внутреннего метода библиотеки для большей совместимости с макросами.
 
Не знаю, баг или фича, но для фьючерсов профит и цена открытия считаются не совсем так, как ожидается. Допустим, происходит открытие позиции в 12.00, в 18.40 происходит клиринг и автоматическое переоткрытие позиции, после чего в 20.00 позиция закрывается. В итоге получается 4 сделки (вход-выход и 2 сделки клиринга). GetHistoryPositionData для тикета 4-й сделки (выхода из позиции) выбирает профит как MT4ORDERS::Order.Profit = ::HistoryDealGetDouble(Ticket, DEAL_PROFIT); Что вернёт по сути разницу между сделками 3-4 (клирингом и выходом). Но цену открытия он вернёт как MT4ORDERS::Order.OpenPrice = ::HistoryDealGetDouble(OpenTicket, DEAL_PRICE);. Т.е. вернёт цену открытия 1-й сделки. На мой взгляд, имеет смысл сделать единообразно, либо тянуть всё с первой сделки (и цену открытия, и профит), либо тянуть всё с последнего открытия (с 3-й сделки в клиринг). Или это фича, и так должно быть, и я что-то упускаю?
 
traveller00:
Не знаю, баг или фича, но для фьючерсов профит и цена открытия считаются не совсем так, как ожидается. Допустим, происходит открытие позиции в 12.00, в 18.40 происходит клиринг и автоматическое переоткрытие позиции, после чего в 20.00 позиция закрывается. В итоге получается 4 сделки (вход-выход и 2 сделки клиринга). GetHistoryPositionData для тикета 4-й сделки (выхода из позиции) выбирает профит как MT4ORDERS::Order.Profit = ::HistoryDealGetDouble(Ticket, DEAL_PROFIT); Что вернёт по сути разницу между сделками 3-4 (клирингом и выходом). Но цену открытия он вернёт как MT4ORDERS::Order.OpenPrice = ::HistoryDealGetDouble(OpenTicket, DEAL_PRICE);. Т.е. вернёт цену открытия 1-й сделки. На мой взгляд, имеет смысл сделать единообразно, либо тянуть всё с первой сделки (и цену открытия, и профит), либо тянуть всё с последнего открытия (с 3-й сделки в клиринг). Или это фича, и так должно быть, и я что-то упускаю?

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

На Неттинге использую все так же библиотеку, но обхожу работу с историей.

 

https://www.mql5.com/ru/blogs/post/733393


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

#include <MT4Orders.mqh>

#define BENCH(A)                                                               \
{                                                                              \
  const ulong _StartTime = GetMicrosecondCount();                              \
  A;                                                                           \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - _StartTime)); \
}

void OnStart()
{
  BENCH(HistorySelectByPosition(270107))
  BENCH(HistorySelectByPosition(270107))

  BENCH(HistorySelect(0, INT_MAX))
  BENCH(HistorySelect(0, INT_MAX))

  BENCH(OrdersHistoryTotal())
  BENCH(OrdersHistoryTotal())

  BENCH(OrderSelect(270107, SELECT_BY_TICKET, MODE_HISTORY))
  BENCH(OrderPrint());

  BENCH(OrderSelect(1000, SELECT_BY_POS, MODE_HISTORY))
  BENCH(OrderPrint());
}


Результат.

Time[HistorySelectByPosition(270107)] = 9232 // Холодный запуск.
Time[HistorySelectByPosition(270107)] = 8571 // Горячий запуск.

Time[HistorySelect(0,INT_MAX)] = 152856 // Холодный запуск.
Time[HistorySelect(0,INT_MAX)] = 94924  // Горячий запуск.

Time[OrdersHistoryTotal()] = 155735 // Холодный запуск.
Time[OrdersHistoryTotal()] = 6774   // Горячий запуск.

Time[OrderSelect(270107,1,1)] = 23 // Бесплатно.
#85469 2020.02.05 22:32:12 buy 0.01 USDCNH 6.97767 0.00000 6.98533 2020.02.05 22:32:13 6.97533 0.00 0.00 -0.34 OrderSendTest_Position 0
Time[OrderPrint()] = 20 // Бесплатно.

Time[OrderSelect(1000,0,1)] = 11 // Бесплатно.
#10613 2020.02.06 02:34:32 buy 0.01 EURUSD 1.10049 0.00000 1.11046 2020.02.06 02:34:32 1.10046 0.00 0.00 -0.03 OrderSendTest_Position 0
Time[OrderPrint()] = 13 // Бесплатно.


Хорошо видно, во сколько обходятся HistorySelect-функции.

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

OrderSelect по истории оказался бесплатен.

Особенности исполнения торговых приказов MT5
Особенности исполнения торговых приказов MT5
  • www.mql5.com
Анализировал с владельцем MT5-сервера тормоза торговых приказов. Запускался OrderSend-Test2.mq5 в том же месте, где MT5-сервер стоит. Т.е. нулевой пинг. Демо, все внутри. Изучались логи MT5-сервера (2170) и MT5-клиента (2280). Логи сервера не буду приводить, просто словами опишу. Думаю, результаты буду интерсны всем, т.к. это поможет раскрыть...
 

Можно собрать статистику по времени, затраченному на исполнение маркет-ордеров (включая TP/SL).

//Статистика по затраченному времени на исполнение маркет-ордеров (включая TP/SL).
#property script_show_inputs

input datetime inFrom = 0;
input datetime inTo = INT_MAX;

struct ORDER
{
  ulong Ticket;
  
  ulong FillingTime;
  
  string ToString( void ) const
  {
    return((string)Ticket + ": " + ::TimeToString(this.FillingTime / 1000, TIME_SECONDS) +
                            "." + ::IntegerToString(this.FillingTime % 1000, 3, '0'));
  }
};

// Собирает данные по затраченному времени на исполнение маркет-ордеров
int GetOrders( ORDER &Orders[], const datetime From = 0, const datetime To = INT_MAX )
{
  int Amount = 0;
  
  if (HistorySelect(From, To)) // Если есть записи в истории
    for (int i = ArrayResize(Orders, HistoryOrdersTotal()) - 1; i >= 0; i--) // Бежим по выборке ордеров
    {
      const ulong TicketOrder = HistoryOrderGetTicket(i); // Выбрали ордер
      
      if ((HistoryOrderGetInteger(TicketOrder, ORDER_TYPE) <= ORDER_TYPE_SELL) &&   // Если маркет-ордер
          (HistoryOrderGetInteger(TicketOrder, ORDER_STATE) == ORDER_STATE_FILLED)) // Если ордер исполнился
      {
        Orders[Amount].Ticket = TicketOrder;
        
        // Запомнили затраченное время на исполнение.
        Orders[Amount++].FillingTime = HistoryOrderGetInteger(TicketOrder, ORDER_TIME_DONE_MSC) -
                                       HistoryOrderGetInteger(TicketOrder, ORDER_TIME_SETUP_MSC);
      }
      }
  
  return(ArrayResize(Orders, Amount));
}

// #include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

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

void OnStart()
{
  ORDER Orders[];
  
  if (GetOrders(Orders, inFrom, inTo))
  {
    ArraySortStruct(Orders, FillingTime); // https://www.mql5.com/ru/forum/170952/page166#comment_15151387
    
    // Распечатали самые длительные по исполнению маркет-ордера.
    for (int i = ArraySize(Orders) - 1, k = 0; (i >= 0) && (k < 10); i--, k++)
    {
      Print((string)k + " - " + Orders[i].ToString());

    #ifdef __MT4ORDERS__
      if (OrderSelect(Orders[i].Ticket, SELECT_BY_TICKET))
      {
        OrderPrint();
        
        PRINT(OrderTicketID());
        PRINT(OrderTicketOpen());
  
        Print("-------------------");      
      }
    #endif // __MT4ORDERS__        
    }
  }
}


Результат.

0 - 348806: 00:01:57.311
1 - 348530: 00:01:39.027
2 - 348494: 00:01:15.259
3 - 348406: 00:01:07.671
4 - 348950: 00:01:04.869
5 - 348960: 00:01:02.888
6 - 348814: 00:01:00.654
7 - 348392: 00:01:00.642
8 - 348508: 00:00:54.515
9 - 348550: 00:00:54.467


До двух минут исполнение на запущенном счете. Поделитесь здесь своей статой. Скрипт никакие библиотеки не использует, подходит для Неттинг/Хеджа.

 

В MT4/5 вести отладку при работе с историей торгов довольно неприятно. Приходится использовать различные костыльные решения.


В MT5 можно сразу посмотреть все поля выбранного через MT4Orders ордера. Для этого нужно добавить в наблюдение MT4ORDERS::Order.


Так можно видеть все свойства выбранного ордера.

 
fxsaber:

Поделитесь здесь своей статой. Скрипт никакие библиотеки не использует, подходит для Неттинг/Хеджа.

Вот такой есть реал:

2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      0 - 34487054: 00:00:06.768
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      1 - 34487223: 00:00:06.166
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      2 - 49869622: 00:00:03.656
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      3 - 34486559: 00:00:02.833
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      4 - 34486482: 00:00:02.051
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      5 - 34486480: 00:00:02.023
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      6 - 34486467: 00:00:01.983
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      7 - 42624984: 00:00:01.589
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      8 - 33738445: 00:00:01.088
2020.02.27 14:53:30.275 ExecutionSpeed (EURUSD,H1)      9 - 42625044: 00:00:00.932
 

И еще один:

2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      0 - 1532297: 00:00:14.989
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      1 - 1528006: 00:00:04.983
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      2 - 1527412: 00:00:03.543
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      3 - 1528097: 00:00:01.812
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      4 - 1478424: 00:00:01.502
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      5 - 1478368: 00:00:01.502
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      6 - 1478410: 00:00:01.502
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      7 - 1478344: 00:00:01.501
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      8 - 1733682: 00:00:01.480
2020.02.27 14:59:50.616 ExecutionSpeed (EURUSD,H1)      9 - 737378: 00:00:00.346
 
Andrey Khatimlianskii:

Вот такой есть реал:

Спасибо за информацию. Такое длительное исполнение, наверное, связано со сторонними шлюзами. Интересно, как на биржах.

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