English Русский 中文 Deutsch 日本語 Português
Asesores Expertos basados en estrategias populares de trading, y un poco de alquimia en la optimización de robots (Parte VI)

Asesores Expertos basados en estrategias populares de trading, y un poco de alquimia en la optimización de robots (Parte VI)

MetaTrader 4Sistemas comerciales | 11 mayo 2016, 13:16
1 443 0
Nikolay Kositsin
Nikolay Kositsin

Introducción

En mi artículo anterior, había descrito en detalle la implementación de los Asesores Expertos que procesan la información que llega desde dos períodos de tiempo distintos. No obstante, esta información no es siempre suficientemente precisa para entrar al mercado. Por ejemplo, si el período de tiempo más pequeño es igual a H1, entrar al mercado nada más cambiar la barra cada hora no es siempre la mejor solución, puesto que la tendencia inferior a H1 y que en general está presente en el ruido del precio puede ir en contra de la posición a abrir. En muchos casos, se puede detectar fácilmente esta tendencia a corto plazo. En caso de que la tendencia vaya en contra de la posición a abrir, habrá que posponer la entrada al mercado hasta que la tendencia de los períodos de tiempo más cortos cambie de dirección. O, en el peor de los casos, entrar al mercado antes del siguiente cambio de barra de una hora. Voy a intentar de comenzar mi artículo con esta tarea.

Sistema de triple pantalla de Elder

Alexander Elder es conocido por ser el autor de libros muy populares sobre la psicología del trading y el comportamiento de las masas. Fue él quien inventó la idea de utilizar tres períodos de tiempo en el análisis de los mercados financieros. Estos gráficos se llaman Triple pantalla de Elder. Ya vimos en mi artículo anterior cómo implementar un pantalla doble. Ahora le tenemos que añadir una tercera pantalla. Como ejemplos para la implementación del código, podemos utilizar algunos Asesores Expertos que ya existen en mi artículo anterior. No obstante, he decidido desarrollar otro Asesor Experto (Exp_14.mq4) basado en los mismos procedimientos, sólo para cambiar.

Como punto de partida para escribir el código he optado por el Exp_12.mq4 donde he sustituido el promedio móvil JFatl.mq4 por el oscilador JCCIX.mq4 y el indicador de seguimiento de la tendencia MAMA_NK.mq4 que consiste en dos promedios móviles por el indicador StepMA_Stoch_NK.mq4 compuesto por un par de osciladores estocásticos. Al final, el algoritmo inicial sigue siendo el mismo, sólo he cambiado las llamadas a los indicadores personalizados, las variables externas del Asesor Experto y la inicialización de las constantes en el bloque de la función init(), también he modificado el código de los bloques destinados a detectar las señales de entrada al mercado. Una vez más, voy a describir por encima el algoritmo de funcionamiento del Asesor Experto mediante dos períodos de tiempo, al igual que en mi artículo anterior. Aunque lo voy a detallar un poco más esta vez.

Para las posiciones largas tenemos:

Y para las posiciones cortas:

Este sería el algoritmo final más racional posible que tenemos que implementar en el código del programa para utilizar los gráficos de tres períodos distintos de tiempo:

Para las posiciones largas:

Para las posiciones cortas:

La implementación de este algoritmo en el código del Asesor Experto basado en Exp_15.mq4 es la siguiente:

//+==================================================================+
//|                                                       Exp_15.mq4 |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +---------------------------------------------------------------------------+
//---- EXPERT ADVISORS INPUTS FOR BUY TRADES 
extern bool   Test_Up = true;//filter of trade calculations direction
extern double Money_Management_Up = 0.1;
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +   
extern int    TimeframeX_Up = 1440;                 
extern int    PeriodWATR_Up = 10; 
extern double Kwatr_Up = 1.0000; 
extern int    HighLow_Up = 0; 
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    Timeframe_Up = 240;
extern int    JJLength_Up = 8;  // depth of JJMA smoothing for the entry price
extern int    JXLength_Up = 8;  // depth of JurX smoothing for the obtained indicator
extern int    Phase_Up = 100;// the parameter ranging
                        // from -100 to +100 influences the process quality; 
extern int    IPC_Up = 0; /* Selecting price to calculate 
the indicator on (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    TimeframeN_Up = 15;
extern int    Noise_period_Up = 8;
//extern int    SmoothN_Up = 7;
//extern int    MaMethodN_Up = 1;
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    STOPLOSS_Up = 50;  // StopLoss
extern int    TAKEPROFIT_Up = 100; // TakeProfit
extern bool   ClosePos_Up = true; // enable forcible closing the position
//----+ +---------------------------------------------------------------------------+
//---- EXPERT ADVISORS INPUTS FOR SELL TRADES
extern bool   Test_Dn = true;//filter of trade calculations direction
extern double Money_Management_Dn = 0.1;
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    TimeframeX_Dn = 1440;
extern int    PeriodWATR_Dn = 10; 
extern double Kwatr_Dn = 1.0000; 
extern int    HighLow_Dn = 0; 
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    Timeframe_Dn = 240;
extern int    JJLength_Dn = 8;  // depth of JJMA smoothing for the entry price
extern int    JXLength_Dn = 8;  // depth of JurX smoothing for the obtained indicator
extern int    Phase_Dn = 100;// the parameter ranging
                        // from -100 to +100 influences the process quality; 
extern int    IPC_Dn = 0; /* Selecting price to calculate 
the indicator on (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    TimeframeN_Dn = 15;
extern int    Noise_period_Dn = 8;
//extern int    SmoothN_Dn = 7;
//extern int    MaMethodN_Dn = 1;
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    STOPLOSS_Dn = 50;  // StopLoss
extern int    TAKEPROFIT_Dn = 100; // TakeProfit
extern bool   ClosePos_Dn = true; // enable forcible closing the position
//----+ +---------------------------------------------------------------------------+
//---- Integer variables for calling to custom indicators
int SmoothN_Up = 7, SmoothN_Dn = 7, MaMethodN_Up = 1, MaMethodN_Dn = 1;
//---- Integer variables for the minimum of reference bars
int MinBar_Up, MinBar_Dn, MinBarX_Up, MinBarX_Dn, MinBarN_Up, MinBarN_Dn;
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the value of variable Timeframe for correctness
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter",Name,
                     " cannot ", "be equal to", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the values of timeframe variables for correctness
   TimeframeCheck("TimeframeX_Up", TimeframeX_Up);
   TimeframeCheck("Timeframe_Up", Timeframe_Up);
   TimeframeCheck("TimeframeN_Up", TimeframeN_Up);

//---- Checking the values of timeframe variables for correctness
   TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); 
   TimeframeCheck("Timeframe_Dn", Timeframe_Dn); 
   TimeframeCheck("TimeframeN_Dn", TimeframeN_Dn);

//---- Initialization of variables             
   MinBarX_Up = 2 + PeriodWATR_Up;
   MinBar_Up = 4 + 3 * JXLength_Up + 30;
   MinBarN_Up = 4 + Noise_period_Up + SmoothN_Up;

//---- Initialization of variables
   MinBarX_Dn = 2 + PeriodWATR_Dn;
   MinBar_Dn = 4 + 3 * JXLength_Dn + 30;
   MinBarN_Dn = 4 + Noise_period_Dn + SmoothN_Dn;
                                          
//---- initialization complete
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- EA deinitialization complete
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaration of local variables
   int    bar;
   double JCCIX[2], Trend, Fast_StepMA, Slow_StepMA, MA1, MA2;
   //----+ Declaration of static variables
   static datetime StopTime_Up, StopTime_Dn;
   static double   TrendX_Up, TrendX_Dn, OldTrend_Up, OldTrend_Dn;
   //---
   static int  LastBars_Up, LastBars_Dn;
   static int  LastBarsX_Up, LastBarsX_Dn, LastBarsN_Up, LastBarsN_Dn;
   //---
   static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop;
   static bool SecondStart_Up, SecondStart_Dn, NoiseBUY_Sign, NoiseSELL_Sign;
   
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS                                        |
   //----+ +---------------------------------------------------------------+
   if (Test_Up) 
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      int IBARSX_Up = iBars(NULL, TimeframeX_Up);
      int IBARSN_Up = iBars(NULL, TimeframeN_Up);
      //---
      if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up && IBARSN_Up >= MinBarN_Up)
       {       
         //----+ +----------------------+
         //----+ DETECTING A TREND      |
         //----+ +----------------------+
         if (LastBarsX_Up != IBARSX_Up)
          {
           //----+ Initialization of variables
           LastBarsX_Up = IBARSX_Up;
           BUY_Sign = false;
           BUY_Stop = false;
           
           //----+ calculating the values of indicators
           Fast_StepMA = iCustom(NULL, TimeframeX_Up, "StepMA_Stoch_NK", 
                                 PeriodWATR_Up, Kwatr_Up, HighLow_Up, 0, 1);
           //---         
           Slow_StepMA = iCustom(NULL, TimeframeX_Up, "StepMA_Stoch_NK", 
                                 PeriodWATR_Up, Kwatr_Up, HighLow_Up, 1, 1);
           //----+ detecting a trend                                 
           TrendX_Up = Fast_StepMA - Slow_StepMA;
           //----+ defining a signal to close trades
           if (TrendX_Up < 0)
                      BUY_Stop = true;                                      
          }
         
         //----+ +----------------------------------------+
         //----+ DETECTING SIGNALS TO ENTER THE MARKET    |
         //----+ +----------------------------------------+
         if (LastBars_Up != IBARS_Up && TrendX_Up > 0)
          {
           //----+ Initialization of variables
           BUY_Sign = false;
           LastBars_Up = IBARS_Up;
           //----+ Initialization of noise variables 
           NoiseBUY_Sign = false;
           StopTime_Up = iTime(NULL, Timeframe_Up, 0)
                                          + 50 * Timeframe_Up;
           
           //----+ Initialization of zero
           if (!SecondStart_Up)
            {
              //--- Search for trend direction at the first start
              for(bar = 2; bar < IBARS_Up - 1; bar++)
               {
                 JCCIX[0] = iCustom(NULL, Timeframe_Up, 
                    "JCCIX", JJLength_Up, JXLength_Up, Phase_Up, IPC_Up, 0, bar); 
                 //---  
                 JCCIX[1] =  iCustom(NULL, Timeframe_Up, 
                    "JCCIX", JJLength_Up, JXLength_Up, Phase_Up, IPC_Up, 0, bar + 1); 
                 //---  
                 OldTrend_Up = JCCIX[0] - JCCIX[1];
                 //---    
                 if (OldTrend_Up != 0)
                   {
                    SecondStart_Up = true;
                    break;
                   }
               }
            } 
           
           //----+ calculating the values of indicators and loading them to a buffer      
           for(bar = 1; bar < 3; bar++)
                     JCCIX[bar - 1] =                  
                         iCustom(NULL, Timeframe_Up, 
                                "JCCIX", JJLength_Up, JXLength_Up, 
                                                   Phase_Up, IPC_Up, 0, bar);
           
           //----+ detecting signals for trades   
           Trend = JCCIX[0] - JCCIX[1];
            
           if (TrendX_Up > 0)                     
              if (OldTrend_Up < 0)
                         if (Trend > 0)
                                 BUY_Sign = true; 
           if (Trend != 0)
                   OldTrend_Up = Trend;                                   
          }
         
         //----+ +------------------------------------------------+
         //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET      |
         //----+ +------------------------------------------------+
         if (BUY_Sign)
          if (LastBarsN_Up != IBARSN_Up)
           {
             NoiseBUY_Sign = false;
             LastBarsN_Up = IBARSN_Up;
             //---
             MA1 = iCustom(NULL, TimeframeN_Up, 
                      "2Moving Avereges", Noise_period_Up, SmoothN_Up, 
                         MaMethodN_Up, MaMethodN_Up, PRICE_LOW, 0, 0, 1);
             //---
             MA2 = iCustom(NULL, TimeframeN_Up,
                       "2Moving Avereges", Noise_period_Up, SmoothN_Up, 
                         MaMethodN_Up, MaMethodN_Up, PRICE_LOW, 0, 0, 2);
             //---                   
             if (MA1 > MA2 || TimeCurrent() > StopTime_Up)   
                                           NoiseBUY_Sign = true;
                                           
           }
         
         //----+ +-------------------+
         //----+ MAKING TRADES       |
         //----+ +-------------------+
         if (NoiseBUY_Sign)
           if (!OpenBuyOrder1(BUY_Sign, 1, Money_Management_Up, 
                                          STOPLOSS_Up, TAKEPROFIT_Up))
                                                                 return(-1);
         if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop, 1))
                                        return(-1);
        }
     }
     
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS                                       |
   //----+ +---------------------------------------------------------------+
   if (Test_Dn) 
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      int IBARSX_Dn = iBars(NULL, TimeframeX_Dn);
      int IBARSN_Dn = iBars(NULL, TimeframeN_Dn);
      //---
      if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn && IBARSN_Dn >= MinBarN_Dn)
       {
         //----+ +----------------------+
         //----+ DETECTING A TREND      |
         //----+ +----------------------+
         if (LastBarsX_Dn != IBARSX_Dn)
          {
           //----+ Initialization of variables
           LastBarsX_Dn = IBARSX_Dn;
           SELL_Sign = false;
           SELL_Stop = false;
           
           //----+ calculating the values of indicators
           Fast_StepMA = iCustom(NULL, TimeframeX_Dn, "StepMA_Stoch_NK", 
                                 PeriodWATR_Dn, Kwatr_Dn, HighLow_Dn, 0, 1);
           //---         
           Slow_StepMA = iCustom(NULL, TimeframeX_Dn, "StepMA_Stoch_NK", 
                                 PeriodWATR_Dn, Kwatr_Dn, HighLow_Dn, 1, 1);
           //----+ detecting a trend                                 
           TrendX_Dn = Fast_StepMA - Slow_StepMA;
           //----+ defining a signal to close trades
           if (TrendX_Dn > 0)
                      SELL_Stop = true;                                      
          }
         
         //----+ +----------------------------------------+
         //----+ DETECTING SIGNALS TO ENTER THE MARKET    |
         //----+ +----------------------------------------+
         if (LastBars_Dn != IBARS_Dn && TrendX_Dn < 0)
          {
           //----+ Initialization of variables
           SELL_Sign = false;
           LastBars_Dn = IBARS_Dn;
           //----+ Initialization of noise variables
           NoiseSELL_Sign = false;
           StopTime_Dn = iTime(NULL, Timeframe_Dn, 0)
                                          + 50 * Timeframe_Dn;
           
           //----+ Initialization of zero
           if (!SecondStart_Dn)
            {
              //--- Search for trend direction at the first start
              for(bar = 2; bar < IBARS_Dn - 1; bar++)
               {
                 JCCIX[0] = iCustom(NULL, Timeframe_Dn, 
                    "JCCIX", JJLength_Dn, JXLength_Dn, Phase_Dn, IPC_Dn, 0, bar); 
                 //---  
                 JCCIX[1] =  iCustom(NULL, Timeframe_Dn, 
                    "JCCIX", JJLength_Dn, JXLength_Dn, Phase_Dn, IPC_Dn, 0, bar + 1); 
                 //---  
                 OldTrend_Dn = JCCIX[0] - JCCIX[1];
                 //---    
                 if (OldTrend_Dn != 0)
                   {
                    SecondStart_Dn = true;
                    break;
                   }
               }
            } 
           
           //----+ calculating the values of indicators and loading them to a buffer     
           for(bar = 1; bar < 3; bar++)
                     JCCIX[bar - 1]=                  
                         iCustom(NULL, Timeframe_Dn, 
                                "JCCIX", JJLength_Dn, JXLength_Dn, 
                                                   Phase_Dn, IPC_Dn, 0, bar);
           //----+ detecting signals for trades   
           Trend = JCCIX[0] - JCCIX[1];
           //--- 
           if (TrendX_Dn < 0)                                 
              if (OldTrend_Dn > 0)
                         if (Trend < 0)
                                 SELL_Sign = true;
           if (Trend != 0)
                   OldTrend_Dn = Trend;                                         
          }
         
         //----+ +------------------------------------------------+
         //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET      |
         //----+ +------------------------------------------------+
         if (SELL_Sign)
          if (LastBarsN_Dn != IBARSN_Dn)
           {
             NoiseSELL_Sign = false;
             LastBarsN_Dn = IBARSN_Dn;
             //---
             MA1 = iCustom(NULL, TimeframeN_Dn, 
                      "2Moving Avereges", Noise_period_Dn, SmoothN_Dn, 
                         MaMethodN_Dn, MaMethodN_Dn, PRICE_HIGH, 0, 0, 1);
             //---
             MA2 = iCustom(NULL, TimeframeN_Dn,
                      "2Moving Avereges", Noise_period_Dn, SmoothN_Dn,
                         MaMethodN_Dn, MaMethodN_Dn, PRICE_HIGH, 0, 0, 2);
             //---                 
             if (MA1 < MA2 || TimeCurrent() > StopTime_Dn)   
                                           NoiseSELL_Sign = true;
           }
          
         //----+ +-------------------+
         //----+ MAKING TRADES       |
         //----+ +-------------------+
         if (NoiseSELL_Sign)
           if (!OpenSellOrder1(SELL_Sign, 2, Money_Management_Dn, 
                                            STOPLOSS_Dn, TAKEPROFIT_Dn))
                                                                  return(-1);
           if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop, 2))
                                        return(-1);
        }
     }
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Vamos a ver con más detalle la conversión de Exp_14.mq4 en Exp_15.mq4. Tenemos un nuevo módulo, "DETECTING NOISE SIGNALS TO ENTER THE MARKET" (detección de las señales del ruido para entrar al mercado), en el código de nuestro programa. Se puede describir este módulo de la siguiente manera (estoy suponiendo el algoritmo para las posiciones largas sólo):
Se genera la señal NoiseBUY_Sign si la dirección de la tendencia en los períodos de tiempo más cortos coincide con la dirección de la señal de entrada al mercado BUY_Sig. Y si no coincide esta tendencia se genera la señal NoiseBUY_Sign antes de producirse el siguiente cambio de barra.

Como promedio móvil de seguimiento de tendencia, he utilizado un indicador obtenido mediante un doble suavizado de la secuencia del precio mediante los algoritmos habituales de promediado. Como parámetro externo para el Asesor Experto de este módulo, sólo he utilizado dos variables:

extern int    TimeframeN_Up = 15;
extern int    Noise_period_Up = 8;

He fijado la mayoría de las variables externas del indicador personalizado 2Moving Avereges.mq4 (inicialización de las variables globales):

int SmoothN_Up = 7, SmoothN_Dn = 7, MaMethodN_Up = 1, MaMethodN_Dn = 1;

He utilizado exactamente la misma lógica que en mi artículo anterior para añadir el código.

Una idea general sobre la construcción de Asesores Expertos mediante tres períodos de tiempo

En realidad, el código del Asesor Experto ya está listo, y podría parar aquí. Pero en mi opinión, sólo hemos realizado una pequeña parte del trabajo. Es muy difícil que el primer sistema de trading desarrollado en base a esta idea genere buenos resultados en el trading real. Por lo que tenemos que pensar en la idea de escribir el código para uno o dos Asesores Expertos más y elegir la mejor versión. Así que ahora tenemos que pasar por alto el problema de los algoritmos específicos para el cálculo de las señales de trading y utilizar sólo el algoritmo de las tres pantallas. Que por lo general no es un problema. Este sería el código final sin algoritmos:

//+==================================================================+
//|                                                 ThreeScreens.mqh |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +---------------------------------------------------------------------------+
//---- EXPERT ADVISORS INPUTS FOR BUY TRADES
extern bool   Test_Up = true;//filter of trade calculations direction
extern double Money_Management_Up = 0.1;
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +   
extern int    TimeframeX_Up = 1440;                 
// Declarations and initializations of the EA external parameters for long positions for the largest timeframe
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    Timeframe_Up = 240;
// Declarations and initializations of the EA external parameters for long positions for the middle timeframe
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    TimeframeN_Up = 15;
// Declarations and initializations of the EA external parameters for long positions for the smallest timeframe
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    STOPLOSS_Up = 50;  // StopLoss
extern int    TAKEPROFIT_Up = 100; // TakeProfit
extern bool   ClosePos_Up = true; // enable forcible closing the position
//----+ +---------------------------------------------------------------------------+
//---- EXPERT ADVISORS INPUTS FOR SELL TRADES
extern bool   Test_Dn = true;//filter of trade calculations direction
extern double Money_Management_Dn = 0.1;
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    TimeframeX_Dn = 1440;
// Declarations and initializations of the EA external parameters for short positions forlargest timeframe
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    Timeframe_Dn = 240;
// Declarations and initializations of the EA external parameters for short positions formiddle timeframe
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    TimeframeN_Dn = 15;
// Declarations and initializations of the EA external parameters for short positions forthe smallest timeframe
//---- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
extern int    STOPLOSS_Dn = 50;  // StopLoss
extern int    TAKEPROFIT_Dn = 100; // TakeProfit
extern bool   ClosePos_Dn = true; // enable forcible closing the position
//----+ +---------------------------------------------------------------------------+
//---- Integer variables for the minimum of reference bars
int MinBar_Up, MinBar_Dn, MinBarX_Up, MinBarX_Dn, MinBarN_Up, MinBarN_Dn;
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the value of variable Timeframe for correctness
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter",Name,
                     " cannot", "be equal to", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the values of timeframe variables for correctness
   TimeframeCheck("TimeframeX_Up", TimeframeX_Up);
   TimeframeCheck("Timeframe_Up", Timeframe_Up);
   TimeframeCheck("TimeframeN_Up", TimeframeN_Up);

//---- Checking the values of timeframe variables for correctness
   TimeframeCheck("TimeframeX_Dn", TimeframeX_Dn); 
   TimeframeCheck("Timeframe_Dn", Timeframe_Dn); 
   TimeframeCheck("TimeframeN_Dn", TimeframeN_Dn);

//---- Initialization of variables for long positions            
   MinBarX_Up = // initialization of the variable for the minimum reference bars for largest timeframe
   MinBar_Up = // initialization of the variable for the minimum reference bars for middle timeframe
   MinBarN_Up = // initialization of the variable for the minimum reference bars for the smallest timeframe

//---- Initialization of variables for short positions
   MinBarX_Dn =  // initialization of the variable for the minimum reference bars for largest timeframe
   MinBar_Dn =  // initialization of the variable for the minimum reference bars for middle timeframe
   MinBarN_Dn = // initialization of the variable for the minimum reference bars for the smallest timeframe
                                          
//---- initialization complete
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- EA deinitialization complete
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaration of local variables of trading algorithms
   //----+ Declaration of static variables of trading algortihms
   
   //----+ Declaration of static variables
   static datetime StopTime_Up, StopTime_Dn;
   //---
   static int  LastBars_Up, LastBars_Dn;
   static int  LastBarsX_Up, LastBarsX_Dn; 
   static int  LastBarsN_Up, LastBarsN_Dn;
   //---
   static bool BUY_Sign, BUY_Stop;
   static bool SELL_Sign, SELL_Stop;
   static bool NoiseBUY_Sign, NoiseSELL_Sign;
   static double TrendX_Up, TrendX_Dn;
   
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS                                        |
   //----+ +---------------------------------------------------------------+
   if (Test_Up) 
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      int IBARSX_Up = iBars(NULL, TimeframeX_Up);
      int IBARSN_Up = iBars(NULL, TimeframeN_Up);
      //---
      if (IBARS_Up >= MinBar_Up && IBARSX_Up >= MinBarX_Up && IBARSN_Up >= MinBarN_Up)
       {       
         //----+ +----------------------+
         //----+ DETECTING A TREND      |
         //----+ +----------------------+
         if (LastBarsX_Up != IBARSX_Up)
          {
           //----+ Initialization of variables
           LastBarsX_Up = IBARSX_Up;
           BUY_Sign = false;
           BUY_Stop = false;
           
           // Trend direction detecting algorithm on the largest timeframe 
                                              //(initializing variable TrendX_Up)
           
           //----+ defining a signal to close trades
           if (TrendX_Up < 0)
                      BUY_Stop = true;                                      
          }
         
         //----+ +----------------------------------------+
         //----+ DETECTING SIGNALS TO ENTER THE MARKET    |
         //----+ +----------------------------------------+
         if (LastBars_Up != IBARS_Up && TrendX_Up > 0)
          {
           //----+ Initialization of variables
           BUY_Sign = false;
           LastBars_Up = IBARS_Up;
           //----+ Initialization of noise variables
           NoiseBUY_Sign = false;
           StopTime_Up = iTime(NULL, Timeframe_Up, 0)
                                          + 50 * Timeframe_Up;
                    
           // Entering point determining algorithm on the middle timeframe
                                                //(Initializing variable BUY_Sign)
                                             
          }
         
         //----+ +------------------------------------------------+
         //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET      |
         //----+ +------------------------------------------------+
         if (BUY_Sign)
          if (LastBarsN_Up != IBARSN_Up)
           {
             NoiseBUY_Sign = false;
             LastBarsN_Up = IBARSN_Up;
             //---
             
             // Entering point precising algorithm on the smallest timeframe
                                            //(Initializing variable NoiseBUY_Sign)
                                           
           }
         
         //----+ +-------------------+
         //----+ MAKING TRADES       |
         //----+ +-------------------+
         if (NoiseBUY_Sign)
           if (!OpenBuyOrder1(BUY_Sign, 1, Money_Management_Up, 
                                          STOPLOSS_Up, TAKEPROFIT_Up))
                                                                 return(-1);
         if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop, 1))
                                        return(-1);
        }
     }
     
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS                                       |
   //----+ +---------------------------------------------------------------+
   if (Test_Dn) 
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      int IBARSX_Dn = iBars(NULL, TimeframeX_Dn);
      int IBARSN_Dn = iBars(NULL, TimeframeN_Dn);
      //---
      if (IBARS_Dn >= MinBar_Dn && IBARSX_Dn >= MinBarX_Dn && IBARSN_Dn >= MinBarN_Dn)
       {
         //----+ +----------------------+
         //----+ DETECTING A TREND      |
         //----+ +----------------------+
         if (LastBarsX_Dn != IBARSX_Dn)
          {
           //----+ Initialization of variables
           LastBarsX_Dn = IBARSX_Dn;
           SELL_Sign = false;
           SELL_Stop = false;
           
           // Trend direction detecting algorithm on the largest timeframe
                                               //(initializing variable TrendX_Dn)
           
           //----+ defining a signal to close trades
           if (TrendX_Dn > 0)
                      SELL_Stop = true;                                      
          }
         
         //----+ +----------------------------------------+
         //----+ DETECTING SIGNALS TO ENTER THE MARKET    |
         //----+ +----------------------------------------+
         if (LastBars_Dn != IBARS_Dn && TrendX_Dn < 0)
          {
           //----+ Initialization of variables
           SELL_Sign = false;
           LastBars_Dn = IBARS_Dn;
           //----+ Initialization of noise variables
           NoiseSELL_Sign = false;
           StopTime_Dn = iTime(NULL, Timeframe_Dn, 0)
                                          + 50 * Timeframe_Dn;
           
           // Entering point determining algorithm on the middle timeframe
                                                //(Initializing variable SELL_Sign) 
                             
          }
         
         //----+ +------------------------------------------------+
         //----+ DETECTING NOISE SIGNALS TO ENTER THE MARKET      |
         //----+ +------------------------------------------------+
         if (SELL_Sign)
          if (LastBarsN_Dn != IBARSN_Dn)
           {
             NoiseSELL_Sign = false;
             LastBarsN_Dn = IBARSN_Dn;
             //---
             
             // Entering point precising algorithm on the smallest timeframe
                                           //(Initializing variable NoiseSELL_Sign)
    
           }
          
         //----+ +-------------------+
         //----+ MAKING TRADES       |
         //----+ +-------------------+
         if (NoiseSELL_Sign)
           if (!OpenSellOrder1(SELL_Sign, 2, Money_Management_Dn, 
                                            STOPLOSS_Dn, TAKEPROFIT_Dn))
                                                                  return(-1);
           if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop, 2))
                                        return(-1);
        }
     }
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Si queremos utilizar este código como plantilla para escribir Asesores Expertos, tenemos en primer lugar que inicializar las variables en sus correspondientes bloques: "DETECTING A TREND" (detección de tendencia) y "DETECTING NOISE SIGNAL TO ENTER THE MARKET" (detección de las señales del ruido para entrar al mercado):

TrendX_Up = 1;
TrendX_Dn =-1;
Noise8uy_Sign = true;
NoiseSELL_Sign = true;

Después de esto, puede añadir sus propios códigos en los bloques "DETECTING SIGNALS TO ENTER THE MARKET" (detección de señales para entrar al mercado) y configurar el Asesor Expertos con este código. Puede aprender cómo se hace en el código del Asesor Experto Exp_15_A.mq4, en el cual sólo hay algoritmos para detectar señales para entrar al mercado con los períodos de tiempo intermedios, no tiene algoritmos para detectar la tendencia en los períodos de tiempo más largos o en los más pequeños (donde se detecta la tendencia del ruido). Hay que prestar atención a la inicialización de las variables para el número más pequeño de barras en el bloque init(), en este caso:

//---- Initialization of variables             
   MinBarX_Up = 0;
   MinBar_Up = 4 + 3 * JXLength_Up + 30;
   MinBarN_Up = 0;

//---- Initialization of variables
   MinBarX_Dn = 0;
   MinBar_Dn = 4 + 3 * JXLength_Dn + 30;
   MinBarN_Dn = 0;

En un segundo paso hay que eliminar la inicialización de los bloques "DETECTING A TREND":

TrendX_Up = 1;
TrendX_Dn =-1;

Añada su código para detectar la dirección de la tendencia en estos bloques y vuelva a ajustar el Asesor Experto. Se muestra esta etapa de escritura del código en Exp_15_B.mq4. Acuérdese de inicializar las variables MinBarX_Up y MinBarX_Dn en el bloque init():

//---- Initialization of variables             
   MinBarX_Up = 2 + PeriodWATR_Up;
   MinBar_Up = 4 + 3 * JXLength_Up + 30;
   MinBarN_Up = 0;

//---- Initialization of variables
   MinBarX_Dn = 2 + PeriodWATR_Dn;
   MinBar_Dn = 4 + 3 * JXLength_Dn + 30;
   MinBarN_Dn = 0;

Como resultado, tenemos un Asesor Experto trabajando en dos períodos de tiempo. En el tercer paso es exactamente igual que con el código en los bloques "DETECTING NOISE SIGNALS TO ENTER THE MARKET", después de haber eliminado previamente la inicialización

Noise8uy_Sign = true;
NoiseSELL_Sign = true;

de estos bloques y añadir las operaciones aritméticas para la inicialización de las variables para el número más pequeño de barras en el bloque init(), en este caso:

//---- Initialization of variables             
   MinBarX_Up = 2 + PeriodWATR_Up;
   MinBar_Up = 4 + 3 * JXLength_Up + 30;
   MinBarN_Up = 4 + Noise_period_Up + SmoothN_Up;

//---- Initialization of variables
   MinBarX_Dn = 2 + PeriodWATR_Dn;
   MinBar_Dn = 4 + 3 * JXLength_Dn + 30;
   MinBarN_Dn = 4 + Noise_period_Dn + SmoothN_Dn;

Por lo tanto, el código del Asesor Experto tiene ahora tres etapas. Si tratamos de implementar este código en una sola etapa es posible cometer algún error y no va a ser fácil detectarlo.

Conclusión

He presentado en este artículo un planteamiento general para escribir Asesores Expertos mediante tres períodos de tiempo. Técnicamente, se puede llevar a cabo esta idea de manera más sencilla en MQL4. Pero surge otra pregunta: ¿Qué soluciones ayudarían a que esta idea tenga cierto sentido práctico?


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

Archivos adjuntos |
EXPERTS.zip (20.37 KB)
INCLUDE.zip (34.56 KB)
indicators.zip (20.7 KB)
TESTER.zip (6.29 KB)
Cómo cortar un código de AE para una vida más fácil y menos errores. Cómo cortar un código de AE para una vida más fácil y menos errores.
Un simple concepto que se describe en el artículo, permite simplificar los sistemas de trading existentes a aquellos que desarrollan sistemas de trading automático en MQL4, así como a reducir el tiempo necesario para desarrolloar estos nuevos sistemas, gracias a los códigos más cortos.
Interacción entre MetaTrader 4 y Matlab mediante DDE Interacción entre MetaTrader 4 y Matlab mediante DDE
Instrucciones paso a paso sobre cómo organizar la transferencia de datos desde Matlab a MetaTrader 4 usando DDE.
Cómo crear un bot para Telegram en el lenguaje MQL5 Cómo crear un bot para Telegram en el lenguaje MQL5
Este artículo es una guía paso a paso para crear un bot para Telegram en el lenguaje MQL5 El material será de interés para aquellos que quieren vincular un bot comercial a su dispositivo móvil. En el artículo se dan ejemplos de bots que envían señales comerciales, buscan información en páginas web y mandan información sobre el estado de la cuenta comercial, cotizaciones y capturas de pantalla de gráficos a su teléfono inteligente.
Lite_EXPERT2.mqh: Ejemplos de implementación de Asesores Expertos Lite_EXPERT2.mqh: Ejemplos de implementación de Asesores Expertos
En este artículo, el autor sigue familiarizando los lectores con las funciones de Lite_EXPERT2.mqh mediante ejemplos reales de implementación de Asesores Expertos. El artículo aborda el concepto de utilizar las órdenes pendientes flotantes y las órdenes pendientes que cambian de forma dinámica entre una transacción y otra en base al los valores del indicador Average True Range (ATR).