Удаление отложенного ордера

Удаление отложенного ордера выполняется на программном уровне с помощью операции TRADE_ACTION_REMOVE: эту константу следует присвоить полю action структуры MqlTradeRequest перед вызовом одной из разновидностей функции OrderSend. Единственным обязательным полем, помимо action, является order, куда следует записать тикет удаляемого ордера.

В связи с этим метод remove в прикладной структуре MqlTradeRequestSync из файла MqlTradeSync.mqh довольно простой.

struct MqlTradeRequestSyncpublic MqlTradeRequest
{
   ...
   bool remove(const ulong ticket)
   {
      if(!OrderSelect(ticket)) return false;
      action = TRADE_ACTION_REMOVE;
      order = ticket;
      ZeroMemory(result);
      return OrderSend(thisresult);
   }

Проверка факта удаления ордера делается по традиции в методе completed.

   bool completed()
   {
      ...
      else if(action == TRADE_ACTION_REMOVE)
      {
         result.order = order;
         return result.removed(timeout);
      }
      ...
   }

Ожидание фактического удаления ордера производится в методе removed структуры MqlTradeResultSync, также по привычной схеме.

struct MqlTradeResultSyncpublic MqlTradeResult
{
   ...
   bool removed(const ulong msc = 1000)
   {
      if(retcode != TRADE_RETCODE_DONE)
      {
         return false;
      }
   
      if(!wait(orderRemovedmsc))
      {
         Print("Order removal timeout: #=" + (string)order);
         return false;
      }
      
      return true;
   }
   
   static bool orderRemoved(MqlTradeResultSync &ref)
   {
      return !OrderSelect(ref.order) && HistoryOrderSelect(ref.order);
   }

Пример эксперта (PendingOrderDelete.mq5), демонстрирующего удаление ордера, построим практически целиком на PendingOrderSend.mq5. Это обусловлено тем, что так проще гарантировать наличие ордера перед удалением. Таким образом, сразу после запуска эксперт создаст новый ордер с заданными параметрами, а его удаление осуществляется в обработчике OnDeinit. Если изменить входные параметры советника, символ или таймфрейм графика, старый ордер также будет удален, а новый создан.

Для хранения тикета ордера заведена глобальная переменная OwnOrder, которая заполняется в результате вызова PlaceOrder (сама функция — без изменений).

ulong OwnOrder = 0;
   
void OnTimer()
{
   // однократно выполняем код для текущих параметров
   EventKillTimer();
   
   const string symbol = StringLen(Symbol) == 0 ? _Symbol : Symbol;
   OwnOrder = PlaceOrder((ENUM_ORDER_TYPE)TypesymbolVolume,
      Distance2SLTPExpirationUntilMagicComment);
}

Для удаления написана простая функция RemoveOrder, создающая объект request и вызывающая для него последовательно методы remove и completed.

void OnDeinit(const int)
{
   if(OwnOrder != 0)
   {
      RemoveOrder(OwnOrder);
   }
}
   
void RemoveOrder(const ulong ticket)
{
   MqlTradeRequestSync request;
   if(request.remove(ticket) && request.completed())
   {
      Print("OK order removed");
   }
   Print(TU::StringOf(request));
   Print(TU::StringOf(request.result));
}

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

(EURUSD,H1)        Autodetected daily range: 0.0094

(EURUSD,H1)        OK order placed: #=1284920879

(EURUSD,H1)        TRADE_ACTION_PENDING, EURUSD, ORDER_TYPE_BUY_STOP, V=0.01, ORDER_FILLING_FOK, »

                » @ 1.11011, ORDER_TIME_GTC, M=1234567890

(EURUSD,H1)        DONE, #=1284920879, V=0.01, Request executed, Req=1

(EURUSD,H1)        OK order removed

(EURUSD,H1)        TRADE_ACTION_REMOVE, EURUSD, ORDER_TYPE_BUY, ORDER_FILLING_FOK, #=1284920879

(EURUSD,H1)        DONE, #=1284920879, Request executed, Req=2

(XAUUSD,H1)        Autodetected daily range: 47.45

(XAUUSD,H1)        OK order placed: #=1284921672

(XAUUSD,H1)        TRADE_ACTION_PENDING, XAUUSD, ORDER_TYPE_BUY_STOP, V=0.01, ORDER_FILLING_FOK, »

                » @ 1956.68, ORDER_TIME_GTC, M=1234567890

(XAUUSD,H1)        DONE, #=1284921672, V=0.01, Request executed, Req=3

(XAUUSD,H1)        OK order removed

(XAUUSD,H1)        TRADE_ACTION_REMOVE, XAUUSD, ORDER_TYPE_BUY, ORDER_FILLING_FOK, #=1284921672

(XAUUSD,H1)        DONE, #=1284921672, Request executed, Req=4

Мы рассмотрим другой пример удаления ордеров для реализации стратегии "One Cancel Other" (OCO) в разделе о событиях OnTrade.