Структура торговой транзакции (MqlTradeTransaction)

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

  • Отсылка торгового запроса любым MQL5-приложением в клиентском терминале при помощи функций OrderSend и OrderSendAsync и его последующее исполнение;
  • Отсылка торгового запроса через графический интерфейс терминала и его последующее исполнение;
  • Срабатывания отложенных ордеров и стоп-ордеров на сервере;
  • Выполнения операций на стороне торгового сервера.

В результате данных действий для счета выполняются торговые транзакции:

  • обработка торгового запроса;
  • изменение открытых ордеров;
  • изменение истории ордеров;
  • изменение истории сделок;
  • изменение позиций.

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

Для получения торговых транзакций, примененных к счету, в MQL5 предусмотрен специальный обработчик OnTradeTransaction(). В первый параметр этого обработчика передается структура MqlTradeTransaction, описывающая торговые транзакции.

struct MqlTradeTransaction
  {
   ulong                         deal;             // Тикет сделки
   ulong                         order;            // Тикет ордера
   string                        symbol;           // Имя торгового инструмента
   ENUM_TRADE_TRANSACTION_TYPE   type;             // Тип торговой транзакции
   ENUM_ORDER_TYPE               order_type;       // Тип ордера
   ENUM_ORDER_STATE              order_state;      // Состояние ордера
   ENUM_DEAL_TYPE                deal_type;        // Тип сделки
   ENUM_ORDER_TYPE_TIME          time_type;        // Тип ордера по времени действия
   datetime                      time_expiration;  // Срок истечения ордера
   double                        price;            // Цена 
   double                        price_trigger;    // Цена срабатывания стоп-лимитного ордера
   double                        price_sl;         // Уровень Stop Loss
   double                        price_tp;         // Уровень Take Profit
   double                        volume;           // Объем в лотах
   ulong                         position;         // Тикет позиции
   ulong                         position_by;      // Тикет встречной позиции
  };

Описание полей

Поле

Описание

deal

Тикет сделки.

order

Тикет ордера.

symbol

Имя торгового инструмента, по которому совершена транзакция.

type

Тип торговой транзакции. Значение может быть одним из значений перечисления ENUM_TRADE_TRANSACTION_TYPE.

order_type

Тип торгового ордера. Значение может быть одним из значений перечисления ENUM_ORDER_TYPE.

order_state

Состояние торгового ордера. Значение может быть одним из значений перечисления ENUM_ORDER_STATE.

deal_type

Тип сделки. Значение может быть одним из значений перечисления ENUM_DEAL_TYPE.

time_type

Тип ордера по истечению. Значение может быть одним из значений ENUM_ORDER_TYPE_TIME.

time_expiration

Срок истечения отложенного ордера (для ордеров типа ORDER_TIME_SPECIFIED и ORDER_TIME_SPECIFIED_DAY).

price

Цена. В зависимости от типа торговой транзакции может быть ценой ордера, сделки или позиции.

price_trigger

Стоп-цена (цена срабатывания) стоп-лимитного ордера (ORDER_TYPE_BUY_STOP_LIMIT и ORDER_TYPE_SELL_STOP_LIMIT).

price_sl

Цена Stop Loss. В зависимости от типа торговой транзакции может относиться к ордеру, сделке или позиции.

price_tp

Цена Take Profit. В зависимости от типа торговой транзакции может относиться к ордеру, сделке или позиции.

volume

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

position

Тикет позиции, на которую повлияла транзакция.

position_by

Тикет встречной позиции. Используется при закрытии позиции встречной — открытой по тому же инструменту, но в противоположном направлении.

Определяющим параметром для анализа поступившей транзакции является ее тип, который передается в поле type. Например, если транзакция является типом TRADE_TRANSACTION_REQUEST (получен результат обработки торгового запроса сервером), то структура имеет только одно заполненное поле type, остальные поля анализировать не нужно. В этом случае можно произвести анализ двух дополнительных параметров request и result, которые передаются в обработчик OnTradeTransaction(), как это показано в примере ниже.

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

Структура MqlTradeTransaction заполняется по-разному в зависимости от типа торговой транзакции (ENUM_TRADE_TRANSACTION_TYPE):

TRADE_TRANSACTION_ORDER_* и TRADE_TRANSACTION_HISTORY_*

Для торговых транзакций, касающихся обработки открытых ордеров (TRADE_TRANSACTION_ORDER_ADD, TRADE_TRANSACTION_ORDER_UPDATE и TRADE_TRANSACTION_ORDER_DELETE) и истории ордеров (TRADE_TRANSACTION_HISTORY_ADD, TRADE_TRANSACTION_HISTORY_UPDATE, TRADE_TRANSACTION_HISTORY_DELETE), в структуре MqlTradeTransaction заполняются следующие поля:

  • order - тикет ордера;
  • symbol - имя финансового инструмента в ордере;
  • type - тип торговой транзакции;
  • order_type - тип ордера;
  • orders_state - текущее состояние ордера;
  • time_type - тип истечения ордера;
  • time_expiration - время истечения ордера (для ордеров с типом истечения ORDER_TIME_SPECIFIED и ORDER_TIME_SPECIFIED_DAY);
  • price - цена в ордере, указанная клиентом;
  • price_trigger - стоп-цена срабатывания стоп-лимитного ордера (только для ORDER_TYPE_BUY_STOP_LIMIT и ORDER_TYPE_SELL_STOP_LIMIT);
  • price_sl - цена Stop Loss ордера (заполняется, если указана в ордере);
  • price_tp - цена Take Profit ордера (заполняется, если указана в ордере);
  • volume - текущий объем ордера (не исполненный). Изначальный объем ордера можно узнать из истории ордеров при помощи функций HistoryOrders*.
  • position - тикет позиции, открытой, измененной или закрытой в результате исполнения ордера. Заполняется только для рыночных ордеров. Не заполняется для TRADE_TRANSACTION_ORDER_ADD.
  • position_by - тикет встречной позиции. Заполняется только для ордеров на закрытие позиции встречной (close by).

TRADE_TRANSACTION_DEAL_*

Для торговых транзакций, касающихся обработки сделок (TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_DEAL_UPDATE и TRADE_TRANSACTION_DEAL_DELETE), в структуре MqlTradeTransaction заполняются следующие поля:

  • deal - тикет сделки;
  • order - тикет ордера, на основе которого совершена сделка;
  • symbol - имя финансового инструмента в сделке;
  • type - тип торговой транзакции;
  • deal_type - тип сделки;
  • price - цена, по которой совершена сделка;
  • price_sl - цена Stop Loss (заполняется, если указана в ордере, на основе которого совершена сделка);
  • price_tp - цена Take Profit (заполняется, если указана в ордере, на основе которого совершена сделка);
  • volume - объем сделки в лотах.
  • position - тикет позиции, открытой, измененной или закрытой в результате исполнения сделки.
  • position_by - тикет встречной позиции. Заполняется только для сделок на закрытие позиции встречной (out by).

TRADE_TRANSACTION_POSITION

Для торговых транзакций, касающихся изменений позиций, не связанных с исполнением сделок (TRADE_TRANSACTION_POSITION), в структуре MqlTradeTransaction заполняются следующие поля:

  • symbol - имя финансового инструмента позиции;
  • type - тип торговой транзакции;
  • deal_type - тип позиции (DEAL_TYPE_BUY или DEAL_TYPE_SELL);
  • price - средневзвешенная цена открытия позиции;
  • price_sl - цена Stop Loss;
  • price_tp - цена Take Profit;
  • volume - объем позиции в лотах, если он был изменен.
  • position - тикет позиции.

Изменение позиции (добавление, изменение или ликвидация) в результате совершения сделки не влечет за собой появление транзакции TRADE_TRANSACTION_POSITION.

TRADE_TRANSACTION_REQUEST

Для торговых транзакций, описывающих факт, что торговый запрос обработан сервером, и результат его обработки получен (TRADE_TRANSACTION_REQUEST), в структуре MqlTradeTransaction заполняется только одно поле:

  • type - тип торговой транзакции;

Для транзакций данного типа необходимо анализировать только одно поле - type (тип торговой транзакции). Для получения дополнительной информации необходимо анализировать второй и третий параметры функции OnTradeTransaction (request и result).

Пример:

input int MagicNumber=1234567;
 
//--- подключим торговый класс CTrade и объявим переменную этого типа
#include <Trade\Trade.mqh>
CTrade trade;
//--- флаги для установки и удаления отложенного ордера
bool pending_done=false;
bool pending_deleted=false;
//--- здесь будем хранить тикет отложенного ордера
ulong order_ticket;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- установим MagicNumber, которым будут помечаться все наши ордера
   trade.SetExpertMagicNumber(MagicNumber);
//--- торговые запросы будем отправлять в асинхронном режиме с помощью функции OrderSendAsync()
   trade.SetAsyncMode(true);
//--- инициализируем переменную нулем
   order_ticket=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- установка отложенного ордера
   if(!pending_done)
     {
      double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
      double buy_stop_price=NormalizeDouble(ask+1000*_Point,(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS));
      bool res=trade.BuyStop(0.1,buy_stop_price,_Symbol);
      //--- если функция BuyStop() отработала успешно 
      if(res)
        {
         pending_done=true;
         //--- получим результат отправки запроса из ctrade
         MqlTradeResult trade_result;
         trade.Result(trade_result);
         //--- получим request_id для отправленного запроса
         uint request_id=trade_result.request_id;
         Print("Отправлен запрос на установку отложенного ордера. Идентификатор запроса Request_ID=",request_id);
         //--- запомним тикет ордера (при использовании асинхронного режима отправки в CTrade будет равен нулю)
         order_ticket=trade_result.order;
         //--- всё сделано, поэтому досрочно выходим из обработчика OnTick()
         return;
        }
     }
//--- удаление отложенного ордера
   if(!pending_deleted)
      //--- дополнительная проверка
      if(pending_done && (order_ticket!=0))
        {
         //--- попытаемся удалить отложенный ордер
         bool res=trade.OrderDelete(order_ticket);
         Print("OrderDelete=",res);
         //--- при успешной отправке запроса на удаление
         if(res)
           {
            pending_deleted=true;
            //--- получим результат выполнения запроса
            MqlTradeResult trade_result;
            trade.Result(trade_result);
            //--- вытащим из результата идентификатор запроса
            uint request_id=trade_result.request_id;
            //--- выведем в Журнал
            Print("Отправлен запрос на удаление отложенного ордера #",order_ticket,
                  ". Идентификатор запроса Request_ID=",request_id,
                  "\r\n");
            //--- запишем из результата запроса тикет ордера
            order_ticket=trade_result.order;
           }
        }
//---        
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- получим тип транзакции в виде значения перечисления 
   ENUM_TRADE_TRANSACTION_TYPE type=(ENUM_TRADE_TRANSACTION_TYPE)trans.type;
//--- если транзакция является результатом обработки запроса, выведем только её название
   if(type==TRADE_TRANSACTION_REQUEST)
     {
      Print(EnumToString(type));
      //--- выведем строковое описание обработанного запроса
      Print("------------RequestDescription\r\n",RequestDescription(request));
      //--- выведем описание результата запроса
      Print("------------ResultDescription\r\n",TradeResultDescription(result));
      //--- запомним тикет ордера для его удаления на следующей обработке в OnTick()
      if(result.order!=0)
        {
         //--- удалим этот ордер по его тикету при следующем вызове OnTick()
         order_ticket=result.order;
         Print(" Тикет отложенного ордера ",order_ticket,"\r\n");
        }
     }
   else // для транзакций другого типа выведем полное описание
//--- выведем описание полученной транзакции в Журнал
      Print("------------TransactionDescription\r\n",TransactionDescription(trans));
 
//---     
  }
//+------------------------------------------------------------------+
//| Возвращает текстовое описание транзакции                         |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans)
  {
//--- 
   string desc=EnumToString(trans.type)+"\r\n";
   desc+="Symbol: "+trans.symbol+"\r\n";
   desc+="Deal ticket: "+(string)trans.deal+"\r\n";
   desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
   desc+="Order ticket: "+(string)trans.order+"\r\n";
   desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
   desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
   desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
   desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
   desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
   desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
   desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
   desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
   desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
   desc+="Position: "+(string)trans.position+"\r\n";
   desc+="Position by: "+(string)trans.position_by+"\r\n";
//--- вернем полученную строку
   return desc;
  }
//+------------------------------------------------------------------+
//| Возвращает текстовое описание торгового запроса                  |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request)
  {
//---
   string desc=EnumToString(request.action)+"\r\n";
   desc+="Symbol: "+request.symbol+"\r\n";
   desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
   desc+="Order ticket: "+(string)request.order+"\r\n";
   desc+="Order type: "+EnumToString(request.type)+"\r\n";
   desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
   desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
   desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
   desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
   desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
   desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
   desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
   desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
   desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
   desc+="Comment: "+request.comment+"\r\n";
//--- вернем полученную строку
   return desc;
  }
//+------------------------------------------------------------------+
//| Возвращает текстовое описание результата обработки запроса       |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result)
  {
//---
   string desc="Retcode "+(string)result.retcode+"\r\n";
   desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
   desc+="Order ticket: "+(string)result.order+"\r\n";
   desc+="Deal ticket: "+(string)result.deal+"\r\n";
   desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
   desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
   desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
   desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
   desc+="Comment: "+result.comment+"\r\n";
//--- вернем полученную строку
   return desc;
  }

Смотри также

Типы торговых транзакций, OnTradeTransaction()