Получение истории по OrderCloseBy через MQL

 

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


Однако при попытке прочитать эту историю через цикл с OrderSelect и OrderPrint получается такая штука:

: #2 2017.01.02 09:15:00 sell 0.41 EURUSD 1.05210 0.00000 0.00000 2017.01.02 09:15:00 1.05142 0.00 0.00 27.88  346548
: #1 2017.01.02 09:00:00 buy 0.00 EURUSD 1.05142 0.00000 0.00000 2017.01.02 09:15:00 1.05142 0.00 0.00 0.00 close hedge by #2 346548
: #3 2017.01.02 09:15:00 sell 0.01 EURUSD 1.05210 0.00000 0.00000 2017.01.02 09:30:00 1.05195 0.00 0.00 0.15  346548
: #4 2017.01.02 09:30:00 buy 0.00 EURUSD 1.05195 0.00000 0.00000 2017.01.02 09:30:00 1.05195 0.00 0.00 0.00 close hedge by #3 346548
: #7 2017.01.02 10:00:00 buy 0.01 EURUSD 1.05150 0.00000 0.00000 2017.01.02 10:00:00 1.05189 0.00 0.00 0.39  346548
: #6 2017.01.02 09:45:00 sell 0.00 EURUSD 1.05189 0.00000 0.00000 2017.01.02 10:00:00 1.05189 0.00 0.00 0.00 close hedge by #7 346548
: #9 2017.01.02 10:30:00 buy 0.01 EURUSD 1.05122 0.00000 0.00000 2017.01.02 10:30:00 1.05150 0.00 0.00 0.28  346548
: #8 2017.01.02 10:15:00 sell 0.00 EURUSD 1.05150 0.00000 0.00000 2017.01.02 10:30:00 1.05150 0.00 0.00 0.00 close hedge by #9 346548
: #11 2017.01.02 11:00:00 buy 0.01 EURUSD 1.04897 0.00000 0.00000 2017.01.02 11:00:00 1.05099 0.00 0.00 2.02  346548
: #10 2017.01.02 10:45:00 sell 0.00 EURUSD 1.05099 0.00000 0.00000 2017.01.02 11:00:00 1.05099 0.00 0.00 0.00 close hedge by #11 346548
: #12 2017.01.02 11:00:00 buy 0.12 EURUSD 1.04897 0.00000 0.00000 2017.01.02 11:00:00 1.05210 0.00 0.00 37.56  346548
: #5 2017.01.02 09:15:00 sell 0.00 EURUSD 1.05210 0.00000 0.00000 2017.01.02 11:00:00 1.05210 0.00 0.00 0.00 close hedge by #12 346548

Соответствия не наблюдается. Единственное полезное, что видно - так это ссылки на закрываемый ордер в тексте комментария. Но лоты, времена отличаются.

Вопрос: каким образом из кода MQL можно получить аналог таблицы выводимой тестером?

 
Сортировка по времени?
 

Чтобы установить соответствие между текущим выбранным ордером и его родителем после частичного или встречного закрытия, используйте следующий подход:

//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Определение наличия родительского ордера для текущего ордера (по итогам встречного или частичного закрытия)                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetSignOfPartialOrCloseByClose()
{
   string comment = OrderComment();
   if (comment == "")
      return 0;
  
   // Ордер образовался вследствии частичного закрытия
   int fromStart = StringFind(comment, "from #");
   if (fromStart >= 0)
      return GetTicketByPartialClose(comment, fromStart, OrderType(), OrderOpenTime());
  
   // Ордер образовался вследствии встречного закрытия
   if (StringFind(comment, "partial close") >= 0)
   {
      datetime openTime = OrderOpenTime();
      int type = OrderType();
      for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
      {
         if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
            continue;
            
         if (OrderOpenTime() != openTime)
            continue;
            
         if (OrderType() != type)
            continue;
            
         if (StringFind(OrderComment(), "partial close") < 0)
            continue;
            
         return OrderTicket();
      }
   }
  
   return 0;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Получение тикета родительского ордера после частичного закрытия                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetTicketByPartialClose(string comment, int fromStart, int orderType, datetime openTime)
{
   string sTicket = StringSubstr(comment, fromStart + 6);
   int iTicket = (int)StringToInteger(sTicket);
   int type = OrderType();
   if (!OrderSelect(iTicket, SELECT_BY_TICKET))
      return 0;
      
   if (OrderType() == type)                                                                        // Дочерний ордер указывает на родителя - уходим
      return iTicket;
      
   // Дочерний ордер указывает на противоположный ордер. Необходимо искать родительский
   for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
         continue;
        
      if (OrderType() != orderType || OrderOpenTime() != openTime)
         continue;
        
      int iFind = StringFind(OrderComment(), "close hedge by #");
      if (iFind < 0)
         continue;
        
      sTicket = StringSubstr(OrderComment(), iFind + 16);
      int iNewTicket = (int)StringToInteger(sTicket);
      if (iNewTicket != iTicket)
         continue;
        
      return OrderTicket();
   }
  
   return 0;
}


 

 
Ihor Herasko:

Чтобы установить соответствие между текущим выбранным ордером и его родителем после частичного или встречного закрытия, используйте следующий подход:


 

Спасибо за код, но есть пара вопросов. Как видно, в моем отчете - не знаю почему - нет ордеров с комментами, содержащими "from #". Соответственно, обработка ордеров с комментом "close hedge by #" не происходит. Но это еще полбеды. Проблема не столько в поиске встречных ордеров, сколько в определении их правильных параметров. Мне не ясно, почему согласно OrderPrint лоты и даты - кривые, т.е. не соответствуют тому, что видно в отчете тестера.
 
fxsaber:
Сортировка по времени?
Сортировка по-умолчанию, то есть по порядку наполнения истории. Можно видеть что в отчете тестера показано все до #11 ордера, в логе - до #12 (порядок другой - по времени закрытия, насколько я понимаю).
 
Stanislav Korotky:
в моем отчете - не знаю почему - нет ордеров с комментами, содержащими "from #".

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

У вас есть частичное закрытие в отчете? вот поэтому и нет такого комента.


почему согласно OrderPrint лоты и даты - кривые, т.е. не соответствуют тому, что видно в отчете тестера.
покажите что конкретно неверно в отчете. не видно пока что несоответствий
 
Stanislav Korotky:
Сортировка по-умолчанию, то есть по порядку наполнения истории. Можно видеть что в отчете тестера показано все до #11 ордера, в логе - до #12 (порядок другой - по времени закрытия, насколько я понимаю).

Да, по времени закрытия хранит.

fxsaber:
Сортировка по времени?

Плохо сформулировал мысль. Имел в виду, что нужно сделать сортировку по времени + номер тикета. Тогда все встанет на свои места - как в отчете тестера

 
o_O:

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

У вас есть частичное закрытие в отчете? вот поэтому и нет такого комента.


покажите что конкретно неверно в отчете. не видно пока что несоответствий

Код я почитал. Ошибок в своей логике не вижу. Поясню подробнее. Блок обработки встречного закрытия производится в функции GetTicketByPartialClose. Она вызывается только при наличии в комменте "from #" - чего нет. Про коммент "partial close" я вообще ничего не говорил - это вы что-то путаете.

По поводу несоответствия. Например, идем по порядку. На картинке #1 это buy 0.41, а #2 - sell 0.54. Потом с помощью #3 делается встречное закрытие 0.41 лота и #4 - это остаточный sell на 0.13. Теперь посмотрите на лог и попробуйте сформулировать алгоритм, как на основе лога получить только что указанные параметры ордеров.

 
fxsaber:

Плохо сформулировал мысль. Имел в виду, что нужно сделать сортировку по времени + номер тикета. Тогда все встанет на свои места - как в отчете тестера. 

Сортировка ж не меняет содержимого. Все тикеты с картинки приведены во фрагменте лога. Если поменять 1 и 2 местами, подтянуть 5 повыше и пр. - разве что-то изменится?
 
Stanislav Korotky:
Сортировка ж не меняет содержимого. Все тикеты с картинки приведены во фрагменте лога. Если поменять 1 и 2 местами, подтянуть 5 повыше и пр. - разве что-то изменится?
Что-то туго соображаю. В чем тогда несоответствие со скрином?
 
fxsaber:
Что-то туго соображаю. В чем тогда несоответствие со скрином?
Я чуть выше написал конкретный вопрос - как вытащить лоты по порядку, начиная с buy 0.41, sell 0.54 и т.д. из лога. Может и я туплю. Ну так просветите, плиз.