English Deutsch 日本語
preview
Creación de un modelo de restricción de tendencia de velas (Parte 2): Fusionar indicadores nativos

Creación de un modelo de restricción de tendencia de velas (Parte 2): Fusionar indicadores nativos

MetaTrader 5Trading | 17 septiembre 2024, 09:30
23 0
Clemence Benjamin
Clemence Benjamin

Contenido

  1. Introducción
  2. Mirando atrás en la historia
  3. Identificar algunos problemas del sistema actual
  4. Versionar nuestro próximo programa MQL5
  5. Explorar las medias móviles
  6. Incorporar medias móviles a nuestro programa
  7. Explorando el RSI
  8. Implementación del RSI
  9. Comparación de resultados
  10. Conclusión


Introducción

MetaTrader 5 incluye varios indicadores incorporados que proporcionan a los operadores una importante ventaja analítica en el mercado. En este artículo hablaremos específicamente de dos de ellos: Las medias móviles y el índice de fuerza relativa. Las medias móviles se utilizan habitualmente para identificar la dirección de una tendencia y los posibles niveles de soporte y resistencia. Suavizan los datos de precios para crear una única línea fluida, lo que facilita la detección de tendencias. Por otro lado, el índice de fuerza relativa (Relative Strength Index, RSI) es un oscilador de impulso que mide la velocidad y el cambio de los movimientos de los precios. Los operadores utilizan el RSI para determinar las condiciones de sobrecompra y sobreventa en el mercado, lo que puede ayudarles a tomar decisiones de negociación más informadas. Combinando estos dos indicadores, los operadores pueden obtener información valiosa sobre las tendencias del mercado y los posibles puntos de entrada y salida de sus operaciones. 

Estos son algunos de los indicadores incorporados más utilizados en MetaTrader 5:

  • Medias móviles
  • Bandas de Bollinger
  • Índice de fuerza relativa (RSI)
  • Convergencia/divergencia de la media móvil (Moving Average Convergence Divergence, MACD)
  • Oscilador estocástico
  • Rango medio real (Average True Range, ATR)
  • Ichimoku Kinko Hyo
  • Retroceso de Fibonacci

Al utilizar las medias móviles y el índice de fuerza relativa junto con otras herramientas de análisis técnico, los operadores pueden desarrollar una estrategia de negociación más completa. Supervisando continuamente las condiciones del mercado y ajustando sus estrategias en consecuencia, los operadores pueden adelantarse a los acontecimientos y aprovechar las oportunidades rentables. Es esencial mantenerse disciplinado y paciente, ya que el comercio puede ser impredecible y volátil. Al incorporar las medias móviles y el índice de fuerza relativa a sus análisis, los operadores pueden mejorar su proceso de toma de decisiones y aumentar sus posibilidades de éxito en el mercado. Recuerde, el trading es una habilidad que lleva tiempo y práctica dominar, por lo que es importante mantener el compromiso de aprender y mejorar sus habilidades de trading.


Mirando atrás en la historia

Examinemos el código que aparece a continuación para poder evaluar el rendimiento del indicador en datos históricos que abarcan al menos unos cuantos miles de barras. Examinemos el código que aparece a continuación para poder evaluar el rendimiento del indicador en datos históricos que abarcan al menos unos cuantos miles de barras. Mediante el análisis de los movimientos pasados de los precios, los operadores pueden determinar la dirección y la fuerza de la tendencia, alineando sus estrategias de negociación en consecuencia. Los patrones históricos de las velas pueden señalar los niveles clave de soporte y resistencia, donde los precios suelen hacer una pausa o retroceder. Estudiando cómo se han comportado los precios en estos niveles anteriormente, los operadores pueden anticipar futuros movimientos de los precios y establecer puntos de entrada y salida eficaces para sus operaciones.


Los operadores pueden utilizar los datos históricos de las velas para probar sus estrategias de negociación y medir su rendimiento en diferentes escenarios de mercado. Al probar las operaciones con datos históricos, los operadores pueden evaluar la eficacia de sus estrategias y realizar los ajustes necesarios para mejorar sus resultados comerciales. En esencia, profundizar en el historial de los gráficos de velas es un componente vital del análisis técnico, que ofrece a los operadores valiosas perspectivas sobre las tendencias, los patrones y los comportamientos del mercado que pueden guiarles a la hora de tomar decisiones de negociación informadas y rentables. 

Además de analizar los patrones históricos de las velas, los operadores también pueden utilizar indicadores técnicos para comprender mejor la dinámica del mercado. Estos indicadores pueden ayudar a identificar los posibles puntos de entrada y salida, así como proporcionar señales para las inversiones o continuaciones de tendencia. Al combinar la información de los gráficos de velas con las señales generadas por los indicadores, los operadores pueden desarrollar una estrategia de negociación más completa que tenga en cuenta tanto la acción de los precios como el análisis técnico. Este enfoque holístico puede mejorar la toma de decisiones y aumentar la probabilidad de éxito de las operaciones en los dinámicos y siempre cambiantes mercados financieros.

Examinemos esta pieza de que define hasta qué punto hacia atrás se visualizará nuestro indicador en el historial de gráficos de velas como parte de nuestro código principal.

#define PLOT_MAXIMUM_BARS_BACK 10000 //the integer value can be made higher expanding the gap you can visualize in history
#define OMIT_OLDEST_BARS 50


Identificar algunos problemas del sistema actual

En esta fase estamos examinando las señales proporcionadas en el gráfico por el Indicador de Restricción de Tendencia (Trend Constraint). Aunque la restricción filtró con éxito las señales negativas, seguimos teniendo problemas con las señales fuera de tendencia a una escala visual muy pequeña. Es importante eliminar estas señales y centrarse en las auténticas señales de tendencia. Esto pone de relieve la necesidad de utilizar herramientas integradas como la media móvil y el RSI a través de MQL5. En las secciones siguientes profundizaremos en estas herramientas.

Índice Boom500; Señales fuera de tendencia

Fig 1: Trend Constraint v1.00, Índice Boom 500

En las próximas secciones, exploraremos cómo la media móvil y el RSI pueden ayudar a mejorar nuestro análisis de tendencias y proporcionar señales más precisas para la toma de decisiones. Al incorporar estas herramientas a nuestro análisis, pretendemos mejorar la eficacia general de nuestra estrategia de negociación y obtener mejores resultados en el mercado. Profundicemos en las funcionalidades y ventajas de estas herramientas para optimizar nuestro enfoque de negociación.


Versionar nuestro próximo programa MQL5

Una vez iniciado nuestro viaje MQL5, cada etapa completada marca una versión. A medida que sigamos añadiendo funciones a nuestro programa, necesitaremos versionarlo a un nuevo nivel y, por tanto, actualizarlo. Veamos cómo lo hacemos al principio de nuestro código. A continuación presentamos nuestra primera versión de la Restricción de Tendencia (Trend Constraint) en código.

///Indicator Name: Trend Constraint
#property copyright "Clemence Benjamin"
#property link      "https://mql5.com"
#property version   "1.00"
#property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"

Para actualizar nuestra versión, sólo tenemos que cambiar los dígitos de la propiedad version en nuestro código. Por ejemplo, en este artículo, nuestra próxima versión de Trend Constraint será la 1.01. A continuación se muestra el fragmento de código actualizado que muestra cómo aparecerá en el código principal más adelante en el artículo.

///Indicator Name: Trend Constraint
#property copyright "Clemence Benjamin"
#property link      "https://mql5.com"
#property version   "1.01"
#property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"

¡Bien hecho! Así es como actualizamos nuestro programa MQL5. A continuación, avanzaremos a las versiones 1.02, 1.03, 1.04, etc.


Exploración de las medias móviles

Las medias móviles son cruciales para ilustrar las tendencias del mercado, y comprenden medias móviles lentas y rápidas. El cruce de estos dos puede indicar una continuación de la tendencia o un retroceso. En este artículo, he empleado una media móvil suavizada con un periodo de 7 en comparación con una media móvil simple bastante más lenta con un periodo de 400 para eliminar ciertas señales fuera de tendencia. Este enfoque permitió una representación más precisa de la tendencia subyacente del mercado, filtrando las fluctuaciones a corto plazo y el ruido. Mediante el uso de una combinación de medias móviles rápidas y lentas, pude identificar cambios de tendencia significativos al tiempo que minimizaba las señales falsas. Este método demostró ser eficaz para captar los movimientos más amplios del mercado y proporcionar información valiosa para tomar decisiones de negociación con conocimiento de causa.

La media móvil es una herramienta de análisis técnico muy utilizada que suaviza los datos de precios creando un precio medio actualizado constantemente. Ayuda a los operadores a identificar tendencias y posibles puntos de inversión. El concepto de media móvil se desarrolló para reducir el impacto de las fluctuaciones a corto plazo y resaltar las tendencias a más largo plazo en el movimiento de los precios.

 El uso de medias móviles en el análisis financiero se remonta a los primeros analistas técnicos como Richard Donchian y George Marechal a mediados del siglo XX.

La fórmula para calcular una media móvil simple (SMA) es sencilla:

SMA = (P1 + P2 ... + Pn)/n

Donde:

  • SMA = Media móvil simple.
  • P1,P2,...,Pn = Precio de los periodos especificados (por ejemplo, precios de cierre).
  • n = Número de periodos (por ejemplo, días) sobre los que calcular las medias.

Gráfico del EURUSD con medias móviles

Fig 2: Medias móviles, EURUSD

Incorporación de medias móviles al programa

La media móvil más lenta puede ser significativa para identificar cambios de tendencia. Esto es evidente en la forma en que el precio interactúa con las medias móviles lentas. Normalmente, el precio prueba la media móvil lenta varias veces antes de continuar o cambiar la tendencia. La media móvil lenta sigue de cerca el movimiento actual de los precios. De este modo, la media móvil lenta actúa como un sólido nivel de soporte o resistencia, reflejando la fortaleza de la tendencia subyacente. Los operadores suelen utilizar este indicador para confirmar los cambios o continuaciones de tendencia, ya que su naturaleza retardada proporciona un indicador fiable del sentimiento del mercado. Al observar la relación entre el precio y la media móvil lenta, los inversores pueden obtener información valiosa sobre la dinámica del mercado y tomar decisiones de negociación con conocimiento de causa.

Además, la capacidad de la media móvil lenta para suavizar las fluctuaciones de los precios puede ofrecer a los operadores una imagen más clara de la dirección general del mercado. Al centrarse en la convergencia o divergencia entre el precio y la media móvil lenta, los inversores pueden anticipar posibles cambios en el impulso. La fiabilidad de este indicador a la hora de captar las tendencias a largo plazo lo convierte en una herramienta valiosa para los operadores que buscan capear movimientos sustanciales de los precios al tiempo que filtran el ruido a corto plazo. Comprender los matices de la media móvil lenta puede mejorar la capacidad de un operador para navegar por las complejidades de los mercados financieros con mayor precisión y confianza.

En el artículo anterior, desarrollamos un indicador de restricción de tendencia D1 con 2 topes para compra y venta. Aunque en un principio nos pareció satisfactorio, nuestro objetivo ahora es mejorar aún más su eficacia. Al igual que en nuestro trabajo anterior, el código consta de 2 búferes. Nuestro objetivo es restringir la salida a medias móviles lentas para filtrar las señales falsas. Las medias móviles lentas desempeñan un papel importante en la determinación de las tendencias. La restricción dicta comprar exclusivamente cuando el precio es superior a la SMA 400 y vender exclusivamente cuando es inferior.

  1. Media móvil simple suavizada (SSMA) 7 para representar el precio.
  2. Media móvil simple 400 para representar el cumplimiento de la tendencia.
  3. Código MQL5 para la condición.
///Indicator Name: Trend Constraint
#property copyright "Clemence Benjamin"
#property link      "https://mql5.com"
#property version   "1.00"
#property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"

//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2

#property indicator_type1 DRAW_ARROW
#property indicator_width1 5
#property indicator_color1 0xD42A00
#property indicator_label1 "Buy"

#property indicator_type2 DRAW_ARROW
#property indicator_width2 5
#property indicator_color2 0x0000D4
#property indicator_label2 "Sell"

#define PLOT_MAXIMUM_BARS_BACK 5000
#define OMIT_OLDEST_BARS 50

//--- indicator buffers
double Buffer1[];
double Buffer2[];

double myPoint; //initialized in OnInit
int MA_handle;
double MA[];
int MA_handle2;
double MA2[];
double Open[];
double Close[];
int MA_handle3;
double MA3[];
int MA_handle4;
double MA4[];
double Low[];
double High[];

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | Trend Constraint @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
   SetIndexBuffer(0, Buffer1);
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
   PlotIndexSetInteger(0, PLOT_ARROW, 241);
   SetIndexBuffer(1, Buffer2);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
   PlotIndexSetInteger(1, PLOT_ARROW, 242);
   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
     }
   MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_EMA, PRICE_CLOSE);
   if(MA_handle < 0)
     {
      Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   MA_handle2 = iMA(NULL, PERIOD_CURRENT, 21, 0, MODE_EMA, PRICE_CLOSE);
   if(MA_handle2 < 0)
     {
      Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   MA_handle3 = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE);
   if(MA_handle3 < 0)
     {
      Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   MA_handle4 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE);
   if(MA_handle4 < 0)
     {
      Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
   int limit = rates_total - prev_calculated;
   //--- counting from 0 to rates_total
   ArraySetAsSeries(Buffer1, true);
   ArraySetAsSeries(Buffer2, true);
   //--- initial zero
   if(prev_calculated < 1)
     {
      ArrayInitialize(Buffer1, EMPTY_VALUE);
      ArrayInitialize(Buffer2, EMPTY_VALUE);
     }
   else
      limit++;
   
   datetime TimeShift[];
   if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total);
   ArraySetAsSeries(TimeShift, true);
   int barshift_M1[];
   ArrayResize(barshift_M1, rates_total);
   int barshift_D1[];
   ArrayResize(barshift_D1, rates_total);
   for(int i = 0; i < rates_total; i++)
     {
      barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]);
      barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]);
   }
   if(BarsCalculated(MA_handle) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
   ArraySetAsSeries(MA, true);
   if(BarsCalculated(MA_handle2) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total);
   ArraySetAsSeries(MA2, true);
   if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total);
   ArraySetAsSeries(Open, true);
   if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total);
   ArraySetAsSeries(Close, true);
   if(BarsCalculated(MA_handle3) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) <= 0) return(rates_total);
   ArraySetAsSeries(MA3, true);
   if(BarsCalculated(MA_handle4) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) <= 0) return(rates_total);
   ArraySetAsSeries(MA4, true);
   if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
   ArraySetAsSeries(Low, true);
   if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
   ArraySetAsSeries(High, true);
   //--- main loop
   for(int i = limit-1; i >= 0; i--)
     {
      if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
      
      if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue;
      if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue;
      
      //Indicator Buffer 1
      if(MA[i] > MA2[i]
      && MA[i+1] < MA2[i+1] //Moving Average crosses above Moving Average
      && Open[barshift_M1[i]] >= Close[1+barshift_D1[i]] //Candlestick Open >= Candlestick Close
      && MA3[i] > MA4[i] //Moving Average > Moving Average
      )
        {
         Buffer1[i] = Low[i]; //Set indicator value at Candlestick Low
        }
      else
        {
         Buffer1[i] = EMPTY_VALUE;
        }
      //Indicator Buffer 2
      if(MA[i] < MA2[i]
      && MA[i+1] > MA2[i+1] //Moving Average crosses below Moving Average
      && Open[barshift_M1[i]] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close
      && MA3[i] < MA4[i] //Moving Average < Moving Average
      )
        {
         Buffer2[i] = High[i]; //Set indicator value at Candlestick High
        }
      else
        {
         Buffer2[i] = EMPTY_VALUE;
        }
     }
   return(rates_total);
  }
//Thank you for following along this is ready to  compile


Exploración del oscilador RSI

El RSI ayuda a identificar las zonas extremas del mercado, incluidas las áreas de sobrecompra y sobreventa Esto puede ser útil para los operadores que buscan determinar posibles puntos de reversión u oportunidades de continuación de la tendencia. Al utilizar el RSI junto con otros indicadores técnicos y métodos de análisis, los operadores pueden tomar decisiones más informadas a la hora de entrar o salir de las operaciones. Además, el RSI también puede utilizarse para confirmar la fuerza de una tendencia o para detectar divergencias entre el precio y el impulso, que pueden indicar un posible cambio de dirección. Los operadores deben ser cautelosos a la hora de confiar únicamente en el RSI y siempre deben tener en cuenta otros factores como las condiciones del mercado, los acontecimientos noticiosos y el sentimiento general del mercado antes de tomar decisiones de negociación. Es importante recordar que ningún indicador es infalible por sí solo, y que a menudo es necesaria una combinación de herramientas y análisis para lograr estrategias de negociación exitosas.

La fórmula para el RSI que figura a continuación se atribuye a J. Welles Wilder Jr. que introdujo el concepto en 1978.

RSI = 100 - (100/(1+RS))

Donde:

  • RS = Ganancia media / Pérdida media.
  • Ganancia media = Suma de las ganancias durante el periodo especificado / Número de periodos.
  • Pérdida media = Suma de las pérdidas durante el periodo especificado / Número de periodos.

RSI del índice Boom 500

Fig 3: Niveles del RSI, Índice Boom 500

Implementación del RSI

Identificar los niveles del RSI en clave y alinearlos con las tendencias principales puede ser muy útil. En esta sección, incorporamos las condiciones RSI a nuestro programa de indicadores MQL5. La incorporación de las condiciones del RSI a nuestro programa de indicadores MQL5 nos permite analizar mejor las tendencias del mercado y tomar decisiones de trading más informadas. Al alinear los niveles del RSI con las tendencias principales, podemos identificar los posibles puntos de entrada y salida con mayor precisión, aumentando la eficacia de nuestra estrategia de negociación. Solíamos confiar en los cruces de medias móviles como condición de entrada. Ahora, estamos eliminando el cruce de MA y utilizando en su lugar los niveles de RSI para la entrada, junto con otras condiciones incorporadas recientemente para crear una nueva versión, Trend Constrain V1.02.

 En esta fase, necesitamos incorporar entradas para el valor del RSI con el fin de optimizar las zonas de sobrecompra y sobreventa. Compruebe el código a continuación.

input double Oversold = 30;
input double Overbought = 70;
//I have set the default standard values, but you can alter them to suit your strategy and instrument being traded.

Implementemos ahora estas condiciones RSI en nuestro código para mejorar la funcionalidad de nuestro indicador. Empecemos por definir los niveles del RSI que queremos utilizar en nuestro indicador. Podemos fijar el nivel de sobrecompra en 70 y el de sobreventa en 30. Esto nos ayudará a identificar posibles puntos de reversión en el mercado. A continuación, añadiremos la lógica necesaria a nuestro código para comprobar estas condiciones RSI y generar señales en consecuencia. Esto nos dará una visión más completa de la dinámica del mercado y nos ayudará a tomar decisiones de negociación más informadas. Procedamos a implementar estos cambios en nuestro programa indicador MQL5.

///Indicator Name: Trend Constraint
#property copyright "Clemence Benjamin"
#property link      "https://mql5.com"
#property version   "1.02"
#property description "A model that seek to produce sell signal when D1 candle is Bearish only and  buy signal when it is Bullish"

///--- indicator settings
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2

#property indicator_type1 DRAW_ARROW
#property indicator_width1 5
#property indicator_color1 0xFF3C00
#property indicator_label1 "Buy"

#property indicator_type2 DRAW_ARROW
#property indicator_width2 5
#property indicator_color2 0x0000FF
#property indicator_label2 "Sell"

#define PLOT_MAXIMUM_BARS_BACK 5000
#define OMIT_OLDEST_BARS 50

//--- indicator buffers
double Buffer1[];
double Buffer2[];

input double Oversold = 30;
input double Overbought = 70;
double myPoint; //initialized in OnInit
int RSI_handle;
double RSI[];
double Open[];
double Close[];
int MA_handle;
double MA[];
int MA_handle2;
double MA2[];
double Low[];
double High[];

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | Trend Constraint V1.02 @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
   SetIndexBuffer(0, Buffer1);
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
   PlotIndexSetInteger(0, PLOT_ARROW, 241);
   SetIndexBuffer(1, Buffer2);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1));
   PlotIndexSetInteger(1, PLOT_ARROW, 242);
   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
     }
   RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE);
   if(RSI_handle < 0)
     {
      Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE);
   if(MA_handle < 0)
     {
      Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE);
   if(MA_handle2 < 0)
     {
      Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
   int limit = rates_total - prev_calculated;
   //--- counting from 0 to rates_total
   ArraySetAsSeries(Buffer1, true);
   ArraySetAsSeries(Buffer2, true);
   //--- initial zero
   if(prev_calculated < 1)
     {
      ArrayInitialize(Buffer1, EMPTY_VALUE);
      ArrayInitialize(Buffer2, EMPTY_VALUE);
     }
   else
      limit++;
   
   datetime TimeShift[];
   if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total);
   ArraySetAsSeries(TimeShift, true);
   int barshift_M1[];
   ArrayResize(barshift_M1, rates_total);
   int barshift_D1[];
   ArrayResize(barshift_D1, rates_total);
   for(int i = 0; i < rates_total; i++)
     {
      barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]);
      barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]);
   }
   if(BarsCalculated(RSI_handle) <= 0) 
      return(0);
   if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) <= 0) return(rates_total);
   ArraySetAsSeries(RSI, true);
   if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total);
   ArraySetAsSeries(Open, true);
   if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total);
   ArraySetAsSeries(Close, true);
   if(BarsCalculated(MA_handle) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
   ArraySetAsSeries(MA, true);
   if(BarsCalculated(MA_handle2) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total);
   ArraySetAsSeries(MA2, true);
   if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
   ArraySetAsSeries(Low, true);
   if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
   ArraySetAsSeries(High, true);
   //--- main loop
   for(int i = limit-1; i >= 0; i--)
     {
      if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
      
      if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue;
      if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue;
      
      //Indicator Buffer 1
      if(RSI[i] < Oversold
      && RSI[i+1] > Oversold //Relative Strength Index crosses below fixed value
      && Open[barshift_M1[i]] >= Close[1+barshift_D1[i]] //Candlestick Open >= Candlestick Close
      && MA[i] > MA2[i] //Moving Average > Moving Average
      )
        {
         Buffer1[i] = Low[i]; //Set indicator value at Candlestick Low
        }
      else
        {
         Buffer1[i] = EMPTY_VALUE;
        }
      //Indicator Buffer 2
      if(RSI[i] > Overbought
      && RSI[i+1] < Overbought //Relative Strength Index crosses above fixed value
      && Open[barshift_M1[i]] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close
      && MA[i] < MA2[i] //Moving Average < Moving Average
      )
        {
         Buffer2[i] = High[i]; //Set indicator value at Candlestick High
        }
      else
        {
         Buffer2[i] = EMPTY_VALUE;
        }
     }
   return(rates_total);
  }
// Thank you for following along we are here


Comparación de resultados

Después de revisar el artículo anterior, hemos avanzado mucho en la creación de un gráfico claro con el número de señales presentadas. El RSI y las medias móviles han tenido un efecto positivo en nuestros resultados, sirviendo como indicadores visuales para controlar los cambios de tendencia. Nuestro indicador de restricción de tendencia de velas de marco temporal superior también ha mostrado mejoras. Además, la incorporación del indicador SMA 400 ha proporcionado más información sobre los posibles retrocesos del mercado, mejorando la precisión general de nuestros análisis. Al combinar estas diversas señales, estamos mejor equipados para tomar decisiones de negociación informadas y adaptarnos a la evolución de las condiciones del mercado. Estoy entusiasmado con los progresos que hemos realizado y mantengo mi compromiso de perfeccionar esta estrategia para obtener aún mejores resultados en el futuro.

Índice Boom 500, Smart Chart

Fig 4: Trend Constraint v1.02, Índice Boom 500

La imagen de arriba puede servir de referencia al principio del artículo, cuando tratábamos de identificar algunos problemas del sistema actual.

Índice Boom 500, Trend Constraint V1.02

Fig 5: Trend Constraint v1.02, Índice Boom 500


Conclusión

El indicador de tendencia de velas no puede sustituir a las medias móviles, pero puede complementarlas para obtener excelentes resultados. Los indicadores incorporados en MT5 sirven de base para crear otros indicadores personalizados. Cuando se utilizan conjuntamente, estas herramientas pueden ser muy eficaces. Hemos avanzado hacia una nueva etapa en este desarrollo y estamos empezando a enfrentarnos a problemas con los pesos y a retos de actualización que requieren atención. Nuestro próximo artículo se centrará en abordar estos retos mientras seguimos perfeccionando este sistema.

Consulte la Guía de algotrading.


Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/14803

Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Algoritmos de optimización de la población: Algoritmo de optimización de ballenas (Whale Optimization Algorithm, WOA) Algoritmos de optimización de la población: Algoritmo de optimización de ballenas (Whale Optimization Algorithm, WOA)
El algoritmo de optimización de ballenas (WOA) es un algoritmo metaheurístico inspirado en el comportamiento y las estrategias de caza de las ballenas jorobadas. La idea básica del WOA es imitar el método de alimentación denominado "red de burbujas", en el que las ballenas crean burbujas alrededor de la presa para atacarla después en espiral.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Aprendizaje automático y Data Science (Parte 22): Aprovechar las redes neuronales de autocodificadores para realizar operaciones más inteligentes pasando del ruido a la señal Aprendizaje automático y Data Science (Parte 22): Aprovechar las redes neuronales de autocodificadores para realizar operaciones más inteligentes pasando del ruido a la señal
En el vertiginoso mundo de los mercados financieros, separar las señales significativas del ruido es crucial para operar con éxito. Al emplear sofisticadas arquitecturas de redes neuronales, los autocodificadores destacan a la hora de descubrir patrones ocultos en los datos de mercado, transformando datos ruidosos en información práctica. En este artículo, exploramos cómo los autocodificadores están revolucionando las prácticas de negociación, ofreciendo a los operadores una poderosa herramienta para mejorar la toma de decisiones y obtener una ventaja competitiva en los dinámicos mercados actuales.