English Русский 中文 Deutsch 日本語 Português
Ejemplo de Asesor Experto

Ejemplo de Asesor Experto

MetaTrader 4Ejemplos | 19 enero 2016, 12:53
5 643 0
MetaQuotes
MetaQuotes

Este artículo expone los principios de desarrollo de programas MQL4 mediante la creación de un Asesor Experto que implementa un sistema basado en el indicador estándar MACD. En este Asesor Experto también veremos algunas implementaciones de ejemplo, y también estableceremos los niveles de take profit de forma segura con la ayuda del trailing stop. En nuestro ejemplo las operaciones se llevan a cabo abriendo y manejando una sola posición.

Principios de trading:

  • Entrada larga (BUY) – el indicador MACD está por debajo de la línea cero, se dirige hacia arriba y se cruza con la línea de señal, que va hacia abajo.

  • Entrada corta (SELL) – el indicador MACD está por encima de la línea cero, se dirige hacia abajo y se cruza con la línea de señal, que va hacia arriba.

  • Salida larga – por ejecución del límite take profit, por ejecución del trailing stop o cuando MACD cruza su línea de señal (MACD está por encima de cero, se dirige hacia abajo y se cruza con la línea de señal, que va hacia arriba).

  • Salida corta – por ejecución del límite take profit, por ejecución del trailing stop o cuando MACD cruza su línea de señal (MACD está por debajo de cero, se dirige hacia arriba y se cruza con la línea de señal, que va hacia abajo).

Nota importante: con el objetivo de excluir de nuestro análisis los cambios insignificantes del indicador MACD (los "montículos" pequeños del gráfico), hemos introducido una medida adicional para controlar el tamaño de los "montículos" mostrados, como se explica a continuación. El tamaño del indicador tiene que ser como mínimo 5 unidades del precio mínimo (5*Point, que para USD/CHF = 0.0005 y para USD/JPY = 0.05).


Paso 1 – Escribir la descripción del Asesor Experto

Coloque el puntero del ratón en la sección Expert Advisors de la ventana Navegador, haga clic con el botón derecho del ratón, y seleccione la opción "Nuevo Archivo" del menú contextual. El asistente MQL4 de creación de asesores expertos le pedirá que introduzca unos datos. En la ventana emergente, escriba el nombre (Nombre) del Asesor Experto - Ejemplo MACD, el autor (Autor) - indique su nombre, el enlace (Enlace) - un enlace a su website, en las notas (Notas) - Ejemplo de pruebas con un Asesor Experto basado en MACD.


Step 2 – Creación de la estructura principal del programa

El código fuente del Asesor Experto ocupa solo unas cuantas páginas, pero a veces hasta un volumen así de pequeño puede resultar difícil de entender, especialmente si tenemos en cuenta que no somos programadores profesionales; por cierto, en caso contrario, no necesitaríamos ninguna explicación. :)

Echemos un vistazo a la siguiente descripción para hacernos una idea de la estructura de un Asesor Experto estándar:

  1. Inicialización de variables

  2. Comprobación inicial de los datos

    • comprobación del gráfico, número de barras del gráfico

    • comprobación de los valores de las variables externas: Lots, S/L, T/P, T/S

  3. Configuración de las variables internas para acceder rápidamente a los datos

  4. Comprobación del terminal de trading, ¿está vacío? En caso afirmativo, entonces:

    • comprobaciones: disponibilidad de fondos de la cuenta, etc.

    • ¿se puede abrir una posición larga (BUY)?

      • abrir una posición larga y salir

  5. ¿se puede abrir una posición corta (SELL)?

    • abrir una posición corta y salir

terminando el Asesor Experto...
                    • Control de las posiciones abiertas previamente en el ciclo

                      • si es una posición larga

                        • ¿deberíamos cerrarla?

                        • ¿hay que reiniciar el trailing stop?

                      • si es una posición corta

                        • ¿deberíamos cerrarla?

                        • ¿hay que reiniciar el trailing stop?

                    • Es bastante sencillo porque solo tiene cuatro bloques principales.

                      Ahora vamos a generar piezas de código, paso a paso, para cada sección de la estructura del esquema:

                      1. Inicialización de variables
                        En primer lugar, todas las variables del programa se tienen que definir de acuerdo a la sintaxis del lenguaje MQL 4. Por esto insertamos el bloque de inicialización de variables al comienzo del programa

                        extern double TakeProfit = 50;
                        extern double Lots = 0.1;
                        extern double TrailingStop = 30;
                        extern double MACDOpenLevel=3;
                        extern double MACDCloseLevel=2;
                        extern double MATrendPeriod=26;
                        

                        El lenguaje MQL 4 dispone de las así llamadas variables externas. Estas variables se pueden configurar desde fuera sin necesidad de modificar el código fuente del asesor experto. Lo que proporciona una flexibilidad adicional. En nuestro programa, la variable MATrendPeriod se define como una variable externa. Definimos la variable justo al comienzo del programa.

                        extern double MATrendPeriod=26;
                      2. Comprobación inicial de los datos
                        Esta parte del código puede reutilizarse casi en cualquier experto con modificaciones mínimas, porque es un bloque de comprobación estándar:

                        // comprobación inicial de los datos
                        // es importante asegurarse que el experto trabaja con un
                        // gráfico normal, y que el usuario no se ha equivocado en el momento de 
                        // configurar las variables externas (Lots, StopLoss, TakeProfit, 
                        // TrailingStop) en nuestro caso, comprobamos el TakeProfit
                        // en un gráfico de menos de 100 barras
                           if(Bars<100)
                             {
                              Print("menos de 100 barras");
                              return(0);  
                             }
                           if(TakeProfit<10)
                             {
                              Print("TakeProfit inferior a 10");
                              return(0);  // comprobación de TakeProfit
                             }
                        
                      3. Configuración de las variables internas para acceder rápidamente a los datos
                        A menudo hace falta acceder a los valores del indicador desde el código fuente, o gestionar los valores calculados. Con el objetivo de simplificar la codificación y acelerar el acceso, los datos se ponen en variables internas.

                        int start()
                          {
                           double MacdCurrent, MacdPrevious, SignalCurrent;
                           double SignalPrevious, MaCurrent, MaPrevious;
                           int cnt, ticket, total;
                        
                        // para simplificar la codificación y acelerar el acceso
                        // ponemos los datos en variables internas
                           MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
                           MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
                           SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
                           SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
                           MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
                           MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
                        

                        Ahora, en vez de la incómoda notación iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0), podemos utilizar MacdCurrent en el código fuente.

                      4. Comprobación del terminal de trading, ¿está vacío? En caso afirmativo, entonces:
                        Nuestro Asesor Experto solo utiliza las posiciones que se abren a mercado, sin manejar las órdenes pendientes. Sin embargo, vamos a añadir una pequeña capa de seguridad, comprobando las órdenes colocadas previamente en el terminal de trading:

                         total=OrdersTotal();
                           if(total<1) 
                             {
                        
                        • comprobaciones: disponibilidad de fondos de la cuenta, etc.
                          Antes de analizar la situación del mercado es aconsejable que compruebe el estado de su cuenta. Asegúrese que tiene fondos suficientes para abrir posiciones.

                                if(AccountFreeMargin()<(1000*Lots))
                                  {
                                   Print("No hay dinero. Margen libre = ", AccountFreeMargin());
                                   return(0);  
                                  }
                          
                        • ¿se puede abrir una posición larga (BUY)?
                          Condición de entrada de una posición larga: MACD está por debajo de la línea cero, se desplaza hacia arriba y se cruza con la línea de señal, que va hacia abajo. Es así como la describimos en MQL4 (nótese que operamos con los valores del indicador que han sido previamente almacenados en variables):

                                // comprobamos la posibilidad de posición larga (BUY)
                                if(MacdCurrent<0 && MacdCurrent>SignalCurrent && 
                                   MacdPrevious<SignalPrevious &&
                                   MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && 
                                   MaCurrent>MaPrevious)
                                  {
                                   ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,
                                                    "ejemplo macd",16384,0,Green);
                                   if(ticket>0)
                                     {
                                      if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
                                         Print("Orden BUY abierta : ",OrderOpenPrice());
                                     }
                                   else Print("Error de apertura de posición BUY : ",GetLastError()); 
                                   return(0); 
                                  }
                          

                          El control adicional del tamaño de los "montículos" que se dibujan ya se ha mencionado anteriormente. La variable MACDOpenLevel está definida por el usuario y se puede cambiar sin tener que interferir con el texto del programa, lo que proporciona una gran flexibilidad. Al comienzo del programa hemos insertado una descripción de esta variable, así como la descripción de la variable que se utiliza abajo.

                        • ¿se puede abrir una posición corta (SELL)?
                          Condición de entrada de una posición corta: MACD está por debajo de la línea cero, se desplaza hacia abajo y se cruza con la línea de señal, que va hacia arriba. La notación es como sigue:

                                    // comprobamos la posibilidad de posición corta (SELL)
                                    if(MacdCurrent>0 && MacdCurrentSignalPrevious && 
                                       MacdCurrent>(MACDOpenLevel*Point) && 
                                       MaCurrent<MaPrevious)
                                      {
                                       ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,
                                                        "ejemplo macd",16384,0,Red);
                                       if(ticket>0)
                                         {
                                          if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
                                             Print("Apertura de posición SELL : ",OrderOpenPrice());
                                         }
                                       else Print("Error de apertura de posición SELL : ",GetLastError()); 
                                       return(0); 
                                      }
                          
                            return(0);
                           }
                          

                      5. Control de las posiciones abiertas previamente en el ciclo

                        // es importante entrar al mercado de forma correcta, 
                        // pero es más importante salir de forma correcta...   
                        for(cnt=0;cnt
                          {
                           OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
                           if(OrderType()<=OP_SELL &&   // comprobación de posición abierta 
                              OrderSymbol()==Symbol())  // comprobación del símbolo
                             {
                        

                        "cnt" – " es una variable del ciclo que se tiene que definir así al comienzo del programa:

                         int cnt = 0; 

                        • si es una posición larga

                          if(OrderType()==OP_BUY)   // apertura de posición larga
                            {
                          
                          
                          • ¿deberíamos cerrarla?
                            Condición de salida de una posición larga: MACD se cruza con la línea de señal, MACD está por encima de la línea cero desplazándose hacia abajo y cruzándose con la línea de señal, que va hacia arriba.

                            if(MacdCurrent>0 && MacdCurrent<SignalPrevious &&
                               MacPrevious>SignalPrevious &&
                               MacdCurrent>(MACDCloseLevel*Point))
                              {
                               OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // cerramos la posición
                               return(0); // salimos
                              }
                            
                          • ¿deberíamos reiniciar el trailing stop?
                            Establecemos el trailing stop solo cuando la posición tiene un beneficio que supera el nivel de trailing stop en puntos, y cuando el nuevo nivel del stop es mejor que el anterior.

                            // comprobación del trailing stop
                            if(TrailingStop>0)  
                              {                 
                               if(Bid-OrderOpenPrice()>Point*TrailingStop)
                                 {
                                  if(OrderStopLoss()
                                    {
                                     OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,
                                                 OrderTakeProfit(),0,Green);
                                     return(0);
                                    }
                                 }
                              }
                            

                          Cerramos la llave del operador.

                             }
                      6. si es una posición corta

                        else // ir a la posición corta
                          {
                        
                        • ¿deberíamos cerrarla?
                          Condición de salida de una posición corta: MACD se cruza con la línea de señal, MACD está por debajo de la línea cero desplazándose hacia arriba y cruzándose con la línea de señal, que va hacia abajo.

                          if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&
                             MacdPrevious<SignalPrevious &&
                             MathAbs(MacdCurrent)>(MACDCloseLevel*Point))
                            {
                             OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // cerrar posición
                             return(0); // salimos
                            }
                          
                        • ¿deberíamos reiniciar el trailing stop?
                          Establecemos el trailing stop solo cuando la posición tiene un beneficio que supera el nivel de trailing stop en puntos, y cuando el nuevo nivel del stop es mejor que el anterior.

                          // comprobación del trailing stop
                          if(TrailingStop>0)  
                            {                 
                             if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
                               {
                                if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
                                  {
                                   OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,
                                               OrderTakeProfit(),0,Red);
                                   return(0);
                                  }
                               }
                            }
                          

                        Cerramos todas las llaves que permanecen abiertas.

                                 }
                              }
                           }
                         return(0);
                        }
                        

                  Así pues, finalmente, siguiendo paso a paso este procedimiento hemos escrito nuestro Asesor Experto.

                  Paso 3 – Ensamblar el código resultante del programa

                  Abramos la configuración del Asesor Experto (para ello podemos utilizar un botón o una línea del menú "Propiedades..."). Entonces se abre una ventana donde tenemos que definir la configuración externa de los parámetros:



                  Ensamblemos todo el código de la sección anterior:

                  //+------------------------------------------------------------------+
                  //|                                                  MACD Sample.mq4 |
                  //|                      Copyright © 2005, MetaQuotes Software Corp. |
                  //|                                       https://www.metaquotes.net/ |
                  //+------------------------------------------------------------------+
                  extern double TakeProfit = 50;
                  extern double Lots = 0.1;
                  extern double TrailingStop = 30;
                  extern double MACDOpenLevel=3;
                  extern double MACDCloseLevel=2;
                  extern double MATrendPeriod=26;
                  
                  //+------------------------------------------------------------------+
                  //|                                                                  |
                  //+------------------------------------------------------------------+
                  int start()
                    {
                     double MacdCurrent, MacdPrevious, SignalCurrent;
                     double SignalPrevious, MaCurrent, MaPrevious;
                     int cnt, ticket, total;
                  // comprobación inicial de los datos
                  // es importante asegurarse que el experto trabaja con un
                  // gráfico normal, y que el usuario no se ha equivocado en el momento de 
                  // configurar las variables externas (Lots, StopLoss, TakeProfit, 
                  // TrailingStop) en nuestro caso, comprobamos el TakeProfit
                  // en un gráfico de menos de 100 barras
                     if(Bars<100)
                       {
                        Print("menos de 100 barras");
                        return(0);  
                       }
                     if(TakeProfit<10)
                       {
                        Print("TakeProfit inferior a 10");
                        return(0);  // comprobación de TakeProfit
                       }
                  // para simplificar la codificación y acelerar el acceso
                  // ponemos los datos en variables internas
                     MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
                     MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
                     SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
                     SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
                     MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
                     MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
                     total=OrdersTotal();
                     if(total<1) 
                       {
                        // no se identifican órdenes abiertas
                        if(AccountFreeMargin()<(1000*Lots))
                          {
                           Print("No hay dinero. Margen libre = ", AccountFreeMargin());
                           return(0);  
                          }
                        // comprobamos la posibilidad de posición larga (BUY)
                        if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
                           MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious)
                          {
                           ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"ejemplo macd",16384,0,Green);
                           if(ticket>0)
                             {
                              if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("Orden BUY abierta : ",OrderOpenPrice());
                             }
                           else Print("Error de apertura de posición BUY : ",GetLastError()); 
                           return(0); 
                          }
                        // comprobamos la posibilidad de posición corta (SELL)
                        if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && 
                           MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious)
                          {
                           ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,"ejemplo macd",16384,0,Red);
                           if(ticket>0)
                             {
                              if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("Orden SELL abierta : ",OrderOpenPrice());
                             }
                           else Print("Error de apertura de posición SELL : ",GetLastError()); 
                           return(0); 
                          }
                        return(0);
                       }
                     // es importante entrar al mercado de forma correcta, 
                     // pero es más importante salir de forma correcta...   
                     for(cnt=0;cnt<total;cnt++)
                       {
                        OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
                        if(OrderType()<=OP_SELL &&   // comprobación de posición abierta 
                           OrderSymbol()==Symbol())  // comprobación del símbolo
                          {
                           if(OrderType()==OP_BUY)   // apertura de posición larga
                             {
                              // ¿debería cerrarse?
                              if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
                                 MacdCurrent>(MACDCloseLevel*Point))
                                  {
                                   OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // cerramos la posición
                                   return(0); // salimos
                                  }
                              // comprobación del trailing stop
                              if(TrailingStop>0)  
                                {                 
                                 if(Bid-OrderOpenPrice()>Point*TrailingStop)
                                   {
                                    if(OrderStopLoss()<Bid-Point*TrailingStop)
                                      {
                                       OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
                                       return(0);
                                      }
                                   }
                                }
                             }
                           else // ir a la posición corta
                             {
                              // ¿debería cerrarse?
                              if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&
                                 MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point))
                                {
                                 OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // cerrar posición
                                 return(0); // salimos
                                }
                              // comprobación del trailing stop
                              if(TrailingStop>0)  
                                {                 
                                 if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
                                   {
                                    if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
                                      {
                                       OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
                                       return(0);
                                      }
                                   }
                                }
                             }
                          }
                       }
                     return(0);
                    }
                  // fin.
                  

                  Para terminar de configurar nuestro asesor experto, tan solo especifique los valores de las variables externas "Lots = 1", "Stop Loss (S/L) = 0" (sin usar), "Take Profit (T/P) = 120" (adecuado en intervalos de una hora), "Trailing Stop (T/S) = 30". Por supuesto que usted puede establecer sus propios valores. Presione el botón "Compilar", y si no aparece ningún mensaje de error (por cierto, puede copiar el texto de arriba en MetaEditor), haga clic en el botón "Guardar".

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

                  Calidad de modelado de datos de un minuto Calidad de modelado de datos de un minuto
                  Calidad de modelado de datos de un minuto
                  Cómo manejar el Error 146, "Trade context busy" Cómo manejar el Error 146, "Trade context busy"
                  Este artículo expone el problema que plantea el uso de varios asesores expertos que trabajan de forma simultánea en un mismo Terminal Cliente MT 4. Se dirige a todos aquellos que cuentan con experiencia básica en el manejo del terminal y tienen conocimientos básicos de programación en MQL4.
                  Cómo elegir correctamente un producto para comprar en el Mercado. Guía paso a paso Cómo elegir correctamente un producto para comprar en el Mercado. Guía paso a paso
                  En esta guía paso a paso, se describen las recomendaciones y consejos que pueden ayudarle a entender y decidir qué producto debe comprar en el Mercado. En este artículo intentaremos entender cómo encontrar un producto adecuado, cómo cribar lo que no necesitamos, cómo determinar la efectividad de un producto y en qué medida le será necesario a usted mismo.
                  MagicNumber, el identificador "mágico" de la orden MagicNumber, el identificador "mágico" de la orden
                  Este artículo expone el problema que plantea el uso de varios asesores expertos que trabajan de forma simultánea en un mismo Terminal Cliente MT 4. Aprenderemos a indicar al asesor experto que maneje solamente sus propias órdenes, sin que modifique o cierre otras posiciones, es decir, las abiertas manualmente o las colocadas por otros expertos. Este artículo se dirige a los usuarios que tienen unos conocimientos básicos de programación en MQL 4 y cuentan con algo de experiencia manejando el terminal.