Estructura de transacción comercial (MqlTradeTransaction)

Como resultado de ejecución de ciertas acciones con la cuenta de trading su estado se cambia. A estas acciones les pertenecen:

  • El envío de una solicitud comercial por parte de cualquier aplicación MQL5 en el terminal de cliente utilizando la función OrderSend y OrderSendAsync, con su posterior ejecución;
  • El envío de una solicitud comercial a través de la interfaz gráfica del terminal y su posterior ejecución;
  • El accionamiento de órdenes pendientes y órdenes Stop en el servidor;
  • La ejecución de operaciones en el servidor de trading.

Como resultado de estas acciones, para la cuenta se ejecutan las transacciones comerciales:

  • tramitación de la solicitud comercial;
  • cambio de órdenes abiertas;
  • cambio del historial de órdenes;
  • cambio del historial de operaciones;
  • cambio de posiciones.

Por ejemplo, al enviar una orden de compra, ésta se tramita, para la cuenta se crea una orden de compra correspondiente, se realiza la ejecución de la orden, su eliminación de la lista de las abiertas, se agrega al historial de órdenes, luego la operación correspondiente se agrega al historial, y se crea una posición nueva. Pues todas estas acciones son transacciones comerciales.

Para recibir las transacciones comerciales que se aplican a la cuenta, en MQL5 ha sido diseñado un manejador especial OnTradeTransaction(). En el primer parámetro de este manejador se traspasa la estructura MqlTradeTransaction que describe las transacciones comerciales.

struct MqlTradeTransaction
  {
   ulong                         deal;             // Ticket de la operación
   ulong                         order;            // Ticket de la orden
   string                        symbol;           // Nombre del instrumento financiero
   ENUM_TRADE_TRANSACTION_TYPE   type;             // Tipo de transacción comercial
   ENUM_ORDER_TYPE               order_type;       // Tipo de la orden
   ENUM_ORDER_STATE              order_state;      // Estado de la orden
   ENUM_DEAL_TYPE                deal_type;        // Tipo de la operación
   ENUM_ORDER_TYPE_TIME          time_type;        // Tipo de la orden según el tiempo de ejecución
   datetime                      time_expiration;  // Plazo de vencimiento de la orden
   double                        price;            // Precio 
   double                        price_trigger;    // Precio de activación de la orden stop limitada
   double                        price_sl;         // Nivel Stop Loss
   double                        price_tp;         // Nivel Take Profit
   double                        volume;           // Volumen en lotes
   ulong                         position;         // Position ticket
   ulong                         position_by;      // Comentarios sobre la orden
  };

Descripción de campos

Campo

Descripción

deal

Ticket de la operación.

order

Ticket de la orden.

symbol

Nombre del instrumento financiero para el que se realiza la transacción.

type

Tipo de transacción comercial. El valor puede ser uno de los valores de la enumeración ENUM_TRADE_TRANSACTION_TYPE.

order_type

Tipo de orden comercial. El valor puede ser uno de los valores de la enumeración ENUM_ORDER_TYPE.

order_state

Estado de orden comercial. El valor puede ser uno de los valores de la enumeración ENUM_ORDER_STATE.

deal_type

Tipo de operación. El valor puede ser uno de los valores de la enumeración ENUM_DEAL_TYPE.

time_type

Tipo de la orden según su expiración. El valor puede ser uno de los valores de la enumeración ENUM_ORDER_TYPE_TIME.

time_expiration

Plazo de expiración de la orden pendiente (para las órdenes del tipo ORDER_TIME_SPECIFIED y ORDER_TIME_SPECIFIED_DAY).

price

Precio. En función del tipo de la transacción comercial puede ser el precio de la orden, operación o posición.

price_trigger

Precio stop (precio de activación) de la orden stop limitada (ORDER_TYPE_BUY_STOP_LIMIT y ORDER_TYPE_SELL_STOP_LIMIT).

price_sl

Precio Stop Loss. En función del tipo de la transacción comercial puede referirse al precio de la orden, operación o posición.

price_tp

Precio Take Profit. En función del tipo de la transacción comercial puede referirse al precio de la orden, operación o posición.

volume

Volumen en lotes. En función del tipo de la transacción comercial puede referirse al volumen actual de la orden, volumen de la operación o volumen de la posición.

position

Ticket de la posición a la que ha influido la transacción.

position_by

Ticket de la posición opuesta. Se usa al cerrar una posición con otra opuesta, abierta en el mismo instrumento, pero en dirección contraria.

El parámetro determinante para el análisis de una transacción que llega es su tipo que figura en el campo type. Por ejemplo, si la transacción es del tipo TRADE_TRANSACTION_REQUEST (el resultado de procesamiento de la solicitud por parte del servidor ha sido recibido), entonces la estructura tiene sólo un campo rellenado type, los demás no hace falta analizar. En este caso se puede realizar el análisis de dos campos adicionales request y result que se pasan al manejador OnTradeTransaction(), tal como se muestra en el ejemplo de abajo.

Teniendo información sobre el tipo de la operación comercial, se puede tomar la decisión sobre el análisis del estado actual de la orden, posición y transacciones (deals) en la cuenta de trading. Hay que tener en cuenta que una solicitud comercial enviada del terminal al servidor puede provocar varias transacciones (transactions) comerciales, cuya orden de llegada al terminal no se garantiza.

La estructura MqlTradeTransaction se llena de una manera diferente en función del tipo de transacción comercial (ENUM_TRADE_TRANSACTION_TYPE):

TRADE_TRANSACTION_ORDER_* y TRADE_TRANSACTION_HISTORY_*

Para las transacciones comerciales que conciernen el procesamiento de las órdenes abiertas (TRADE_TRANSACTION_ORDER_ADD, TRADE_TRANSACTION_ORDER_UPDATE y TRADE_TRANSACTION_ORDER_DELETE) e historial de órdenes (TRADE_TRANSACTION_HISTORY_ADD, TRADE_TRANSACTION_HISTORY_UPDATE, TRADE_TRANSACTION_HISTORY_DELETE), en la estructura MqlTradeTransaction se llenan los siguientes campos:

  • order - ticket de la orden;
  • symbol - nombre del instrumento financiero en la orden;
  • type - tipo de transacción (transaction) comercial;
  • order_type - tipo de la orden;
  • orders_state - estado actual de la orden;
  • time_type - tipo de vencimiento de la orden;
  • time_expiration - tiempo de expiración de la orden (para las órdenes con el tipo de vencimiento ORDER_TIME_SPECIFIED y ORDER_TIME_SPECIFIED_DAY);
  • price - precio de la orden especificado por el cliente;
  • price_trigger - precio stop de activación de la orden stop limitada (sólo para ORDER_TYPE_BUY_STOP_LIMIT y ORDER_TYPE_SELL_STOP_LIMIT);
  • price_sl - precio Stop Loss de la orden (se rellena si está especificado en la orden);
  • price_tp - precio Take Profit de la orden (se rellena si está especificado en la orden);
  • volume - volumen actual de la orden (no ejecutado). El volumen inicial de la orden se puede conocer del historial de órdenes utilizando la función HistoryOrders*.
  • position - ticket de la posición abierta, modificada o cerrada como resultado de la ejecución de una orden. Se rellena solo para las órdenes de mercado. No se rellena para TRADE_TRANSACTION_ORDER_ADD.
  • position_by - ticket de la posición opuesta. Se rellena solo para las órdenes de cierre de posición con una opuesta (close by).

TRADE_TRANSACTION_DEAL_*

Para las transacciones (transactions) comerciales que conciernen el procesamiento de las operaciones (deals) (TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_DEAL_UPDATE y TRADE_TRANSACTION_DEAL_DELETE), en la estructura MqlTradeTransaction se llenan los siguientes campos:

  • deal - ticket de la operación (deal);
  • order - ticket de la orden a base de la cual ha sido realizada la operación (deal);
  • symbol - nombre del instrumento financiero en la operación (deal);
  • type - tipo de transacción (transaction) comercial;
  • deal_type - tipo de la operación (deal);
  • Precio – precio por el que ha sido realizada la operación (deal);
  • price_sl - precio Stop Loss (se rellena si está especificado en la orden a base de la cual ha sido realizada la operación (deal));
  • price_tp - precio Take Profit (se rellena si está especificado en la orden a base de la cual ha sido realizada la operación (deal));
  • Volumen – volumen de la operación (deal) en lotes.
  • position - ticket de la posición abierta, modificada o cerrada como resultado de la ejecución de una operación.
  • position_by - ticket de la posición opuesta. Solo se rellena para las operaciones de cierre de posición con una opuesta (out by).

TRADE_TRANSACTION_POSITION

Para las transacciones (transactions) comerciales que conciernen las modificaciones de posiciones no relacionadas con la ejecución de las operaciones (deals) (TRADE_TRANSACTION_POSITION), en la estructura MqlTradeTransaction se llenan los siguientes campos:

  • symbol - nombre del instrumento financiero de la posición;
  • type - tipo de transacción (transaction) comercial;
  • deal_type - tipo de posición (DEAL_TYPE_BUY o DEAL_TYPE_SELL);
  • price - precio medio ponderado de la apertura de la posición;
  • price_sl - precio Stop Loss;
  • price_tp - precio Take Profit;
  • Volumen – volumen de la posición en lotes si no ha sido modificado.
  • position - ticket de la posición.

La modificación de una posición (agregación, cambio o eliminación) como resultado de ejecución de la transacción (deal) no supone la aparición tras sí la transacción (transaction) TRADE_TRANSACTION_POSITION.

TRADE_TRANSACTION_REQUEST

Para las transacciones (transactions) comerciales que describen el hecho de que la solicitud comercial haya sido procesada por el servidor y que el resultado de su procesamiento haya sido recibido (TRADE_TRANSACTION_REQUEST), en la estructura MqlTradeTransaction se rellena sólo un campo:

  • type - tipo de transacción (transaction) comercial;

Para las transacciones de este tipo hay que analizar sólo un campo - type (tipo de transacción comercial). Para obtener la información adicional hay que analizar el segundo y el tercer parámetro de la función OnTradeTransaction (request y result).

Ejemplo:

input int MagicNumber=1234567;
 
//--- activamos la clase de trading CTrade y declaramos la variable de este tipo
#include <Trade\Trade.mqh>
CTrade trade;
//--- banderas para colocación y eliminación de la orden pendiente
bool pending_done=false;
bool pending_deleted=false;
//--- aquí vamos a guardar el ticket de la orden pendiente
ulong order_ticket;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- establecemos MagicNumber para marcar todas nuestras órdenes
   trade.SetExpertMagicNumber(MagicNumber);
//--- vamos a mandar las solicitude comerciales en el modo asincrónico utilizando la función OrderSendAsync()
   trade.SetAsyncMode(true);
//--- inicializamos la variable con un cero
   order_ticket=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- colocación de orden pendiente
   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);
      //--- si la función BuyStop() ha trabajado con éxito 
      if(res)
        {
         pending_done=true;
         //--- obtenemos el resultado del envío de la solicitud desde ctrade
         MqlTradeResult trade_result;
         trade.Result(trade_result);
         //---obtenemos request_id para la solicitud enviada
         uint request_id=trade_result.request_id;
         Print("La solicitud para colocar la orden pendiente ha sido enviada. Identificador de la solicitud Request_ID=",request_id);
         //--- recordamos el ticket de la orden (al usar el modo asincrónico del envío a CTrade, será igual a cero)
         order_ticket=trade_result.order;
         //--- todo está hecho por eso salimos del manejador OnTick()
         return;
        }
     }
//--- eliminación de la orden pendiente
   if(!pending_deleted)
      //--- verificación adicional
      if(pending_done && (order_ticket!=0))
        {
         //--- intentamos eliminar la orden pendiente
         bool res=trade.OrderDelete(order_ticket);
         Print("OrderDelete=",res);
         //--- si la solicitud para la eliminación ha sido enviada con éxito
         if(res)
           {
            pending_deleted=true;
            //--- obtenemos el resultado de ejecución de la solicitud
            MqlTradeResult trade_result;
            trade.Result(trade_result);
            //--- extraemos del resultado el identificador de la solicitud
            uint request_id=trade_result.request_id;
            //--- mostramos en el Diario
            Print("Se ha enviado la solicitud para la eliminación de la orden pendiente #",order_ticket,
                  ". Identificador de la solicitud Request_ID=",request_id,
                  "\r\n");
            //--- registramos el ticket de la orden desde el resultado de la solicitud
            order_ticket=trade_result.order;
           }
        }
//---        
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- obtenemos el tipo de la transacción como valor de la enumeración 
   ENUM_TRADE_TRANSACTION_TYPE type=(ENUM_TRADE_TRANSACTION_TYPE)trans.type;
//--- si la transacción es el resultado de procesamiento de la solicitud, mostramos sólo su nombre
   if(type==TRADE_TRANSACTION_REQUEST)
     {
      Print(EnumToString(type));
      //--- mostramos la descripción de la solicitud procesada
      Print("------------RequestDescription\r\n",RequestDescription(request));
      //--- mostramos la descripción del resultado de la solicitud
      Print("------------ResultDescription\r\n",TradeResultDescription(result));
      //--- recordamos el ticket de la orden para su eliminación durante el siguiente procesamiento en OnTick()
      if(result.order!=0)
        {
         //--- eliminamos esta orden según su ticket durante la siguiente llamada de OnTick()
         order_ticket=result.order;
         Print(" Ticket de la orden pendiente ",order_ticket,"\r\n");
        }
     }
   else // para la transacción de otro tipo mostramos la descripción completa
//--- mostramos la descripción de la transacción recibida en el Diario
      Print("------------TransactionDescription\r\n",TransactionDescription(trans));
 
//---     
  }
//+------------------------------------------------------------------+
//|  Devuelve la descripción textual de la transacción               |
//+------------------------------------------------------------------+
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";
//--- devolvemos la cadena obtenida
   return desc;
  }
//+------------------------------------------------------------------+
//|  Devuelve la descripción textual de la solicitud comercial       |
//+------------------------------------------------------------------+
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";
//--- devolvemos la cadena obtenida
   return desc;
  }
//+------------------------------------------------------------------+
//|  Devuelve la descripción textual del resultado de procesamiento  |
//|  de la solicitud                                                 |
//+------------------------------------------------------------------+
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";
//--- devolvemos la cadena obtenida
   return desc;
  }

Véase también

Tipos de transacciones comerciales, OnTradeTransaction()