OrderSend

La función OrderSend() está destinada para realizar la actividad comercial dentro de los márgenes de MQL5.

bool  OrderSend(
   MqlTradeRequest&  request      // estructura de petición
   MqlTradeResult&   result       // estructura de respuesta
   );

Parámetros

request

[in]  Puntero a una estructura del tipo MqlTradeRequest que describe la acción comercial del cliente.

result

[in,out]  Puntero a una estructura del tipo MqlTradeResult que describe el resultado de una operación comercial en caso de llevarla a cabo con éxito (se devuelve true).

Valor devuelto

En caso de comprobar las estructuras (comprobación de punteros) con éxito, la función devuelve true, pero eso no significa que la operación comercial que se solicita vaya a ser ejecutada con éxito. Para una descripción más detallada de los resultados de la ejecución de esta función, hay que analizar los campos de la estructura result.

Nota

Las solicitudes comerciales pasan por varias fases de comprobación en el servidor comercial. En primer lugar se comprueba si todos los campos necesarios del parámetro request están rellenados correctamente. Si no hay errores, el servidor acepta la solicitud para su procesamiento. Si la orden se acepta con éxito, la función OrderSend() devuelve el valor true.

Se recomienda comprobar personalmente la solicitud antes de enviarla al servidor comercial. Para eso sirve la función OrderCheck() que no sólo comprueba si hay fondos suficientes en la cuenta para la ejecución de la operación comercial, sino también devuelve muchos otros parámetros útiles como resultado de comprobación de la solicitud comercial:

  • código de retorno que avisa sobre un error en la solicitud que se comprueba;
  • valor del balance de la cuenta que se queda tras la ejecución de la operación comercial;
  • valor de fondos propios que se obtiene tras la ejecución de la operación comercial;
  • valor del beneficio flotante que se obtiene tras la ejecución de la operación comercial;
  • margen necesario para la operación comercial;
  • fondos propios que se quedan disponibles después de realizar la operación comercial;
  • nivel del margen que va a establecerse después de realizar la operación comercial;
  • comentario sobre el código de respuesta, descripción del error en su caso.

Al enviar una orden de mercado (MqlTradeRequest.action=TRADE_ACTION_DEAL), si la función OrderSend()da un resultado exitoso, esto no siginifca que la orden se haya ejecutado (se han ejecutado las operaciones correspondientes): true en este caso significa solo que la orden ha sido correctamente colocada en el sistema comercial para su posterior ejecución. El servidor comercial puede rellenar los valores de los campos deal o order en la estructura del resultado retornado result, si estos datos le son conocidos en el momento de la formación de la respuesta a la llamada OrderSend(). En general, el evento o eventos de ejecución de las operaciones correspondientes a una orden pueden suceder ya después de que se envíe la respuesta a la llamada OrderSend(). Por eso, para cualquier tipo de solucitud comercial, al recibir el resultado de la ejecución de OrderSend(), es necesario en primer lugar comprobar el código de retorno del servidor comercial retcode y el código de respuesta del sistema comercial retcode_external (en caso necesario), que están disponibles en la estructura del resultado retornada result.

Cada orden aceptada se almacena en el servidor comercial esperando su procesamiento hasta que se de una de las condiciones adecuadas para su ejecución:

  • expiración del plazo de vigencia,
  • aparición de una solicitud opuesta,
  • ejecución de la orden tras la recepción del precio de ejecución,
  • aparición de la solicitud de cancelación de la orden.

Durante el procesamiento de la orden el servidor comercial envía un mensaje al terminal sobre el evento Trade, que se puede procesar mediante la función OnTrade().

En el servidor el resultado de ejecución de la solicitud comercial que ha sido enviada con la función OrderSend() se puede seguir a través del manejador OnTradeTransaction. Hay que tener en cuenta que durante la ejecución de una solicitud comercial el manejador OnTradeTransaction será invocado varias veces.

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. La función OnTradeTransaction será llamada para cada uno de estos eventos.

Ejemplo:

//--- valores para ORDER_MAGIC
input long order_magic=55555;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- vamos a comprobar que se trata de una cuenta de demostración
   if(AccountInfoInteger(ACCOUNT_TRADE_MODE)==ACCOUNT_TRADE_MODE_REAL)
     {
      Alert("Operación del script en una cuenta real está prohibida!");
      return;
     }
//--- colocamos o eliminamos una orden
   if(GetOrdersTotalByMagic(order_magic)==0) 
     {
      //--- no hay órdenes corrientes - colocamos una orden
      uint res=SendRandomPendingOrder(order_magic);
      Print("Código de devolución del servidor comercial ",res);
     }
   else // hay órdenes - eliminamos órdenes 
     {
      DeleteAllOrdersByMagic(order_magic);
     }
//---
  }
//+---------------------------------------------------------------------+
//|  recibir la cantidad actual de órdenes con ORDER_MAGIC especificada |
//+---------------------------------------------------------------------+
int GetOrdersTotalByMagic(long const magic_number)
  {
   ulong order_ticket;
   int total=0;
//--- repasamos todas las órdenes pendientes
   for(int i=0;i<OrdersTotal();i++)
      if((order_ticket=OrderGetTicket(i))>0)
         if(magic_number==OrderGetInteger(ORDER_MAGIC)) total++;
//---
   return(total);
  }
//+------------------------------------------------------------------+
//| elimina todas las órdenes pendientes con ORDER_MAGIC especifcada |
//+------------------------------------------------------------------+
void DeleteAllOrdersByMagic(long const magic_number)
  {
   ulong order_ticket;
//--- repasamos todas las órdenes pendientes
   for(int i=0;i<OrdersTotal();i++)
      if((order_ticket=OrderGetTicket(i))>0)
         //--- orden con ORDER_MAGIC apropiada
         if(magic_number==OrderGetInteger(ORDER_MAGIC))
           {
            MqlTradeResult result={};
            MqlTradeRequest request={};
            request.order=order_ticket;
            request.action=TRADE_ACTION_REMOVE;
            OrderSend(request,result);
            //--- apuntamos en el log la respuesta del servidor
            Print(__FUNCTION__,": ",result.comment," código de respuesta ",result.retcode);
           }
//---
  }
//+------------------------------------------------------------------+
//|  establecer una orden pendiente de una manera aleatoria          |
//+------------------------------------------------------------------+
uint SendRandomPendingOrder(long const magic_number)
  {
//--- preparamos la solicitud
   MqlTradeRequest request={};
   request.action=TRADE_ACTION_PENDING;         // definir una orden pendiente
   request.magic=magic_number;                  // ORDER_MAGIC
   request.symbol=_Symbol;                      // instrumento
   request.volume=0.1;                          // volumen de 0.1 lote
   request.sl=0;                                // Stop Loss sin especificar
   request.tp=0;                                // Take Profit sin especificar
//--- vamos a formar el tipo de orden
   request.type=GetRandomType();                // tipo de orden
//---vamos a formar el precio para una orden pendiente
   request.price=GetRandomPrice(request.type);  // precio de apertura
//--- enviamos la orden comercial
   MqlTradeResult result={};
   OrderSend(request,result);
//--- introducimos la respuesta del servidor en el log
   Print(__FUNCTION__,":",result.comment);
   if(result.retcode==10016) Print(result.bid,result.ask,result.price);
//--- devolvemos el código de retorno del servidor comercial
   return result.retcode;
  }
//+------------------------------------------------------------------+
//| recibir el tipo de una orden pendiente de una manera aleatoria   |
//+------------------------------------------------------------------+
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);
     }
//--- valor incorrecto
   return(WRONG_VALUE);
  }
//+------------------------------------------------------------------+
//|  recibir el precio de una manera aleatoria                       |
//+------------------------------------------------------------------+
double GetRandomPrice(ENUM_ORDER_TYPE type)
  {
   int t=(int)type;
//--- nivel de stops para el símbolo
   int distance=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
//--- recibimos los datos del último tick
   MqlTick last_tick={};
   SymbolInfoTick(_Symbol,last_tick);
//--- vamos a calcular el precio de acuerdo con el tipo
   double price;
   if(t==2 || t==5) // ORDER_TYPE_BUY_LIMIT o ORDER_TYPE_SELL_STOP
     {
      price=last_tick.bid; // partimos del precio Bid
      price=price-(distance+(MathRand()%10)*5)*_Point;
     }
   else             // ORDER_TYPE_SELL_LIMIT o ORDER_TYPE_BUY_STOP
     {
      price=last_tick.ask; // partimos del precio Ask
      price=price+(distance+(MathRand()%10)*5)*_Point;
     }
//---
   return(price);
  }

Véase también

Tipos de operaciones comerciales, Estructura de solicitud comercial, Estructura de resultado de solicitud comercial