Получение списка действующих ордеров

Программам-экспертам часто требуется выполнять перебор имеющихся активных ордеров и анализировать их свойства. В частности, в разделе о модификации отложенного ордера, в примере PendingOrderModify.mq5 была написана специальная функция GetMyOrder для нахождения "собственных" ордеров эксперта, подлежащих периодическому исправлению. Там анализ проводился по имени символа и идентификатору эксперта (Magic-номеру). В принципе, такой же подход должен был бы применяться и в примере удаления отложенного ордера PendingOrderDelete.mq5 из предыдущего раздела.

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

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

int OrdersTotal()

Функция OrdersTotal возвращает количество активных в данный момент ордеров. В их число входят отложенные ордера, а также рыночные, которые еще не исполнены. Как правило, рыночный ордер исполняется оперативно и потому застать его в активной фазе можно не часто, но на тонком рынке, при отсутствии ликвидности, такое может случиться. Как только ордер исполняется (по нему заключается сделка), он переводится из разряда действующих в историю. О работе с историей ордеров мы поговорим в отдельном разделе.

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

ulong OrderGetTicket(uint index)

Функция OrderGetTicket возвращает тикет ордера по его номеру в списке ордеров в торговом окружении терминала. Параметр index должен быть в пределах от 0 до значения OrdersTotal()-1 включительно. Порядок следования ордеров не регламентирован.

Функция OrderGetTicket выбирает ордер, то есть копирует данные о нем в некий внутренний кеш, так что MQL-программа может читать все его свойства с помощью последующих вызовов функций OrderGetDouble, OrderGetInteger, OrderGetString, о которых речь пойдет в отдельном разделе.

Наличие такого кеша означает, что полученные из него данные могут рано или поздно устареть: самого ордера может уже не быть или в нем могут измениться какие-то свойства (например, статус, цена открытия, уровни Stop Loss или Take Profit, срок истечения). Поэтому для гарантированного получения свежих данных об ордере рекомендуется вызывать функцию OrderGetTicket непосредственно перед обращением за ними. Напомним, как это происходило в примере PendingOrderModify.mq5.

ulong GetMyOrder(const string nameconst ulong magic)
{
   for(int i = 0i < OrdersTotal(); ++i)
   {
      ulong t = OrderGetTicket(i);
      if(OrderGetInteger(ORDER_MAGIC) == magic
      && OrderGetString(ORDER_SYMBOL) == name)
      {
         return t;
      }
   }
   return 0;
}

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

Аналогичное выделение ордера с копированием его данных во внутренний кеш выполняет и функция OrderSelect.

bool OrderSelect(ulong ticket)

Функция проверяет наличие ордера и подготавливает возможность дальнейшего чтения его свойств. В данном случае ордер задается не по порядковому номеру, а по тикету, который должен быть так или иначе получен MQL-программой ранее, в частности, в результате выполнения OrderSend/OrderSendAsync.

Функция возвращает true в случае успеха. Значение false, как правило, означает, что ордера с указанным тикетом не существует. Наиболее частая причина для этого — переход ордера из разряда действующих в исторические, например, в результате исполнения или отмены (точный статус мы научимся определять позднее). Для выделения ордеров в истории существуют другие функции.

Ранее мы использовали функцию OrderSelect в структуре MqlTradeResultSync для отслеживания создания и удаления отложенного ордера.