OrderSend

Функция OrderSend() предназначена для совершения торговых операций через отправку запросов на торговый сервер.

bool  OrderSend(
   MqlTradeRequest&  request,      // структура запроса
   MqlTradeResult&   result        // структура ответа
   );

Параметры

request

[in]  Указатель на структуру типа MqlTradeRequest, описывающую торговое действие клиента.

result

[in,out]  Указатель на структуру типа MqlTradeResult, описывающую результат торговой операции в случае успешного выполнения (возврата true).

Возвращаемое значение

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

Примечание

Торговый запрос проходит несколько стадий проверок на торговом сервере. В первую очередь проверяется корректность заполнения всех необходимых полей параметра request, и при отсутствии ошибок сервер принимает ордер для дальнейшей обработки. При успешном принятии ордера торговым сервером функция OrderSend() возвращает значение true.

Рекомендуется самостоятельно проверить запрос перед отправкой его торговому серверу. Для проверки запроса существует функция OrderCheck(), которая не только проверит достаточность средств для совершения торговой операции, но и вернет в результатах проверки торгового запроса многие другие полезные параметры:

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

При отправке рыночного ордера (MqlTradeRequest.action=TRADE_ACTION_DEAL) успешный результат функции OrderSend() не означает, что ордер был выполнен (исполнены соответствующие сделки): true в этом случае означает только то, что ордер был успешно размещен в торговой системе для дальнейшего выполнения. Торговый сервер может в возвращаемой структуре результата result заполнить значения полей deal или order, если эти данные будут ему известны в момент формирования ответа на вызов OrderSend(). В общем случае событие или события исполнения сделок, соответствующих ордеру, могут произойти уже после того, как будет отправлен ответ на вызов OrderSend(). Поэтому для любого типа торгового запроса при получении результата выполнения OrderSend() необходимо в первую очередь проверять код возврата торгового сервера retcode и код ответа внешней торговой системы retcode_external (при необходимости), которые доступны в возвращаемой структуре результата result.

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

  • истечение срока действия,
  • появление встречного запроса,
  • срабатывание ордера при поступлении цены исполнения,
  • поступление запроса на отмену ордера.

В момент обработки ордера торговый сервер посылает терминалу сообщение о наступлении торгового события Trade, которое можно обработать функцией OnTrade().

Результат исполнения торгового запроса на сервере, отправленного функцией OrderSend() можно отслеживать при помощи обработчика OnTradeTransaction. При этом следует учитывать, что в результате исполнения одного торгового запроса обработчик OnTradeTransaction будет вызван несколько раз.

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

Пример:

//--- значения для ORDER_MAGIC
input long order_magic=55555;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- убедимся,что счет является учебным
   if(AccountInfoInteger(ACCOUNT_TRADE_MODE)==ACCOUNT_TRADE_MODE_REAL)
     {
      Alert("Работа скрипта на реальном счете запрещена!");
      return;
     }
//--- установим либо удалим ордер
   if(GetOrdersTotalByMagic(order_magic)==0) 
     {
      //--- текущих ордеров нет - установим ордер
      uint res=SendRandomPendingOrder(order_magic);
      Print("Код возврата торгового сервера ",res);
     }
   else // ордера есть - удалим ордера
     {
      DeleteAllOrdersByMagic(order_magic);
     }
//---
  }
//+------------------------------------------------------------------+
//| Получает текущее количество ордеров с указанным ORDER_MAGIC      |
//+------------------------------------------------------------------+
int GetOrdersTotalByMagic(long const magic_number)
  {
   ulong order_ticket;
   int total=0;
//--- пройдем по всем отложенным ордерам
   for(int i=0;i<OrdersTotal();i++)
      if((order_ticket=OrderGetTicket(i))>0)
         if(magic_number==OrderGetInteger(ORDER_MAGIC)) total++;
//---
   return(total);
  }
//+------------------------------------------------------------------+
//| Удаляет все отложенные ордера с указанным ORDER_MAGIC            |
//+------------------------------------------------------------------+
void DeleteAllOrdersByMagic(long const magic_number)
  {
   ulong order_ticket;
//--- пройдем по всем отложенным ордерам
   for(int i=OrdersTotal()-1;i>=0;i--)
      if((order_ticket=OrderGetTicket(i))>0)
         //--- ордер с подходящим ORDER_MAGIC
         if(magic_number==OrderGetInteger(ORDER_MAGIC))
           {
            MqlTradeResult result={};
            MqlTradeRequest request={};
            request.order=order_ticket;
            request.action=TRADE_ACTION_REMOVE;
            OrderSend(request,result);
            //--- выведем в лог ответ сервера  
            Print(__FUNCTION__,": ",result.comment," код ответа ",result.retcode);
           }
//---
  }
//+------------------------------------------------------------------+
//| Установить случайным образом отложенный ордер                    |
//+------------------------------------------------------------------+
uint SendRandomPendingOrder(long const magic_number)
  {
//--- готовим запрос
   MqlTradeRequest request={};
   request.action=TRADE_ACTION_PENDING;         // установка отложенного ордера
   request.magic=magic_number;                  // ORDER_MAGIC
   request.symbol=_Symbol;                      // инструмент
   request.volume=0.1;                          // объем в 0.1 лот
   request.sl=0;                                // Stop Loss не указан
   request.tp=0;                                // Take Profit не указан   
//--- сформируем тип ордера
   request.type=GetRandomType();                // тип ордера
//---сформируем цену для отложенного ордера
   request.price=GetRandomPrice(request.type);  // цена для открытия
//--- отправим торговый приказ
   MqlTradeResult result={};
   OrderSend(request,result);
//--- выведем в лог ответ сервера  
   Print(__FUNCTION__,":",result.comment);
   if(result.retcode==10016) Print(result.bid,result.ask,result.price);
//--- вернем код ответа торгового сервера
   return result.retcode;
  }
//+------------------------------------------------------------------+
//| Получить случайным образом тип отложенного типа                  |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetRandomType()
  {
   int t=MathRand()%4;
//---   0<=t<4
   switch(t)
     {
      case(0):return(ORDER_TYPE_BUY_LIMIT);
      case(1):return(ORDER_TYPE_SELL_LIMIT);
      case(2):return(ORDER_TYPE_BUY_STOP);
      case(3):return(ORDER_TYPE_SELL_STOP);
     }
//--- недопустимое значение
   return(WRONG_VALUE);
  }
//+------------------------------------------------------------------+
//| Получить цену случайным образом                                  |
//+------------------------------------------------------------------+
double GetRandomPrice(ENUM_ORDER_TYPE type)
  {
   int t=(int)type;
//--- уровень стопов по символу
   int distance=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
//--- получим данные последнего тика
   MqlTick last_tick={};
   SymbolInfoTick(_Symbol,last_tick);
//--- вычислим цену в соответствие с типом
   double price;
   if(t==2 || t==5) // ORDER_TYPE_BUY_LIMIT или ORDER_TYPE_SELL_STOP
     {
      price=last_tick.bid; // оттолкнемся от цены Bid
      price=price-(distance+(MathRand()%10)*5)*_Point;
     }
   else             // ORDER_TYPE_SELL_LIMIT или ORDER_TYPE_BUY_STOP
     {
      price=last_tick.ask; // оттолкнемся от цены Ask
      price=price+(distance+(MathRand()%10)*5)*_Point;
     }
//---
   return(price);
  }

Смотри также

Типы торговых операций, Структура торгового запроса, Структура результатов проверки торгового запроса, Структура результата торгового запроса