English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Sistemas de trading simples usando indicadores semáforo

Sistemas de trading simples usando indicadores semáforo

MetaTrader 5Sistemas comerciales | 26 diciembre 2013, 10:22
5 735 0
Nikolay Kositsin
Nikolay Kositsin

Introducción

Los indicadores semáforo o indicadores de señal son simples detectores que indican el momento para entrar o salir del mercado. Cuando hay una señal de entrada en la barra actual aparece una etiqueta en un gráfico del símbolo. Esta etiqueta puede usarse como condición para realizar una transacción.

Hay muchos indicadores de este tipo, pero la verdadera esencia del sistema de trading original basado en estos indicadores no ha cambiado en absoluto. Por tanto, es una buena idea implementarlo de la forma más simple y universal. Esto permitirá usar posteriormente el resultado obtenido al trabajar con indicadores similares, sin tener que realizar grandes cambios.

Fig.1. Indicador de señal de semáforo ASCtrend

Fig.1. Indicador de señal de semáforo ASCtrend

Fig.2. Indicador ASCtrend. Señal de trading para realizar una transacción 

Fig.2. Señal de trading para realizar una transacción usando el indicadores de señal de semáforo


Ejemplos típicos de indicadores de señal de semáforo

Actualmente hay muchos indicadores de este tipo en la base de código. En este artículo voy a proporcionar solo unos pocos enlaces a las páginas web correspondientes:

Además de los indicadores de señal de semáforo, hay un grupo de indicadores de tendencia de semáforo:

Fig.3. Señales de trading usando el indicador Heiken_Ashi_Smoothed 

Fig.3. Indicador de tendencia de semáforo

 

Fig.4. Señal de trading para realizar una transacción usando un indicador de tendencia de semáforo Heiken_Ashi_Smoothed

Fig.4. Señal de trading para realizar una transacción usando un indicador de tendencia de semáforo Heiken_Ashi_Smoothed

Los sistemas de trading que emplean estos indicadores utilizan un código ligeramente distinto para obtener señales de trading, mientras que el código del asesor experto permanece prácticamente inalterado.

Ejemplos típicos de indicadores de tendencia de semáforo

La base de código contiene una gran cantidad de estos indicadores. En este artículo voy a proporcionar solo unos pocos enlaces a las páginas web correspondientes:

 

Datos básicos para crear un sistema de trading:

  1. Indicadores semáforo con los parámetros de entrada que estarán presentes en el asesor experto;
  2. Lista de parámetros de trading del asesor experto de entrada adicionales:
    • un porcentaje de los recursos financieros de depósitos usados en la transacción;
    • un tamaño de Stop Loss y Take Profit (las órdenes pendientes no deben usarse en caso de valores cero);
    • retardo (diferencia máxima permitida entre los precios de la transacción actual y los establecidos);
    • índice de la barra, desde el que las señales de trading serán recibidas;
    • permisos para abrir posiciones cortas y largas;
    • permisos para el cierre forzado de posiciones largas y cortas de acuerdo con las señales del indicador.

Por supuesto, sería mucho más adecuado dar órdenes para realizar transacciones usando las funciones de trading universales. Estas funciones son muy complejas y deben ser empaquetadas en una librería separada para que el código de la aplicación sea lo más sencillo posible.

El código del asesor experto que implementa el sistema de trading de semáforo:

//+------------------------------------------------------------------+
//|                                                 Exp_ASCtrend.mq5 |
//|                             Copyright © 2011,   Nikolay Kositsin |
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, Nikolay Kositsin"
#property link      "farria@mail.redcom.ru"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Parámetros de entrada del indicador del Expert Advisor           |
//+------------------------------------------------------------------+
input double MM=-0.1;             // porcentaje de un depósito en un contrato, valores negativos - tamaño de lote
input int    StopLoss_=1000;      // Stop loss en puntos
input int    TakeProfit_=2000;    // Take profit en puntos
input int    Deviation_=10;       // Max. price deviation in points
input bool   BuyPosOpen=true;     // Permission to buy
input bool   SellPosOpen=true;    // Permission to sell
input bool   BuyPosClose=true;    // Permission to exit long positions
input bool   SellPosClose=true;   // Permission to exit short positions
//+----------------------------------------------+
//| ASCtrend indicator input parameters          |
//+----------------------------------------------+
input ENUM_TIMEFRAMES InpInd_Timeframe=PERIOD_H1; // ASCtrend indicator time frame
input int  RISK=4;                               // Risk level
input uint SignalBar=1;                          // Bar index for getting an entry signal
//+----------------------------------------------+

int TimeShiftSec;
//---- declaration of integer variables for the indicators handles
int InpInd_Handle;
//---- declaration of integer variables of the start of data calculation
int min_rates_total;
//+------------------------------------------------------------------+
//| Trading algorithms                                               |
//+------------------------------------------------------------------+
#include <TradeAlgorithms.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---- getting ASCtrend indicator handle
   InpInd_Handle=iCustom(Symbol(),InpInd_Timeframe,"ASCtrend",RISK);
   if(InpInd_Handle==INVALID_HANDLE) Print(" Failed to get handle of ASCtrend indicator");

//---- initialization of a variable for storing a chart period in seconds  
   TimeShiftSec=PeriodSeconds(InpInd_Timeframe);

//---- initialization of variables of the start of data calculation
   min_rates_total=int(3+RISK*2+SignalBar);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----
   GlobalVariableDel_(Symbol());
//----
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---- checking the number of bars to be enough for calculation
   if(BarsCalculated(InpInd_Handle)<min_rates_total) return;
   
//---- uploading history for IsNewBar() and SeriesInfoInteger() functions normal operation  
   LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe);

//---- declaration of local variables
   double DnVelue[1],UpVelue[1];
//---- declaration of static variables
   static bool Recount=true;
   static bool BUY_Open=false,BUY_Close=false;
   static bool SELL_Open=false,SELL_Close=false;
   static datetime UpSignalTime,DnSignalTime;
   static CIsNewBar NB;

//+----------------------------------------------+
//| Searching for deals performing signals       |
//+----------------------------------------------+
   if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar
     {
      //---- zeroing out trading signals
      BUY_Open=false;
      SELL_Open=false;
      BUY_Close=false;
      SELL_Close=false;
      Recount=false;

      //---- copy newly appeared data into the arrays
      if(CopyBuffer(InpInd_Handle,1,SignalBar,1,UpVelue)<=0) {Recount=true; return;}
      if(CopyBuffer(InpInd_Handle,0,SignalBar,1,DnVelue)<=0) {Recount=true; return;}

      //---- getting buy signals
      if(UpVelue[0] && UpVelue[0]!=EMPTY_VALUE)
        {
         if(BuyPosOpen) BUY_Open=true;
         if(SellPosClose) SELL_Close=true;
         UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- getting sell signals
      if(DnVelue[0] && DnVelue[0]!=EMPTY_VALUE)
        {
         if(SellPosOpen) SELL_Open=true;
         if(BuyPosClose) BUY_Close=true;
         DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- searching for the last trading direction for getting positions closing signals
      //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //if execution is set to "Random delay" in the Strategy Tester 
      if((BuyPosOpen && BuyPosClose || SellPosOpen && SellPosClose) && (!BUY_Close && !SELL_Close))
        {
         int Bars_=Bars(Symbol(),InpInd_Timeframe);

         for(int bar=int(SignalBar+1); bar<Bars_; bar++)
           {
            if(SellPosClose)
              {
               if(CopyBuffer(InpInd_Handle,1,bar,1,UpVelue)<=0) {Recount=true; return;}
               if(UpVelue[0]!=0 && UpVelue[0]!=EMPTY_VALUE)
                 {
                  SELL_Close=true;
                  break;
                 }
              }

            if(BuyPosClose)
              {
               if(CopyBuffer(InpInd_Handle,0,bar,1,DnVelue)<=0) {Recount=true; return;}
               if(DnVelue[0]!=0 && DnVelue[0]!=EMPTY_VALUE)
                 {
                  BUY_Close=true;
                  break;
                 }
              }
           }
        }
     }

//+----------------------------------------------+
//| Performing deals                             |
//+----------------------------------------------+
//---- Closing a long position
   BuyPositionClose(BUY_Close,Symbol(),Deviation_);

//---- Closing a short position   
   SellPositionClose(SELL_Close,Symbol(),Deviation_);

//---- Buying
   BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);

//---- Selling
   SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);
//----
  }
//+------------------------------------------------------------------+

El código para realizar esta idea es muy simple y claro, aunque deben aclararse algunos detalles.

El período del gráfico usado por un indicador de señal y un asesor experto se fija en la variable de entrada InpInd_Timeframe del asesor experto. Por tanto, el cambio de un gráfico en el que se sitúa un asesor experto no altera este parámetro para el mismo.

La función IsNewBar() era necesaria para determinar el momento en el que la nueva barra es implementada como una clase situada en el archivo TradeAlgorithms.mqh. Esto permite usar cualquier número de funciones de este tipo en el código fácilmente, estableciendo una variable ClsNewBar estática individual para cada una de ellas.

Las variables UpSignalTime y DnSignalTime se usan para guardar y transferir el tiempo tras el cual es posible realizar la próxima transacción después de la anterior a las funciones de trading. En nuestro caso esta característica se usa para evitar tener que realizar varias transacciones en la misma dirección en la misma barra (cuando se realiza una transacción, la función de trading almacena el momento de finalización de la barra actual y no realiza nuevas transacciones en la misma dirección hasta ese instante).

El bloque "Buscando la última dirección de trading para obtener señales para posiciones de cierre" en la función OnTick() es necesario para poder recibir señales de cierre de posición en las barras sin señales de trading. En los casos de funcionamiento normal de un asesor experto no es necesario. Pero si ocurre un fallo en la conexión a internet es muy posible que se pierda una nueva señal de trading. No es buena idea entrar al mercado post factum, pero sí será una buena opción cerrar las posiciones abiertas.


Usando el sistema de trading con otros indicadores de señal de semáforo

Ahora, si es necesario usar este código con otro indicadores de señal de semáforo, deben realizarse las siguientes acciones:

  1. Reemplazar los datos del indicador previo por los parámetros necesarios del nuevo en los parámetros de entrada de un asesor experto;
  2. Cambiar el código de obtención del controlador del indicador en el bloque OnInit();
  3. Determinar los índices para los buffers de indicador usados para almacenar las señales de trading buy y sell desde el código del indicador e introducirlos adecuadamente en las llamadas a la función CopyBuffer() del bloque OnTick(). En este caso se usan los buffers de indicador cero y primero;
  4. Cambiar la inicialización de la variable del punto de inicio del cálculo de los datos (min_rates_total) en un asesor experto de acuerdo con el código del indicador;
  5. Cambiar el bloque "Buscando la última dirección de trading para obtener señales para posiciones de cierre" en la función OnTick() de acuerdo con el código del indicador.


Usando el sistema de trading con otros indicadores de tendencia de semáforo

Al usar este sistema de trading con indicadores de tendencia de semáforo, el código del asesor experto cambia un poco en el bloque para determinar las señales para las transacciones de la función OnTick(). Por ejemplo, el código para el asesor experto basado en el indicador FiboCandles será como se indica a continuación :

//+------------------------------------------------------------------+
//| Función tick del experto                                         |
//+------------------------------------------------------------------+
void OnTick()
  {
//---- verificando el número de barras para que sean suficientes para el cálculo
   if(BarsCalculated(InpInd_Handle)<min_rates_total) return;   

//---- subiendo el historial para las funciones IsNewBar() y SeriesInfoInteger()  
   LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe);

//---- declaración de variables locales
   double TrendVelue[2];
//---- declaración de variables estáticas
   static bool Recount=true;
   static bool BUY_Open=false,BUY_Close=false;
   static bool SELL_Open=false,SELL_Close=false;
   static datetime UpSignalTime,DnSignalTime;
   static CIsNewBar NB;

//+----------------------------------------------+
//| buscando señales que realizan transacciones  |
//+----------------------------------------------+
   if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar
     {
      //---- poniendo a cero las señales de trading
      BUY_Open=false;
      SELL_Open=false;
      BUY_Close=false;
      SELL_Close=false;
      Recount=false;

      //---- copiando los datos nuevos obtenidos a las matrices
      if(CopyBuffer(InpInd_Handle,4,SignalBar,2,TrendVelue)<=0) {Recount=true; return;}

      //---- obteniendo señales buy
      if(TrendVelue[0]==1 && TrendVelue[1]==0)
        {
         if(BuyPosOpen) BUY_Open=true;
         if(SellPosClose)SELL_Close=true;
         UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- obteniendo señales sell
      if(TrendVelue[0]==0 && TrendVelue[1]==1)
        {
         if(SellPosOpen) SELL_Open=true;
         if(BuyPosClose) BUY_Close=true;
         DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec;
        }

      //---- buscando la última dirección de trading para obtener señales de cierre de posiciones
      //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //si la ejecución se establece en  "retraso aleatorio" en el probador de estrategia 
        {
         if(SellPosOpen && SellPosClose  &&  TrendVelue[1]==0) SELL_Close=true;
         if(BuyPosOpen  &&  BuyPosClose  &&  TrendVelue[1]==1) BUY_Close=true;
        }
     }

//+----------------------------------------------+
//| realizando transacciones                     |
//+----------------------------------------------+
//---- Cerrando una posición larga
   BuyPositionClose(BUY_Close,Symbol(),Deviation_);

//---- Cerrando una posición corta   
   SellPositionClose(SELL_Close,Symbol(),Deviation_);

//---- Comprando
   BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);

//---- Vendiendo
   SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_);
//----
  }

En este caso, las señales de trading son recibidas solo desde un buffer de indicador de color (que contiene los índices de color). Los datos en este buffer solo pueden tener dos valores: 0 - para mercado ascendente y 1 - para el descendente. El código del bloque "Buscando la última dirección de trading para obtener señales de cierre de posiciones" ha pasado a ser lo más simple posible, ya que una dirección de tendencia en cualquier barra puede recibirse desde la celda apropiada del buffer del indicador.

En el bloque "Reallizando transacciones" las funciones de cierre de posiciones van primero, seguidas por las funciones de apertura. Cuando se da la secuencia opuesta solo será posible cerrar las transacciones en una barra ¡y no podremos abrirlas simultáneamente al hacer pruebas en el modo "solo precios abiertos"! Por tanto, los resultados de trading se verán afectados.


Probando el sistema de trading

Antes de proceder a probar el sistema de trading debe aclararse un importante detalle. Cuando el valor de la variable de entrada SignalBar es igual a cero, el asesor experto obtendrá transacciones ejecutando señales desde la barra actual. Pero la señal de la barra actual no es de confianza cuando indica el cambio de la tendencia en sentido opuesto a esta señal en la barra anterior. Las señales en la barra actual pueden aparecer y desaparecer, mientras que una tendencia puede ir en contra de estas señales durante mucho tiempo. Esto puede verse fácilmente si se prueba un asesor experto en todos los ticks con la visualización habilitada y la variable SignalBar es igual a cero. La visualización del funcionamiento del indicador ASCtrend muestra un claro síntoma de este hecho en tal caso.

De nuevo, solo el modo "Every tick" es apropiado para la optimización de un asesor experto con una señal recibida de la barra actual. En caso de que se vaya a recibir de alguna otra barra cerrada, es suficiente el modo "solo precios abiertos". Esto acelera enormemente el análisis del comportamiento del sistema de trading sin grandes pérdidas de calidad.

Por tanto, ¡es mejor no usar señales de la barra actual para probar y optimizar estos sistemas de trading!

Por ello vamos a probar el asesor experto con los parámetros por defecto en EUR/USD desde el principio del año hasta el comienzo de diciembre:

Fig.5. Resultados de las pruebas del Expert Advisor Exp_ASCtrend con los parámetros por defecto en EUR/USD H1. 

Fig.5. Resultados de las pruebas del asesor experto Exp_ASCtrend con los parámetros por defecto en EUR/USD H1  

Después de cambiar un poco los ajustes del asesor experto en el probador de estrategias, encontramos con facilidad la combinación más adecuada de los parámetros del asesor experto para los datos históricos existentes:

 Fig.6. Resultados de las pruebas del Expert Advisor Exp_ASCtrend después de la optimización con mejores parámetros en EUR/USD H1

Fig.6. Resultados de las pruebas del asesor experto Exp_ASCtrend después de la optimización con mejores parámetros en EUR/USD H1  

El proceso de optimización del sistema de trading no tiene nada de especial, por eso solo proporciono un enlace al artículo que describe este proceso en detalle: "MQL5: Guía para pruebas y optimización de asesores expertos en MQL5".

Por supuesto, sería ingenuo esperar grandes beneficios de un sistema de trading tan simple. Pero es muy posible alcanzar buenos resultados si se gestiona con habilidad este sistema semiautomático y es ajustado regularmente según el comportamiento del mercado en cada momento.

Por ejemplo, hubo una tendencia al alza en el gráfico EUR/USD H12 en 2011 desde enero a mayo. Y fue fácilmente detectable en las primeras etapas:

Fig.7. Gráfico EUR/USD H12 (enero/mayo 2011)

Fig.7. Gráfico EUR/USD H12 (enero/mayo 2011)

Sería interesante probar el asesor experto en este intervalo de tiempo con los ajustes por defecto, la posibilidad de comprar solo y el uso de solo un 5% de un depósito (MM=0.05). Aquí están los resultados del asesor experto con dichos parámetros probados en el gráfico H1:

Fig.8. Resultados de las pruebas del Expert Advisor Exp_ASCtrend con los parámetros por defecto de EUR/USD H1 para enero/mayo 2011 (solo posiciones largas, MM=0.05) 

Fig.8. Resultados de las pruebas del asesor experto Exp_ASCtrend con los parámetros por defectode EUR/USD H1 para enero/mayo 2011 (solo posiciones largas, MM=0.05)

Por supuesto, en este caso un operador es completamente responsable de seleccionar una dirección de la transacción. Pero si tenemos en mente que debe realizarse usando gráficos de grandes períodos de tiempo será difícil que nos encontremos con grandes dificultades.


Modificación del módulo de trading para usarlo con otro indicador

Este artículo podría haber terminado aquí, pero MetaEditor ha adquirido la posibilidad de generar asesores expertos basados en módulos de trading ya prediseñados. El proceso para crear dichos módulos con todo el material que hemos visto aquí es muy complejo y requiere un estudio separado. Por tanto, me voy a centrar en los módulos de trading ya diseñados que son completamente análogos a los sistemas de trading que he sugerido. Y solo después de eso voy a ir a los detalles sobre la modificación de dichos módulos de acuerdo con los indicadores de la señal concreta, evitando entrar en detalles innecesarios.

Vamos a asumir que ya tenemos el conjunto de módulos de trading para sistemas de señales de semáforo (MySignals.zip) y queremos crear el módulo análogo para un indicador particular. Vamos a considerar el indicador BykovTrendSignal.mq5, que es un indicador de señal de semáforo típico. En primer lugar, debemos encontrar el análogo más preciso del indicador en este grupo (Indicators.zip). Vemos que el primer indicador de este artículo (ASCtrend) es el más parecido a él.  Por tanto, vamos a usar el módulo de trading de este indicador para la modificación.

Teniendo en cuenta su uso en el código del programa requerido, el indicador mismo (BykovTrend) tiene un conjunto de parámetros de entrada:

//+----------------------------------------------+
//| Parámetros de entrada del indicador          |
//+----------------------------------------------+
input int RISK=3;
input int SSP=9;
//+----------------------------------------------+

Y necesitamos los índices de los buffers de indicador usados para guardar las señales para realizar transacciones. En nuestro caso estos son: 0 - para señales sell y 1 - para señales buy.

Ahora que conocemos cuál es el módulo que debe usarse para la modificación, lo copiamos en la carpeta \MQL5\Include\Expert\Signal\MySignals\ con el nombre de archivo BykovTrendSignal.mqh y lo abrimos en MetaEditor. Hay una expresión muy habitual en el código "ASCtrend" (el nombre del indicador previo). Debe ser reemplazada por el nombre del nuevo indicador ("BykovTrend"). Para hacer esto, presione las teclas "Ctrl" y "H" simultáneamente y haga el cambio necesario:

 Cambiando el nombre del indicador en el código del módulo de trading

Fig.9. Cambiar el nombre del indicador en el código del módulo de trading

La siguiente etapa de nuestro trabajo es la más minuciosa. Debemos reemplazar todo lo relacionado con los parámetros de entrada del indicador en el código del módulo de trading. El proceso es muy similar al que se indicó en el artículo "MQL5 Wizard: cómo crear un módulo de señales de trading.

En primer lugar, debemos hacer algunos cambios en el bloque comentado de la descripción de la clase de señalaes de trading de MQL5 Wizard:

//+----------------------------------------------------------------------+
//| Descripción de la clase                                              |
//| Title=Las señales basadas en el indicador BykovTrend                 |
//| Type=SignalAdvanced                                                  |
//| Name=BykovTrend                                                      |
//| Class=CBykovTrendSignal                                              |
//| Page=                                                                |
//| Parameter=BuyPosOpen,bool,true,Permission to buy                     |
//| Parameter=SellPosOpen,bool,true,Permission to sell                   |
//| Parameter=BuyPosClose,bool,true,Permission to exit a long position   |
//| Parameter=SellPosClose,bool,true,Permission to exit a short position |
//| Parameter=Ind_Timeframe,ENUM_TIMEFRAMES,PERIOD_H1,Timeframe          |
//| Parameter=RISK,int,4,Risk level                                      |
//| Parameter=SSP,int,9,SSP                                              |
//| Parameter=SignalBar,uint,1,Bar index for entry signal                |
//+----------------------------------------------------------------------+
//--- final de la descripción del wizard 
//+----------------------------------------------------------------------+
//| Clase CBykovTrendSignal.                                             |
//| Finalidad: Clase del generador de señales de trading basada en       |
//| Indicador BykovTrend https://www.mql5.com/ru/code/497/.               |
//|             Deriva de la clase CExpertSignal.                        |
//+----------------------------------------------------------------------+

Ambos indicadores contienen la misma variable de entrada RISK, y por tanto se deben dejar. Pero en estos indicadores su valor por defecto es distinto. De hecho, esta diferencia no es crítica y puede permanecer sin cambios. Se ha añadido la línea de comentario sobre la variable SSP:

//| Parameter=SSP,int,9,SSP                                              |

Y el enlace al indicador de la base de código ha sido reemplazado:

//| Purpose: Clase del generador de señales de trading basada en         |
//| valores BykovTrend  https://www.mql5.com/ru/code/497/.                |

Ahora, todo lo relacionado con los cambios en los parámetros de entrada debe reflejarse en la descripción de la clase de señales de trading CBykovTrendSignal. Tenemos la línea de la nueva declaración de la variable de la clase m_SSP en los parámetros de los ajustes:

   uint              m_SSP;              // SSP

 y la línea de la nueva declaración del método de instalación de los parámetros de los ajustes de SPP():

   void               SSP(uint value)                         { m_SSP=value;              } 

Todo lo relacionado con la variable de entrada RISK en el módulo de señales de trading que creemos es equivalente el módulo de entrada y, por tanto, no hay cambios en el actual ni en ningún otro bloque del módulo de trading.

Ahora pasamos al constructor de la clase CBykovTrendSignal::CBykovTrendSignal(). Debe añadirse a este bloque la inicialización de una nueva variable:

   m_SSP=4;

En el bloque de verificación de los parámetros de ajuste de CBykovTrendSignal::ValidationSettings(), debe realizarse una comprobación de la nueva variable para evaluar si es correcta.

   if(m_SSP<=0)
     {
      printf(__FUNCTION__+": SSP must be above zero");
      return(false);
     }

Después de esto podemos pasar al bloque de inicialización del indicador BykovTrend - BykovTrendSignal::InitBykovTrend(). El nuevo indicador tiene un número diferente de variables de entrada y, por tanto, también será diferente la dimensión de la matriz de parámetros de entrada declarada:

//--- estableciendo los parámetros del indicador
   MqlParam parameters[3];

En nuestro caso necesitamos una dimensión para el nombre del string del indicador y dos más para sus parámetros de entrada.

Ahora tenemos que inicializar una nueva celda de las matrices de los parámetros de entrada, indicando el tipo de variable que se guardará en ella:

   parameters[2].type=TYPE_INT;
   parameters[2].integer_value=m_SSP;

 Después de esto, cambia el número de variables de entrada por 3 en este bloque en la llamada para la inicialización del indicador:

//--- inicialización del objeto   
   if(!m_indicator.Create(m_symbol.Name(),m_Ind_Timeframe,IND_CUSTOM,3,parameters))

El número de buffers en el indicador permanece sin cambios y es igual a dos, y por tanto no hay necesidad de cambiar nada en la línea de inicialización del número de buffers del indicador en nuestro caso:

//--- número de buffers
   if(!m_indicator.NumBuffers(2))  return(false);

Los indicadores de tendencia ASCtrend y BykovTrend tienen dos buffers de indicador cada uno. Las funciones de los buffers son completamente iguales. El buffer cero se usa para almacenar señales sell, mientras que el buffer de índice 1 se usa para almacenar señales buy. Por tanto, no es necesario cambiar nada en los bloques de las funciones para enviar las señales de trading CBykovTrendSignal::LongCondition() y CBykovTrendSignal::ShortCondition() y puede considerarse completado el trabajo de modificación del módulo de señales de trading.

Pero, en general, todos los indicadores de semáforo son distintos y, por tanto, los bloques para los distintos indicadores semáforo pueden diferir entre sí considerablemente. El archivo del módulo de trading MySignals.zip y el archivo Indicators.zip contienen abundantes ejemplos para crear varios indicadores. Tras algunas revisiones, es posible encontrar la información sobre el proceso de sustitución y las posibles versiones del código para este.

Ahora me gustaría centrarme en la variable de entrada Ind_Timeframe del módulo de señales de trading. Esta variable permite descargar un período de tiempo adecuado en el indicador. Sin embargo, el asesor experto generado opera en el mismo marco al que fue asignado. Esto significa que el período de tiempo de la variable de entrada nunca debe exceder un período del gráfico sobre el que opera el asesor experto para proporcionar un funcionamiento normal del módulo.

Finalmente, me gustaría mostrar otra peculiaridad de la creación de módulos de señales de trading. Algunas veces la enumeraciones personalizadas son implementadas en el código del indicador básico como tipos para las variables de entrada del módulo. Por ejemplo, la enumeración personalizada Smooth_Method se usa como tipo de variable MA_SMethod para el indicador Candles_Smoothed:

//+-----------------------------------+
//|  Declaración de enumeraciones     |
//+-----------------------------------+
enum Smooth_Method
  {
   MODE_SMA_,  // SMA
   MODE_EMA_,  // EMA
   MODE_SMMA_, // SMMA
   MODE_LWMA_, // LWMA
   MODE_JJMA,  // JJMA
   MODE_JurX,  // JurX
   MODE_ParMA, // ParMA
   MODE_T3,    // T3
   MODE_VIDYA, // VIDYA
   MODE_AMA,   // AMA
  }; */
//+----------------------------------------------+
//| Parámetros de entrada del indicador          |
//+----------------------------------------------+
input Smooth_Method MA_SMethod=MODE_LWMA; // Método Smoothing 
input int MA_Length=30;                   // Profundidad Smoothing                     
input int MA_Phase=100;                   // Parámetro Smoothing 
                                          // para JJMA variando dentro del rango -100 ... +100,
                                          // para VIDIA es un período CMO, para AMA es un período de media lenta
//+----------------------------------------------+

En tal caso, las variables de entrada de este tipo y todos los elementos asociados en el módulo de señales de trading (Candles_SmoothedSignal.mqh) deben modificarse en las variables de tipo int y uint. También debe realizarse el procedimiento inverso de enumeraciones personalizadas hasta los parámetros de entrada del asesor experto y la sustitución de los tipos de variables de entrada necesaria (asesor experto de ExpM_Candles_Smoothed) para facilitar el uso de las variables de entrada en el código ya generado del asesor experto terminado.

//+------------------------------------------------------------------+
//|  Declaración de enumeraciones                                    |
//+------------------------------------------------------------------+
enum Smooth_Method
  {
   MODE_SMA_,  // SMA
   MODE_EMA_,  // EMA
   MODE_SMMA_, // SMMA
   MODE_LWMA_, // LWMA
   MODE_JJMA,  // JJMA
   MODE_JurX,  // JurX
   MODE_ParMA, // ParMA
   MODE_T3,    // T3
   MODE_VIDYA, // VIDYA
   MODE_AMA,   // AMA
  };
//+------------------------------------------------------------------+
//| Entradas                                                         |
//+------------------------------------------------------------------+
//--- entradas para el experto
input string          Expert_Title         ="Candles_Smoothed"; // Nombre del documento
ulong                 Expert_MagicNumber   =29976;              // 
bool                  Expert_EveryTick     =false;              // 
//--- entradas para la señal principal
input int             Signal_ThresholdOpen =40;                 // Valor del umbral de la señal para abrir [0...100]
input int             Signal_ThresholdClose=20;                 // Valor del umbral de la señal para cerrar [0...100]
input double          Signal_PriceLevel    =0.0;                // Nivel de precio para ejecutar una transacción
input double          Signal_StopLevel     =50.0;               // nivel Stop Loss (en puntos)
input double          Signal_TakeLevel     =50.0;               // nivel Take Profit (en puntos)
input int             Signal_Expiration    =1;                  // vencimiento de las órdenes pendientes (en barras)ars)
input bool            Signal__BuyPosOpen   =true;               // Permiso para comprar de Candles_Smoothed() 
input bool            Signal__SellPosOpen  =true;               // Permiso para vender de Candles_Smoothed() 
input bool            Signal__BuyPosClose  =true;               // Permiso para dar salida a una posición larga de Candles_Smoothed() 
input bool            Signal__SellPosClose =true;               // Candles_Smoothed() Permiso para dar salida a una posición corta
input ENUM_TIMEFRAMES Signal__Ind_Timeframe=PERIOD_H1;            // Período de tiempo de Candles_Smoothed() 
input Smooth_Method   Signal__MA_SMethod   =4;                  // Método Smoothing (1 - 10) de Candles_Smoothed() 
input uint            Signal__MA_Length    =30;                 // Profundidad Smoothing de Candles_Smoothed()  
input uint            Signal__MA_Phase     =100;                // Parámetro Smoothing de Candles_Smoothed() 
input uint            Signal__SignalBar    =1;                  // Índice de barra para la señal de entrada de Candles_Smoothed() 
input double          Signal__Weight       =1.0;                // Peso de Candles_Smoothed() [0...1.0]
//--- Entradas para dinero
input double          Money_FixLot_Percent =10.0;               // Porcentaje
input double          Money_FixLot_Lots    =0.1;                // Volumen fijo

En nuestro caso, esto se ha realizado por la variable de entrada Signal__MA_SMethod.

Puede acelerar la modificación del código considerablemente si abre ambas versiones del código (ASCtrendSignal.mqh y BykovTrendSignal.mqh) simultáneamente en el editor (situando una a la izquierda y la otra a la derecha) y comparar las dos versiones de código con cuidado.

Conclusión

He incluido una cantidad suficiente de asesores expertos basados en el sistema de trading de semáforo en el archivo Experts.zip adjunto a este artículo para permitir a los programadores menos experimentados comprender fácilmente todas las características de la escritura de este código o, al menos, para que puedan trabajar con asesores expertos prediseñados usando indicadores muy conocidos.

Todos los asesores expertos adjuntos se muestran también como módulos de trading para aquellos que quieran usar el simulador de estrategias de trading como base para sus propios sistemas. Estos módulos se encuentran en el archivo MySignals.zip mientras que los sistemas de trading basados en ellos se encuentran en Expertsez.zip. Los indicadores usados en los asesores expertos se encuentran en Indicators.zip. Las rutas para extraer estos archivos son las siguientes:

  • Experts.zip: "\MQL5\Experts\";
  • Expertsez.zip: "\MQL5\Experts\"; 
  • MySignals.zip: "\MQL5\Include\Expert\Signal\MySignals\"; 
  • Indicators.zip: "\MQL5\Indicators\";
  • SmoothAlgorithms.mqh: "\Include\";
  • TradeAlgorithms.mqh: "\Include\".

Reinicie MetaEditor, abra la ventana del navegador, haga clic con el botón derecho del ratón en la etiqueta MQL5 y seleccione "Compilar"en el menú emergente.

El archivo SmoothAlgorithms.mqh es necesario para la compilación de algunos indicadores de Indicators.zip, mientras que el archivo TradeAlgorithms.mqh es necesario para la compilación de todos los asesores expertos de Experts.zip.

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

Archivos adjuntos |
experts.zip (45.12 KB)
expertsez.zip (41.17 KB)
indicators.zip (49.96 KB)
mysignals.zip (57.71 KB)
smoothalgorithms.mqh (278.85 KB)
tradealgorithms.mqh (140.5 KB)
Estrategias con órdenes Expert Advisor multiuso Estrategias con órdenes Expert Advisor multiuso
Este artículo se centra en torno a las estrategias que activamente usan órdenes pendientes, un metalenguaje que puede usarse para describir formalmente tales estrategias, así como en el uso de un Expert Advisor multiuso cuya operativa se basa en dichas descripciones.
El enfoque orientado a objeto para construir paneles multiperíodo y multidivisa El enfoque orientado a objeto para construir paneles multiperíodo y multidivisa
Este artículo describe cómo la programación orientada a objeto puede usarse para crear paneles multiperíodo y multidivisa para Meta Trader 5. El objetivo principal es construir un panel universal que pueda ser usado para mostrar en pantalla diferentes tipos de datos como precios, cambios en los precios, valores de indicador o condiciones sell/buy personalizadas sin necesidad de modificar el código del propio panel.
Una breve guía de inicio rápido para principiantes Una breve guía de inicio rápido para principiantes
¡Hola, apreciado lector! En este artículo intentaré explicarle y mostrarle cómo puede dominar, de forma fácil y rápida, los principios necesarios para crear Expert Advisors, trabajar con indicadores, etc. Está destinado a principiantes y no se utilizarán ejemplos difíciles o complejos.
Las bases de la programación orientada a objetos Las bases de la programación orientada a objetos
No necesita saber qué es poliformismo, encapsulación, etc. para usar la programación orientada a objetos (OOP)... puede simplemente utilizar estas funciones. Este artículo trata las bases de la OOP con ejemplos prácticos.