English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Operaciones de trading en MQL5 - Es fácil

Operaciones de trading en MQL5 - Es fácil

MetaTrader 5Ejemplos | 25 diciembre 2013, 13:51
6 418 0
MetaQuotes
MetaQuotes

Casi todos los operadores llegan al mercado para ganar dinero, pero algunos también disfrutan de ello. Sin embargo, no solo la operativa manual puede proporcionarle una experiencia apasionante. El desarrollo de sistemas de trading automatizados también puede ser fascinante. Crear un robot de trading puede ser tan interesante como leer una buena novela de misterio.

Cuando se desarrolla un algoritmo de trading tenemos que resolver una gran cantidad de aspectos técnicos incluyendo los más importantes:

  1. ¿Con qué negociar?
  2. ¿Cuándo negociar?
  3. ¿Cómo negociar?

Necesitamos responder a la primera pregunta para elegir el símbolo más apropiado. Nuestra elección puede verse afectada por muchos factores, incluyendo la capacidad para automatizar nuestro sistema de trading en el mercado. La segunda pregunta implica la elaboración de normas de trading que indican claramente la dirección de las negociaciones, así como los puntos de entrada y salida. La tercera cuestión parece ser relativamente simple: ¿cómo comprar y vender usando un lenguaje de programación determinado?

En este artículo vamos a ver cómo implementar operaciones de compraventa en el trading algorítmico usando el lenguaje MQL5.


Características de MQL5 para el trading algorítmico

MQL5 es un lenguaje de programación de estrategias de trading con multitud de funciones de trading para el trabajo con órdenes, posiciones y solicitudes de transacciones. De esta forma, el diseño de robots de trading algorítmicos en MQL5 es la tarea que requiere un menor trabajo por parte de un programador.

Las características de MQL5 le permiten realizar una solicitud de transacción y enviarla a un servidor usando las funciones OrderSend() o bien OrderSendAsync(), recibir los resultados de su procesamiento, ver el historial de trading, examinar las especificaciones del contrato para un símbolo, gestionar un evento de trading, así como recibir otros datos necesarios.

Además, MQL5 puede usarse para escribir indicadores técnicos personalizados y aplicar aquellos que ya están implementados, trazar cualquier señal u objeto sobre un gráfico, desarrollar una interfaz de usuario personalizada, etc. Pueden consultarse ejemplos de implementación en numerosos artículos.


Operaciones de trading: ¡tan fácil como ABC!

Hay varios tipos básicos de operaciones que su robot de trading puede necesitar:

  1. comprar/vender al precio actual,
  2. cursar una orden pendiente para comprar/vender según una condición determinada,
  3. modificar/eliminar una orden pendiente,
  4. cerrar/añadir/reducir/revertir una posición,

Todas estas operaciones se realizan mediante la función OrderSend(). Hay también una versión asíncrona llamada OrderSendAsync(). Todos los tipos de operaciones de trading son descritas por la estructura MqlTradeRequest que contiene la descripción de una solicitud de transacción. Por tanto, solo cumplir con la estructura de MqlTradeRequest y gestionar los resultados de la ejecución de las solicitudes puede ser todo un reto cuando se trabaja con operaciones de trading.

En función de su sistema de trading, puede comprar o vender al precio de mercado (BUY o SELL), así como cursar una orden pendiente de compra/venta a una distancia determinada del precio de mercado actual:

  • BUY STOP, SELL STOP - comprar o vender cuando se sobrepasa un nivel determinado (peor que el precio actual);
  • BUY LIMIT, SELL LIMIT - comprar o vender cuando se alcanza un nivel determinado (mejor que el precio actual);
  • BUY STOP LIMIT, SELL STOP LIMIT - establecer BUY LIMIT o SELL LIMIT cuando se alcanza el precio señalado.

Estos tipos de órdenes estándar se corresponden con la enumeración ENUM_ORDER_TYPE



Puede necesitar modificar o eliminar alguna orden pendiente. Esto también puede realizarse mediante las funciones OrderSend()/OrderSendAsync(). Modificar una posición es también un proceso muy sencillo, ya que se realiza usando las mismas operaciones de trading.

Si cree que las operaciones de trading son complejas e intrincadas, es el momento de cambiar de opinión. Le mostraremos no solo cómo escribir código para compras y ventas en MQL5 de forma rápida y sencilla, sino también cómo trabajar con cuentas de trading y propiedades de símbolos. Las clases de transacciones nos ayudarán en esta tarea.


Compruebe su cuenta de trading con CAccountInfo

Lo primero que necesita saber al ejecutar su robot de trading es qué cuenta de trading se va a usar para esta operación. Como estamos escribiendo un código de prueba vamos a implementar una verificación por si el asesor experto es iniciado en una cuenta real.

La clase CAccountInfo se utiliza para trabajar con una cuenta. Añadiremos el archivo AccountInfo.mqh y declararemos la variable de la clase - account:

#include <Trade\AccountInfo.mqh>
//+------------------------------------------------------------------+
//| Función de inicialización del Experto                            |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- objeto para trabajar con la cuenta
   CAccountInfo account;
//--- al recibir el número de cuenta el Expert Advisor se inicia en
   long login=account.Login();
   Print("Login=",login);
//--- determinar el tipo de cuenta
   ENUM_ACCOUNT_TRADE_MODE account_type=account.TradeMode();
//--- si la cuenta es real ¡el Expert Advisor se para immediatamente!
   if(account_type==ACCOUNT_TRADE_MODE_REAL)
     {
      MessageBox("Se prohibe operar en una cuenta real, deshabilitando ","¡Se ha iniciado el Expert Advisor en una cuenta real!");
      return(-1);
     }
//--- mostrar el tipo de cuenta    
   Print("Account type: ",EnumToString(account_type));
//--- determinar si podemos operar en esta cuenta
   if(account.TradeAllowed())
      Print("Se permite operar en esta cuenta");
   else
      Print("Se prohíbe operar en esta cuenta: puede que haya usado la contraseña de inversor");
//--- determinar si podemos usar un Expert Advisor en esta cuenta
   if(account.TradeExpert())
      Print("Se permiten las operaciones automatizadas en esta cuenta");
   else
      Print("Se prohíbe el trading automatizado usando Expert Advisors y scripts");
//--- Determinar si se ha establecido el número de órdenes permitidas
   int orders_limit=account.LimitOrders();
   if(orders_limit!=0)Print("Cantidad máxima admitida de órdenes pendientes activas: ",orders_limit);
//--- Mostrar los nombres de la empresa y el servidor
   Print(account.Company(),": servidor ",account.Server());
//--- mostrar el saldo y beneficio actual en la cuenta al final
   Print("Saldo=",account.Balance(),"  Beneficio=",account.Profit(),"   Valor neto=",account.Equity());
   Print(__FUNCTION__,"  completado"); //---
   return(0);
  }
//+------------------------------------------------------------------+
//| Función de deinicialización del Experto                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Función tick del Experto                                         |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }

Como podemos ver en el código anterior, puede recibirse una gran cantidad de datos usando la variable account en la función OnInit(). Puede añadir este código a su asesor experto para comprobar los registros fácilmente al analizar su operación.

A continuación se muestran los resultados del asesor experto iniciado en el "Campeonato de trading automatizado de 2012".



Recibir ajustes de símbolo con CSymbolInfo

Ya tenemos los datos en la cuenta pero también necesitamos conocer las propiedades del símbolo con el que vamos a negociar antes de realizar las operaciones necesarias. La clase CSymbolInfo, con un gran número de métodos, está diseñada para este propósito. Solo mostraremos una pequeña parte de los métodos en el ejemplo siguiente.

#include<Trade\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//| Función de inicialización del Experto                            |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- ajustes en el objeto que recibe los símbolos
   CSymbolInfo symbol_info;
//--- establecer el nombre del símbolo apropiado
   symbol_info.Name(_Symbol);
//--- recibe y muestra los precios actuales
   symbol_info.RefreshRates();
   Print(symbol_info.Name()," (",symbol_info.Description(),")",
         "  Bid=",symbol_info.Bid(),"   Ask=",symbol_info.Ask());
//--- recibe los niveles mínimos de congelación para las operacioens de trading 
   Print("StopsLevel=",symbol_info.StopsLevel()," pips, FreezeLevel=",
         symbol_info.FreezeLevel()," pips");
//--- recibe el número de posiciones decimales y el tamaño del entero
   Print("Digits=",symbol_info.Digits(),
         ", Point=",DoubleToString(symbol_info.Point(),symbol_info.Digits()));
//--- información sobre el margen diferencial
   Print("SpreadFloat=",symbol_info.SpreadFloat(),", Spread(current)=",
         symbol_info.Spread()," pips");
//--- solicita el tipo de ejecución de orden para los límites
   Print("Límites para las operaciones de trading: ",EnumToString(symbol_info.TradeMode()),
         " (",symbol_info.TradeModeDescription(),")");
//--- determinar el modo de ejecución de operaciones
   Print("Modo de ejecución de operaciones: ",EnumToString(symbol_info.TradeExecution()),
         " (",symbol_info.TradeExecutionDescription(),")");
//---determina el método de cálculo del precio de los contratos
   Print("Cálculo del precio del contrato: ",EnumToString(symbol_info.TradeCalcMode()),
         " (",symbol_info.TradeCalcModeDescription(),")");
//--- tamaño de los contractos
   Print("Tamaño estándar de contrato: ",symbol_info.ContractSize(),
         " (",symbol_info.CurrencyBase(),")");
//--- volúmenes máximos y mínimos en las operaciones de trading
   Print("Volumen: LotsMin=",symbol_info.LotsMin(),"  LotsMax=",symbol_info.LotsMax(),
         "  LotsStep=",symbol_info.LotsStep());
//--- 
   Print(__FUNCTION__,"  completed");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Función de deinicialización del Experto                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Función tick del Experto                                         |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }

A continuación se muestran las propiedades de EURUSD en el campeonato de trading automatizado. Ahora estamos en condiciones de realizar operaciones de trading.



CTrade - La clase adecuada para las operaciones de trading

El trading en MQL5 es realizado solo por dos funciones: OrdenSend() y OrderSendAsync(). De hecho, son dos implementaciones de una única función. OrderSend() envía una solicitud de transacción y espera el resultado de su ejecución, mientras que la orden asíncrona OrderSendAsync() envía una solicitud permitiendo que la aplicación continúe operando sin esperar la respuesta del servidor. De esta forma, es realmente sencillo operar en MQL5, ya que solo usamos una única función para todas las operaciones de trading.

Entonces, ¿cuál es el reto? Ambas funciones reciben la estructura MqlTradeRequest con más de una docena de campos como primer parámetro. No todos los campos deben rellenarse necesariamente. El número de campos que es necesario rellenar depende del tipo de operación de trading. Los valores erróneos o los espacios en blanco cuando éstos requieren ser rellenados pueden dar como resultado un error y la solicitud no será enviada a un servidor. 5 de estos campos requieren los valores apropiados de enumeraciones predefinidas.

Es necesaria una cantidad de campos tan grande para poder describir el gran número de propiedades de una orden en una solicitud de transacción. Las órdenes pueden cambiar en función de la política de ejecución, fecha de caducidad y algunos otros parámetros. Pero no tiene por qué aprender todos estas sutilezas. Tan solo use la clase CTrade ya diseñada. Así es como puede usar la clase en su robot de trading:

#include<Trade\Trade.mqh>
//--- objeto para realizar operaciones de trading
CTrade  trade;
//+------------------------------------------------------------------+
//| Función de inicialización del Experto                            |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- establece MagicNumber para la identificación de sus órdenes
   int MagicNumber=123456;
   trade.SetExpertMagicNumber(MagicNumber);
//--- establece el retardo en los puntos cuando se compra/vende
   int deviation=10;
   trade.SetDeviationInPoints(deviation);
//--- modo de ejecución de una orden, debe usarse el modo permitido por el servidor
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
//--- modo de registro (logging): sería mejor no declarar este método en absoluto ya que la clase establecerá el mejor modo por sí misma
   trade.LogLevel(1); 
//--- qué función se va a usar para el trading: true - OrderSendAsync(), false - OrderSend()
   trade.SetAsyncMode(true);
//---
   return(0);
  }

Veamos ahora cómo puede ayudarnos CTrade en las operaciones de trading.

Comprar/vender al precio actual

A menudo, las estrategias de trading ofrecen la posibilidad de comprar o vender al precio del momento. En este caso, CTrade solicita que se indique el volumen de operaciones de trading necesario. Todos los demás parámetros (precio abierto y nombre del símbolo, niveles de Stop Loss y Take Profit, comentarios de la orden) son opcionales.

//--- 1. Ejemplo de compra al símbolo actual
   if(!trade.Buy(0.1))
     {
      //--- mensaje de error
      Print("Falló el método Buy() . Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("método Buy() ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Por defecto, CTrade usará el nombre del símbolo del gráfico que ha sido iniciado en caso de que dicho nombre no haya sido especificado. Es aconsejable para estrategias simples. Para estrategias con varias divisas debemos siempre especificar el símbolo en el que la operación de trading va a realizarse.

//--- 2. Ejemplo de compra al símbolo especificado
   if(!trade.Buy(0.1,"GBPUSD"))
     {
      //--- mensaje de error
      Print("Falló el método Buy(). Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("método Buy() ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Pueden especificarse todos los parámetros de la orden: niveles de Stop Loss/Take Profit, precio abierto y comentarios.

//--- 3. Ejemplo de compra al símbolo especificado con indicación de Stop Limit y Take Profit
   double volume=0.1;         // especifica un volumen de operación
   string symbol="GBPUSD";    //especifica el símbolo para el que la operación se realiza
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de posiciones decimales
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // punto
   double bid=SymbolInfoDouble(symbol,SYMBOL_BID);             // current price for closing LONG
   double SL=bid-1000*point;                                   //valor Stop Limit no normalizado
   SL=NormalizeDouble(SL,digits);                              // normalizing Stop Loss
   double TP=bid+1000*point;                                   // valor Take Profit no normalizado
   TP=NormalizeDouble(TP,digits);                              // normalizing Take Profit
//--- recibe el precio abierto actual ara posiciones LARGAS
   double open_price=SymbolInfoDouble(symbol,SYMBOL_ASK);
   string comment=StringFormat("Buy %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(open_price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
   if(!trade.Buy(volume,symbol,open_price,SL,TP,comment))
     {
      //--- mensaje de error
      Print("Falló el método Buy(). Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("método Buy() ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Como ya hemos señalado, el número mágico y los retardos aceptables se establecieron al inicializar la copia de CTrade. Por tanto, no son necesarios. Sin embargo, también pueden establecerse antes de cada operación de trading si es necesario.


Cursar una orden con precio límite

Para enviar una orden con precio límite se utiliza el método de clase adecuado de BuyLimit() o SellLimit(). La versión abreviada (cuando solo se indican un precio abierto y un volumen) será adecuada en la mayoría de casos. El precio abierto para una orden limitada de compra debe ser inferior al precio actual, mientras que debe ser superior para una orden limitada de venta. Estas órdenes se usan para entrar al mercado al mejor precio y normalmente son más adecuadas para las estrategias en las que se espera un alza de precios. En tal caso, se usa el símbolo al que ha sido iniciado el asesor experto:

//--- 1. Ejemplo de cursar una orden limitada de compra pendiente
   string symbol="GBPUSD";    // especifica el símbolo en el que se sitúa la orden
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de posiciones decimales
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // punto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // precio de compra de divisa
   double price=1000*point;                                   // precio abierto no normalizado
   price=NormalizeDouble(price,digits);                       // normalizing open price
//--- todo está preparado, enviando una orden limitada de compra pendiente
   if(!trade.BuyLimit(0.1,price))
     {
      //--- mensaje de error
      Print("Falló el método BuyLimit(). Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Método BuyLimit() ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

También puede utilizarse una versión más detallada especificando todos los parámetros: los niveles de órdenes Stop Limit/Take Profit, período de caducidad, nombre del símbolo y comentarios a la orden.

//--- 2. Ejemplo de cursar una orden con límite de compra pendiente con todos los parámetros
   double volume=0.1;
   string symbol="GBPUSD";    // especifica el símbolo en el que se sitúa la orden
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de posiciones decimales
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // punto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // precio de compra actual
   double price=1000*point;                                 // precio abierto no normalizado
   price=NormalizeDouble(price,digits);                      // normalizando el precio de compra
   int SL_pips=300;                                         // Stop Loss en puntos
   int TP_pips=500;                                         // Take Profit en puntos
   double SL=price-SL_pips*point;                           // valor SL no normalizado
   SL=NormalizeDouble(SL,digits);                            // normalizando Stop Loss
   double TP=price+TP_pips*point;                           // valor
   TP=NormalizeDouble(TP,digits);                            // normalizando Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Limit %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- todo está preparado, enviando una orden limitada de compra pendiente al servidor
   if(!trade.BuyLimit(volume,price,symbol,SL,TP,ORDER_TIME_GTC,expiration,comment))
     {
      //--- mensaje de error
      Print("Falló el método BuyLimit(). Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Método BuyLimit() ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Su tarea en la segunda versión es indicar los niveles de SL y TP correctamente. Debe señalarse que el nivel de Take Profit debe ser mayor que el precio abierto durante la compra, mientras que el nivel de Stop Level debe ser menor que el precio abierto. Para las órdenes Sell Limit se produce la situación opuesta. Puede fácilmente obtener información sobre su error al probar un asesor experto sobre datos históricos. En tales casos, la clase CTrade muestra automáticamente los mensajes (al menos que haya llamado a la función LogLevel).


Cursando una orden límite

Para enviar una orden límite, se utilizan los métodos BuyStop() y SellStop(). El precio abierto para la orden Buy Stop debería ser mayor que el precio actual, mientras que debería ser menor para la orden Sell Stop. Las órdenes límite se usan en estrategias que entran al mercado durante una salida del nivel de resistencia, así como para reducir las pérdidas. Versión simple:

//--- 1. ejemplo de cursar una orden Buy Stp pendiente
   string symbol="USDJPY";    // especifica el símbolo en el que se sitúa la orden
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de posiciones decimales
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // punto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // precio de compra actual
   double price=1000*point;                                    // precio abierto no normalizado
   price=NormalizeDouble(price,digits);                        // normalizando precio abierto
//--- todo está preparado, enviando una orden Buy Stop pendiente al servidor 
   if(!trade.BuyStop(0.1,price))
     {
      //--- mensaje de error
      Print("BuyStop() method failed. Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("método BuyStop() ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Una versión más detallada cuando la cantidad máxima de parámetros para la orden Buy Stop pendiente debe ser especificada:

//--- 2. ejemplo de cursar una orden Buy Stop pendiente con todos los parámetros
   double volume=0.1;
   string symbol="USDJPY";    // especifica el símbolo en el que se sitúa la orden
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // número de posiciones decimales
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // punto
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // precio actual de compra
   double price=1000*point;                                   // precio abierto no normalizado
   price=NormalizeDouble(price,digits);                       // normalizando precio abierto
   int SL_pips=300;                                          // Stop Loss en puntos
   int TP_pips=500;                                          // Take Profit en puntos
   double SL=price-SL_pips*point;                            // valor SL no normalizado
   SL=NormalizeDouble(SL,digits);                             // normalizando Stop Loss
   double TP=price+TP_pips*point;                            // valor TP no normalizado
   TP=NormalizeDouble(TP,digits);                             // normalizando Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Stop %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- todo está preparado, enviando una orden Buy Stop pendiente al servidor
   if(!trade.BuyStop(volume,price,symbol,SL,TP,ORDER_TIME_GTC,expiration,comment))
     {
      //--- mensaje de error
      Print("El método BuyStop() ha fallado. Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("método BuyStop() ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Para enviar la orden Sell Stop se utiliza el método de clase apropiado de CTrade. La especificación correcta de los precios tiene aquí una importancia crítica.


Trabajando con posiciones

Puede usar métodos de apertura de posiciones en lugar de los de Buy() y Sell() pero, en este caso, tendrá que especificar más detalles:

//--- número de posiciones decimales
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- valor del punto
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- recibir un precio de compra
   double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
//--- calcula y normaliza los niveles de SL y TP
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
//--- comentarios
   string comment="Buy "+_Symbol+" 0.1 at "+DoubleToString(price,digits);
//--- todo está preparado, intentando abrir una posición de compra
   if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,0.1,price,SL,TP,comment))
     {
      //--- mensaje de error
      Print("El método PositionOpen() ha fallado. Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("El método PositionOpen() se ha ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }


Tan solo necesita especificar un nombre de símbolo, el resto lo hará la clase CTrade.

//--- cerrando una posición en el símbolo actual
   if(!trade.PositionClose(_Symbol))
     {
      //--- mensaje de error
      Print("El método PositionClose() ha fallado. Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("El método PositionClose() se ha ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }


Solo los niveles de Stop Loss y Take Profit están disponibles para modificar una posición abierta. Esto se realiza usando el método PositionModify()

//--- número de posiciones decimales
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- valor del punto
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- recibiendo el precio de compra actual
   double price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
//--- calcula y normaliza los niveles SL y TP
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
//--- todo está preparado, intentando modificar la posición de compra
   if(!trade.PositionModify(_Symbol,SL,TP))
     {
      //--- mensaje de error
      Print("El método PositionModify() ha fallado. Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("El método PositionModify() se ha ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }


Modificar y borrar una orden

El método OrderModify() ha sido implementado en la clase CTrade para cambiar los parámetros de la orden pendiente. Todos los parámetros requeridos deberían someterse a este método.

//--- este es un ticket de orden de prueba, debería ser recibido
   ulong ticket=1234556;
//--- este es un símbolo de prueba, debería ser recibido
   string symbol="EURUSD";
//--- número de posiciones decimales
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- valor del punto
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- recibiendo un precio de compra
   double price=SymbolInfoDouble(symbol,SYMBOL_ASK);
//--- calcula y normaliza los nivels SL y TP 
//--- deberían ser calculados en función del tipo de orden
   double SL=NormalizeDouble(price-1000*point,digits);
   double TP=NormalizeDouble(price+1000*point,digits);
   //--- establece un día de duración
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);   
//--- todo está preparado, intentando modificar la orden
   if(!trade.OrderModify(ticket,price,SL,TP,ORDER_TIME_GTC,expiration))
     {
      //--- mensaje de error
      Print("El método OrderModify() ha fallado. Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("El método OrderModify() se ha ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }


Debería recibir el tique de la orden que debe ser cambiado. Deben especificarse los niveles adecuados de Stop Loss y Take Profit según su tipo. Además, el nuevo precio abierto debería también ser el adecuado para el precio actual.

Debería conocer el tique de una orden para borrarlo:

//--- este es un ticket de orden de prueba, debería ser recibido
   ulong ticket=1234556;
//--- todo está preparado, intentando modificar una orden de compra
   if(!trade.OrderDelete(ticket))
     {
      //--- mensaje de error
      Print("El método OrderDelete() ha fallado. Return code=",trade.ResultRetcode(),
            ". Descripción del código: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("El método OrderDelete() se ha ejecutado con éxito. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }


Esta clase contiene también el método de múltiples usos OrderOpen(), que puede trabajar con órdenes pendientes de cualquier clase. A diferencia de lo que ocurre con los métodos específicos BuyLimit, BuyStop, SellLimit y SellStop, requiere que se especifiquen más parámetros esenciales. Quizás lo encuentre más adecuado.


¿Qué más debemos resolver?

De esta forma, hemos respondido a dos de las tres preguntas. Ha elegido el símbolo para su estrategia y le hemos mostrado cómo escribir fácilmente el código de las operaciones de compra y venta y de las órdenes pendientes en un robot de trading. Sin embargo, la sección "clases para transacciones" dispone de algunas herramientas útiles más para los programadores de MQL5:

Con estas clases puede centrar su atención en la parte de trading de su estrategia, minimizando los aspectos técnicos. Además, puede usarse la clase CTrade para examinar las solicitudes de transacciones. Después de algo de práctica, será capaz de utilizarla para crear sus propias clases con la lógica necesaria de los resultados de la ejecución de la gestión de las solicitudes de trading.

La última pregunta es cómo recibir señales de trading y cómo crear dicho código en MQL5. La mayoría de principiantes en el trading algorítmico comienzan estudiando sistemas simples de trading, como por ejemplo los que se basan en el cruce de medias móviles. Para hacer esto, debería primero aprender a trabajar con indicadores técnicos, creándolos y usándolos en su robot de trading.

Le recomendamos que lea los artículos de las secciones sobre indicadores y ejemplos>indicadores comenzando por los más sencillos. Esto le permitirá ir de las cuestiones más sencillas a las más complejas. Si quiere hacerse una rápida idea sobre el uso de indicadores, consulte MQL5 para principantes: guía para el uso de indicadores técnicos en asesores expertos.


Simplifique las cosas complejas

En cualquier proyecto, las dificultades iniciales se convierten gradualmente en las cuestiones más simples. Los métodos para el desarrollo de robots de trading que se han mostrado aquí están dirigidos, sobre todo, a principiantes, aunque muchos programadores expertos pueden encontrar información nueva de gran utilidad.

El lenguaje MQL5 proporciona no solo ilimitadas oportunidades para el trading algorítmico, sino que también permite a cualquier persona implementarlos de la forma más simple y rápida. Utilice las clases de trading de la librería estándar para ahorrar tiempo en las cosas más importantes, como por ejemplo, para buscar la respuesta a la eterna pregunta de todos los operadores: qué es una tendencia y cómo puede encontrarse una en tiempo real.

Pronto verá que desarrollar un robot de trading en MQL5 ¡es mucho más fácil que aprender un idioma o seguir una tendencia!


Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/481

Archivos adjuntos |
demo_ctrade.mq5 (4.03 KB)
Uso de los recursos en MQL5 Uso de los recursos en MQL5
Los programas MQL5 no solo automatizan cálculos rutinarios, sino que también pueden crear un entorno gráfico completo. Las funciones para crear controles realmente interactivos son ahora virtualmente tan ricas como las de los lenguajes de programación. Si desea escribir un programa entero e independiente en MQL5, use los recursos disponibles en ellos. Los programas con recursos son más fáciles de mantener y distribuir.
Algoritmos que generan ingresos empleando órdenes Trailing Stop Algoritmos que generan ingresos empleando órdenes Trailing Stop
El objetivo de este artículo es estudiar la rentabilidad de los algoritmos con diferentes entradas y salidas en el mercado usando órdenes Trailing Stop. Los tipos de entrada que se usaran son las entradas aleatorias y las entradas inversas. Las órdenes Stop que se usarán son las de tipo Trailing Stop y Trailing Take. El artículo describe los algoritmos generadores de ingresos con una rentabilidad en torno al 30% al año.
MQL5 Wizard: Nueva Versión MQL5 Wizard: Nueva Versión
Este artículo contiene descripciones de los nuevos elementos disponibles en el MQL5 Wizard actualizado. La arquitectura actualizada de señales nos permite crear robots de trading basados en la combinación de varios patrones de mercado. El ejemplo que contiene este artículo explica el procedimiento de creación interactiva de un Asesor Experto.
Visualizar una estrategia en el simulador de Meta Trader 5 Visualizar una estrategia en el simulador de Meta Trader 5
Todos conocemos el refrán "mejor verlo una vez que oírlo cien veces". Podemos leer varios libros sobre París o Venecia, pero basándonos solo en nuestra imaginación no podemos vivir la misma experiencia que si diésemos un paseo al atardecer por estas magníficas ciudades. La ventaja de la visualización puede aplicarse fácilmente a cualquier otro aspecto de nuestras vidas, incluso el trabajo en el mercado de valores, por ejemplo, cuando analizamos los gráficos de precios usando indicadores y, por supuesto, visualizando el probador de estrategia. Este artículo describe las características de visualización del simulador de Meta Trader 5.