OnTradeTransaction

Se llama en los expertos al suceder el evento TradeTransaction. La función ha sido pensada para procesar los resultados de la ejecución de una solicitud comercial.

void  OnTradeTransaction()
   const MqlTradeTransaction&    trans,     // estructura de la transacción comercial
   const MqlTradeRequest&        request,   // estructura de la solicitud
   const MqlTradeResult&         result     // estructura de la respuesta
   );

Parámetros

trans

[in]  Variable del tipo MqlTradeTransaction que describe una transacción realizada en la cuenta comercial.

request

[in]  Variable del tipo MqlTradeRequest que describe la solicitud comercial que ha generado la transacción. Contiene valores solo para una transacción del tipo TRADE_TRANSACTION_REQUEST.

result

[in]  Variable del tipo MqlTradeResult con el resultado de la ejecución de la solicitud comercial que ha generado la transacción. Contiene valores solo para una transacción del tipo TRADE_TRANSACTION_REQUEST.

Valor retornado

No hay valor retornado

Observación

OnTradeTransaction() se llama para procesar el evento TradeTransaction, que el servidor comercial envía al terminal en los siguientes casos:

  • el envío de una solicitud comercial desde un programa MQL5 con la ayuda de las funciones OrderSend()/OrderSendAsync() y su posterior ejecución;
  • el envío manual de una solicitud comercial a través de la interfaz gráfica y su posterior ejecución;
  • la activación de órdenes pendientes y órdenes stop en el servidor;
  • la ejecución de operaciones en lado del servidor comercial.

 

La información sobre el tipo de información se contiene en el campo type de la variable trans. Los tipos de transacciones comerciales se describen en la enumeración ENUM_TRADE_TRANSACTION_TYPE:

  • TRADE_TRANSACTION_ORDER_ADD — añadir una nueva orden activa
  • TRADE_TRANSACTION_ORDER_UPDATE — cambiar una orden activa
  • TRADE_TRANSACTION_ORDER_DELETE — eliminar una orden de la lista de activas
  • TRADE_TRANSACTION_DEAL_ADD — añadir una transacción a la historia
  • TRADE_TRANSACTION_DEAL_UPDATE — cambiar una transacción en la historia
  • TRADE_TRANSACTION_DEAL_DELETE — eliminar una transacción de la historia
  • TRADE_TRANSACTION_HISTORY_ADD — añadir una orden a la historia como resultado de una ejecución o cancelación
  • TRADE_TRANSACTION_HISTORY_UPDATE — cambiar una orden que se encuentra en la historia de órdenes
  • TRADE_TRANSACTION_HISTORY_DELETE — eliminar una orden de la historia de órdenes
  • TRADE_TRANSACTION_POSITION — cambiar una posición no relacionada con la ejecución de una transacción
  • TRADE_TRANSACTION_REQUEST — notificar que la solicitud comercial ha sido procesada por el servidor y que el resultado del procesamiento ha sido recibido.

Al procesar transacciones del tipo TRADE_TRANSACTION_REQUEST, para obtener información adicional es necesario analizar el segundo y tercer parámetros de la función OnTradeTransaction(): request y result.

El envío de una solicitud comercial de compra genera una cadena de transacciones comerciales que se ejecutan en la cuenta comercial: 1) la solicitud es aceptada para su procesamiento, 2) a continuación, para la cuenta se crea la orden de compra correspondiente, 3) después tiene lugar la ejecución de la orden, 4) se elimina la orden ejecutada de la lista de activas, 5) se añade a la historia de órdenes, 6) a continuación, se añade la transacción correspondiente a la historia y 7) se crea una nueva posición. Todas estas acciones son transacciones comerciales. La llegada de cada transacción semejante al terminal constituye el evento TradeTransaction. En este caso, además, la llegada de estas transacciones al terminal no está garantizada, por eso no debemos construir nuestro algoritmo esperando que los grupos de transacciones comerciales lleguen unos detrás de otros.

Mientras el experto procesa las transacciones comerciales con la ayuda del manejador OnTradeTransaction(), el terminal continúa procesando las transacciones comerciales entrantes. De esta forma, el estado de la cuenta comercial puede cambiar ya durante el funcionamiento de OnTradeTransaction(). Por ejemplo, mientras un programa MQL5 procesa el evento de adición de una nueva orden, esta puede ser ejeuctada, eliminada de la lista de abiertas y trasladada a la historia. Posteriormente, al programa se le notificarán todos estos eventos.

La longitud de la cola de transacciones es de 1024 elementos. Si OnTradeTransaction() procesa la siguiente transacción durante demasiado tiempo, las transacciones antiguas que se encuentren en la cola podrían ser remplazadas por otras nuevas.

El manejador OnTrade() se llama después de las llamadas correspondientes de OnTradeTransaction(). En general, no existe una proporción exacta en cuanto a la cantidad de llamadas de OnTrade() y OnTradeTransaction(). Una llamada de OnTrade() corresponde a una o varias llamadas de OnTradeTransaction.

Cada evento Trade puede ser el resultado de una o varias solicitudes comerciales. Las solicitudes comerciales se envían al servidor con la ayuda de OrderSend() o OrderSendAsync(). Cada solicitud puede generar varios eventos comerciales. No debemos confiar en la regla: "Una solicitud - Un evento Trade", ya que el procesamiento de solicitudes puede tener lugar en varias etapas y cada operación puede cambiar el estado de las órdenes, posiciones e historia comercial.

Ejemplo de un experto con el manejador OnTradeTransaction()

//+------------------------------------------------------------------+
//|                                    OnTradeTransaction_Sample.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property description "Ejemplo de oyente de eventos TradeTransaction"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   PrintFormat("LAST PING=%.f ms",
               TerminalInfoInteger(TERMINAL_PING_LAST)/1000.);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
 
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---
   static int counter=0;   // contador de llamadas de OnTradeTransaction()
   static uint lasttime=0; // hora de la última llamada de OnTradeTransaction()
//---
   uint time=GetTickCount();
//--- si la última transacción ha sido hace más de 1 segundo
   if(time-lasttime>1000)
     {
      counter=0; // esto significa que se trata de una nueva operación comercial y podemos resetear el contador
      if(IS_DEBUG_MODE)
         Print(" Nueva operación comercial");
     }
   lasttime=time;
   counter++;
   Print(counter,". ",__FUNCTION__);
//--- resultado de la ejecución de la solicitud comercial
   ulong            lastOrderID   =trans.order;
   ENUM_ORDER_TYPE  lastOrderType =trans.order_type;
   ENUM_ORDER_STATE lastOrderState=trans.order_state;
//--- nombre del símbolo para el que se ha ejecuctado la transacción
   string trans_symbol=trans.symbol;
//--- tipo de transacción
   ENUM_TRADE_TRANSACTION_TYPE  trans_type=trans.type;
   switch(trans.type)
     {
      case  TRADE_TRANSACTION_POSITION:   // modificación de la posición
        {
         ulong pos_ID=trans.position;
         PrintFormat("MqlTradeTransaction: Position  #%I64u %s modified: SL=%.5f TP=%.5f",
                     pos_ID,trans_symbol,trans.price_sl,trans.price_tp);
        }
      break;
      case TRADE_TRANSACTION_REQUEST:     // enviar solicitud comercial
         PrintFormat("MqlTradeTransaction: TRADE_TRANSACTION_REQUEST");
         break;
      case TRADE_TRANSACTION_DEAL_ADD:    // añadir transacción
        {
         ulong          lastDealID   =trans.deal;
         ENUM_DEAL_TYPE lastDealType =trans.deal_type;
         double        lastDealVolume=trans.volume;
         //--- identificador de la transacción en un sistema externo, es el ticket asignado por la bolsa
         string Exchange_ticket="";
         if(HistoryDealSelect(lastDealID))
            Exchange_ticket=HistoryDealGetString(lastDealID,DEAL_EXTERNAL_ID);
         if(Exchange_ticket!="")
            Exchange_ticket=StringFormat("(Exchange deal=%s)",Exchange_ticket);
 
         PrintFormat("MqlTradeTransaction: %s deal #%I64u %s %s %.2f lot   %s",EnumToString(trans_type),
                     lastDealID,EnumToString(lastDealType),trans_symbol,lastDealVolume,Exchange_ticket);
        }
      break;
      case TRADE_TRANSACTION_HISTORY_ADD// añadir una orden a la historia
        {
         //--- identificador de la orden en un sistema externo, es el ticket asignado por la bolsa
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_FILLED)
           {
            if(HistoryOrderSelect(lastOrderID))
               Exchange_ticket=HistoryOrderGetString(lastOrderID,ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("(Exchange ticket=%s)",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),trans_symbol,EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
      default// otras transacciones  
        {
         //--- identificador de la orden en un sistema externo, es el ticket asignado por la Bolsa de Moscú
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_PLACED)
           {
            if(OrderSelect(lastOrderID))
               Exchange_ticket=OrderGetString(ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("Exchange ticket=%s",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
     }
//--- ticket de la orden    
   ulong orderID_result=result.order;
   string retcode_result=GetRetcodeID(result.retcode);
   if(orderID_result!=0)
      PrintFormat("MqlTradeResult: order #%d retcode=%s ",orderID_result,retcode_result);
//---   
  }
//+------------------------------------------------------------------+
//| convierte los códigos numéricos de respuesta en códigos mnemónicos 
//+------------------------------------------------------------------+
string GetRetcodeID(int retcode)
  {
   switch(retcode)
     {
      case 10004: return("TRADE_RETCODE_REQUOTE");             break;
      case 10006: return("TRADE_RETCODE_REJECT");              break;
      case 10007: return("TRADE_RETCODE_CANCEL");              break;
      case 10008: return("TRADE_RETCODE_PLACED");              break;
      case 10009: return("TRADE_RETCODE_DONE");                break;
      case 10010: return("TRADE_RETCODE_DONE_PARTIAL");        break;
      case 10011: return("TRADE_RETCODE_ERROR");               break;
      case 10012: return("TRADE_RETCODE_TIMEOUT");             break;
      case 10013: return("TRADE_RETCODE_INVALID");             break;
      case 10014: return("TRADE_RETCODE_INVALID_VOLUME");      break;
      case 10015: return("TRADE_RETCODE_INVALID_PRICE");       break;
      case 10016: return("TRADE_RETCODE_INVALID_STOPS");       break;
      case 10017: return("TRADE_RETCODE_TRADE_DISABLED");      break;
      case 10018: return("TRADE_RETCODE_MARKET_CLOSED");       break;
      case 10019: return("TRADE_RETCODE_NO_MONEY");            break;
      case 10020: return("TRADE_RETCODE_PRICE_CHANGED");       break;
      case 10021: return("TRADE_RETCODE_PRICE_OFF");           break;
      case 10022: return("TRADE_RETCODE_INVALID_EXPIRATION");  break;
      case 10023: return("TRADE_RETCODE_ORDER_CHANGED");       break;
      case 10024: return("TRADE_RETCODE_TOO_MANY_REQUESTS");   break;
      case 10025: return("TRADE_RETCODE_NO_CHANGES");          break;
      case 10026: return("TRADE_RETCODE_SERVER_DISABLES_AT");  break;
      case 10027: return("TRADE_RETCODE_CLIENT_DISABLES_AT");  break;
      case 10028: return("TRADE_RETCODE_LOCKED");              break;
      case 10029: return("TRADE_RETCODE_FROZEN");              break;
      case 10030: return("TRADE_RETCODE_INVALID_FILL");        break;
      case 10031: return("TRADE_RETCODE_CONNECTION");          break;
      case 10032: return("TRADE_RETCODE_ONLY_REAL");           break;
      case 10033: return("TRADE_RETCODE_LIMIT_ORDERS");        break;
      case 10034: return("TRADE_RETCODE_LIMIT_VOLUME");        break;
      case 10035: return("TRADE_RETCODE_INVALID_ORDER");       break;
      case 10036: return("TRADE_RETCODE_POSITION_CLOSED");     break;
      default:
         return("TRADE_RETCODE_UNKNOWN="+IntegerToString(retcode));
         break;
     }
//---
  }

Ver también

OrderSend, OrderSendAsync, OnTradeTransaction, Estructura de la solicitud comercial, Estructura de la transacción comercial, Tipos de transacciones comerciales, Tipos de operaciones comerciales, Eventos del terminal de cliente