English Русский 中文 Deutsch 日本語 Português
preview
Desarrollamos un indicador Heiken Ashi personalizado utilizando MQL5

Desarrollamos un indicador Heiken Ashi personalizado utilizando MQL5

MetaTrader 5Trading | 6 octubre 2023, 10:05
496 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Introducción

Todos necesitamos interpretar gráficos. Las herramientas que ayudarnos en esta tarea incluyen indicadores calculados según los precios, el volumen, otro indicador técnico o una combinación de estos. Tenemos muchos indicadores listos para usar integrados en el terminal comercial, pero si necesitamos añadir algunas funciones que se adapten a nuestro estilo comercial, tendremos que recurrir a soluciones personalizadas.

En este artículo, usaremos la función iCustom y crearemos un indicador personalizado según nuestras condiciones y preferencias. También crearemos un indicador técnico Heiken Ashi personalizado y lo usaremos en sistemas comerciales. Así, hoy abarcaremos los siguientes temas:

El material del artículo se puede utilizar como muestra para crear indicadores personalizados propios. Usaremos el lenguaje MQL5 (MetaQuotes Language) integrado en la plataforma comercial MetaTrader 5 para escribir los códigos para los indicadores y asesores creados. Si no sabe cómo descargarlos y utilizarlos, lea la sección "Escribiendo el código MQL5 en el MetaEditor" de artículos anteriores.

¡Atención! Toda la información del presente artículo se ofrece «tal cual», únicamente con fines ilustrativos, y no supone ningún tipo de recomendación. El artículo no garantiza ningún resultado en absoluto. Todo lo que ponga en práctica usando este artículo como base, lo hará bajo su propia cuenta y riesgo; el autor no garantiza resultado alguno.

Indicador personalizado y definición de Heiken Ashi

Como mencioné en la introducción de la sección anterior, un indicador personalizado es una herramienta de análisis técnico que puede crear el usuario usando el lenguaje de programación MQL5. Puede utilizarse en MetaTrader 5 para analizar y comprender los movimientos del mercado y ayudar a tomar decisiones de inversión informadas. Existen muchos indicadores técnicos incorporados de gran utilidad, pero a veces necesitamos analizar y comprender cómo se está desempeñando el mercado según algunas ideas matemáticas, estadísticas o técnicas adicionales cuyos principios no están cubiertos por los indicadores existentes. En estos casos, deberemos crear dicho indicador nosotros mismos, y esta es una de las características más destacadas de la plataforma MetaTrader 5: su capacidad para ayudar al usuario a crear herramientas analíticas o comerciales propias que se adapten a sus preferencias y objetivos específicos.

Veamos los pasos necesarios para crear nuestro propio indicador:

Abra el MetaEditor y seleccione la carpeta Indicators en el Navegador.

Carpeta Indicators

Clique en el botón "Crear" para crear un nuevo programa como se muestra en la siguiente imagen

Botón New

Después de esto, se abrirá una ventana en la que deberá seleccionar el tipo de programa a crear. Seleccione "Indicador personalizado"

Seleccionar el tipo de programa

Después de clicar en el botón "Siguiente", se abrirá la siguiente ventana con información sobre el indicador. Introduzca el nombre del indicador personalizado aquí y clique en Siguiente.

Información sobre el indicador

En las siguientes ventanas ofrecemos información más detallada sobre el indicador.

Información sobre el indicador 2

Información sobre el indicador 3

Tras completar todas las configuraciones y clicar en el botón "Finalizar", se abrirá la ventana del editor.

Veremos cómo desarrollar un indicador propio usando Heiken Ashi como ejemplo. Como es lógico, primero necesitaremos aprender más sobre él. Heiken Ashi supone una técnica de gráficos de velas que se puede utilizar para representar y analizar los movimientos del mercado, y puede usarse en combinación con otras herramientas para proporcionar información detallada sobre la que tomar decisiones comerciales informadas.

Los gráficos Heiken Ashi son similares a los gráficos de velas normales, pero los métodos para calcular las velas son distintos. Como ya sabemos, un gráfico de velas normal calcula los precios basándose en una serie de precios reales (apertura, máximo, mínimo y cierre) de un periodo determinado, pero Heiken Ashi tiene en cuenta los precios similares anteriores (apertura, máximo, mínimo y cierre) al calcular sus velas.

Así es como se calculan los valores de Heiken Ashi:

  • Open = (apertura de la vela anterior + cierre de la vela anterior) / 2
  • Close = (apertura + cierre + máximo + mínimo de la vela actual) / 4
  • High = valor más alto desde el máximo, apertura o cierre del periodo actual
  • Low = valor más bajo desde el mínimo, apertura o cierre del periodo actual

Según el cálculo, el indicador construye velas alcistas y bajistas. Los colores de estas velas indicarán la dirección correspondiente del mercado: alcista o bajista. A modo de comparación, a continuación le mostramos las velas japonesas tradicionales y el Heiken Ashi.

 Heiken Ashi

La sección superior muestra las velas tradicionales, mientras que la sección inferior muestra el indicador Heiken Ashi, representado como velas azules y rojas que determinan la dirección del mercado. El objetivo del indicador consiste en filtrar y eliminar parte del ruido en los movimientos del mercado suavizando los datos para evitar señales falsas.


Indicador Heiken Ashi simple

Vamos a crear un indicador Heiken Ashi simple para usarlo en MetaTrader 5. El indicador debe verificar constantemente los precios (apertura, máximo, mínimo y cierre) y realizar cálculos para generar los valores haOpen, haHigh, haLow y haClose. Según los cálculos, el indicador debería mostrar los valores en el gráfico como velas de diferentes colores: azul para el movimiento alcista y rojo para el movimiento bajista. Las velas deberán mostrarse en una ventana aparte debajo del gráfico tradicional en forma de subventana.

Veamos todos los pasos que deberemos seguir para crear este indicador personalizado.

Primero definiremos la configuración del indicador especificando los parámetros adicionales a través de los valores #property y el identificador:

  • (indicator_separate_window) - muestra el indicador en una ventana separada.
  • (indicator_buffers) - número de búferes de cálculo del indicador.
  • (indicator_plots) - número de series gráficas en el indicador. Las series gráficas son los estilos de dibujo que se pueden utilizar al crear un indicador personalizado.
  • (indicator_typeN) - tipo de construcción gráfica según los valores (ENUM_DRAW_TYPE). N - número de series gráficas que definimos en el último parámetro. Comienza a partir de 1.
  • (indicator_colorN) - color de N. N es también el número de series gráficas que hemos definido anteriormente. Comienza a partir de 1.
  • (indicator_widthN) - grosor de N o la serie gráfica.
  • (indicator_labelN) - establece la etiqueta N de una serie gráfica específica.
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue, clrRed
#property indicator_width1  2
#property indicator_label1  "Heiken Ashi Open;Heiken Ashi High;Heiken Ashi Low;Heiken Ashi Close"

Luego crearemos cinco arrays para cinco búferes del indicador (haOpen, haHigh, haLow, haClose, haColor) de tipo double.

double haOpen[];
double haHigh[];
double haLow[];
double haClose[];
double haColor[];

Dentro de OnInit() esta función se utilizará para inicializar un indicador en ejecución.

int OnInit()

A continuación clasificaremos los búferes del indicador usando un array dinámico unidimensional de tipo double usando la función (SetIndexBuffer). Los parámetros serán los siguientes:

  • index - número del búfer de indicador, comenzando desde 0. El número deberá ser menor que el valor declarado en el parámetro (indicator_buffers).
  • buffer[] - array declarado en el indicador personalizado.
  • data_type - tipo de datos que necesitamos almacenar en el array de indicadores.
   SetIndexBuffer(0,haOpen,INDICATOR_DATA);
   SetIndexBuffer(1,haHigh,INDICATOR_DATA);
   SetIndexBuffer(2,haLow,INDICATOR_DATA);
   SetIndexBuffer(3,haClose,INDICATOR_DATA);
   SetIndexBuffer(4,haColor,INDICATOR_COLOR_INDEX);

Luego estableceremos el valor de la propiedad del indicador correspondiente usando la función (IndicatorSetInteger) con una variante de llamada en la que especificaremos el identificador de la propiedad. Los parámetros serán los siguientes:

  • prop_id - identificador de propiedad, que puede ser uno de (ENUM_CUSTOMIND_PROPERTY_INTEGER). Indicaremos (INDICATOR_DIGITS).
  • prop_value - valor de la propiedad. Indicaremos (_Digits).
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);

A continuación, estableceremos el valor de propiedad correspondiente de tipo string con la opción de llamada en la que también especificaremos el identificador de la propiedad. Los parámetros serán los siguientes:

  • prop_id - identificador de propiedad, que puede ser uno de (ENUM_CUSTOMIND_PROPERTY_STRING). Especificaremos (INDICATOR_SHORTNAME) para usar un nombre corto para el indicador.
  • prop_value - valor de la propiedad. Indicaremos ("Simple Heiken Ashi").
   IndicatorSetString(INDICATOR_SHORTNAME,"Simple Heiken Ashi");

Luego estableceremos el valor de la propiedad double correspondiente del indicador necesario usando la función (PlotIndexSetDouble). Los parámetros serán los siguientes:

  • plot_index - índice de construcción gráfica. Indicaremos 0.
  • prop_id - uno de los valores (ENUM_PLOT_PROPERTY_DOUBLE). (PLOT_EMPTY_VALUE) - sin representación.
  • prop_value - valor de la propiedad.
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);

Luego retornaremos (INIT_SUCCEEDED) como parte de la función OnInit() para finalizarla retornando la inicialización exitosa.

   return(INIT_SUCCEEDED);

Dentro de la función OnCalculate, que se llama en el indicador para procesar los datos de precio, el tipo de cálculo cambiará según la serie temporal del periodo actual.

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[])

Ahora crearemos la variable entera start. Le asignaremos el valor más adelante:

int start;

Después usaremos una declaración if para retornar los valores del índice (bajo, alto, abierto y cerrado) y start=1 si prev_calculated es 0, o retornar el valor inicial asignado a (prev_calculated-1):

   if(prev_calculated==0)
     {
      haLow[0]=low[0];
      haHigh[0]=high[0];
      haOpen[0]=open[0];
      haClose[0]=close[0];
      start=1;
     }
   else
      start=prev_calculated-1;

La función for se usa en el ciclo de cálculo principal. La declaración for consta de tres expresiones y declaraciones ejecutables.

Tres expresiones:

  • i=start - posición inicial.
  • i<rates_total && !IsStopped() - condiciones para finalizar el ciclo. IsStopped() comprueba la parada forzosa del indicador.
  • i++ - añadir 1 para obtener una nueva i.

Las operaciones que deberemos realizar cada vez durante el ciclo son:

Cálculo para las cuatro variables de tipo double.

  • haOpenVal - valor de apertura de Heiken Ashi.
  • haCloseVal - valor de cierre de Heiken Ashi.
  • haHighVal - máximo de Heiken Ashi.
  • haLowVal - mínimo de Heiken Ashi.

La asignación de los valores calculados en el paso anterior será similar a la siguiente:

  • haLow[i]=haLowVal
  • haHigh[i]=haHighVal
  • haOpen[i]=haOpenVal
  • haClose[i]=haCloseVal

Ahora comprobaremos si el valor de apertura de Heiken Ashi es inferior al valor de cierre. En caso afirmativo, el indicador debería dibujar una vela azul y, en caso contrario, una roja.

   for(int i=start; i<rates_total && !IsStopped(); i++)
     {
      double haOpenVal =(haOpen[i-1]+haClose[i-1])/2;
      double haCloseVal=(open[i]+high[i]+low[i]+close[i])/4;
      double haHighVal =MathMax(high[i],MathMax(haOpenVal,haCloseVal));
      double haLowVal  =MathMin(low[i],MathMin(haOpenVal,haCloseVal));

      haLow[i]=haLowVal;
      haHigh[i]=haHighVal;
      haOpen[i]=haOpenVal;
      haClose[i]=haCloseVal;

      //--- set candle color
      if(haOpenVal<haCloseVal)
         haColor[i]=0.0;
      else
         haColor[i]=1.0;
     }

Luego finalizaremos la función retornando (rates_total) como prev_calculated para la siguiente llamada,

return(rates_total);

y compilaremos el código para asegurarnos de que no haya errores. El código completo tendrá el aspecto que sigue:

//+------------------------------------------------------------------+
//|                                             simpleHeikenAshi.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue, clrRed
#property indicator_width1  2
#property indicator_label1  "Heiken Ashi Open;Heiken Ashi High;Heiken Ashi Low;Heiken Ashi Close"
double haOpen[];
double haHigh[];
double haLow[];
double haClose[];
double haColor[];
int OnInit()
  {
   SetIndexBuffer(0,haOpen,INDICATOR_DATA);
   SetIndexBuffer(1,haHigh,INDICATOR_DATA);
   SetIndexBuffer(2,haLow,INDICATOR_DATA);
   SetIndexBuffer(3,haClose,INDICATOR_DATA);
   SetIndexBuffer(4,haColor,INDICATOR_COLOR_INDEX);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
   IndicatorSetString(INDICATOR_SHORTNAME,"Simple Heiken Ashi");
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   return(INIT_SUCCEEDED);
  }
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 start;
   if(prev_calculated==0)
     {
      haLow[0]=low[0];
      haHigh[0]=high[0];
      haOpen[0]=open[0];
      haClose[0]=close[0];
      start=1;
     }
   else
      start=prev_calculated-1;
   for(int i=start; i<rates_total && !IsStopped(); i++)
     {
      double haOpenVal =(haOpen[i-1]+haClose[i-1])/2;
      double haCloseVal=(open[i]+high[i]+low[i]+close[i])/4;
      double haHighVal =MathMax(high[i],MathMax(haOpenVal,haCloseVal));
      double haLowVal  =MathMin(low[i],MathMin(haOpenVal,haCloseVal));

      haLow[i]=haLowVal;
      haHigh[i]=haHighVal;
      haOpen[i]=haOpenVal;
      haClose[i]=haCloseVal;
      if(haOpenVal<haCloseVal)
         haColor[i]=0.0;
      else
         haColor[i]=1.0;
     }
   return(rates_total);
  }

Después realizar la compilación con éxito, el indicador estará disponible en la carpeta "Indicadores" en la ventana "Navegador", como se muestra a continuación.

simpleHA nav

Vamos a iniciarlo. Se abrirá una ventana de configuración estándar:

 simpleHA win

La pestaña "Colores" mostrará la configuración por defecto: azul para movimiento ascendente, rojo para movimiento descendente. Los valores se pueden modificar.

 simpleHA win2

Después de clicar en OK, el indicador se adjuntará al gráfico y tendrá el aspecto siguiente:

iniciando simpleHA

Como podemos ver, el indicador funcionará en una subventana separada. Las velas azules y rojas indicarán la dirección del precio (alcista y bajista). Ahora tenemos nuestro propio indicador creado en MetaTrader 5, y podemos usarlo en cualquier sistema comercial. Esto es exactamente lo que haremos ahora.


Asesor experto basado en el indicador personalizado Heiken Ashi

En este apartado aprenderemos a utilizar los indicadores personalizados en un asesor experto. Para ello, crearemos un sistema Heiken Ashi simple que pueda mostrarnos los precios del indicador (apertura, máximo, mínimo y cierre) ya que sabemos que estos son diferentes de los precios reales calculados por el indicador.

Vamos a crear un asesor. Código completo:

//+------------------------------------------------------------------+
//|                                             heikenAshiSystem.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
int heikenAshi;
int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\Heiken Ashi\\simpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("Heiken Ashi System Removed");
  }
void OnTick()
  {
   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[];
   CopyBuffer(heikenAshi,0,0,1,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,1,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,1,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,1,heikenAshiClose);
   Comment("heikenAshiOpen ",DoubleToString(heikenAshiOpen[0],_Digits),
           "\n heikenAshiHigh ",DoubleToString(heikenAshiHigh[0],_Digits),
           "\n heikenAshiLow ",DoubleToString(heikenAshiLow[0],_Digits),
           "\n heikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
  }

Diferencias en este código:

Tipo de programa: asesor. El diseño del programa será diferente porque consta de tres partes, concretamente:

  • int OnInit() - ejecuta el inicio del asesor con el tipo recomendado que retorna un valor entero.
  • void OnDeinit - desinicializa el funcionamiento de un asesor que no retorna ningún valor.
  • void OnTick() - procesa una nueva cotización en cada tick, no retorna un valor.

Fuera de las funciones anteriores y antes de las mismas, crearemos una variable entera (heikenAshi)

int heikenAshi;

Dentro del ámbito de OnInit(), asignaremos el valor de la función iCustom a la variable heikenAshi. La función iCustom retornará el identificador del indicador personalizado, que aquí será Simple Heiken Ashi, pero puede usar cualquier indicador personalizado en la carpeta Indicadores. Parámetros:

  • symbol - nombre del símbolo, usaremos (_Symbol) para el símbolo actual.
  • period - periodo de tiempo, utilizaremos (_Period) para el periodo de tiempo actual.
  • name - nombre del indicador personalizado que indica la ruta al mismo en la carpeta "Indicadores". Aquí usaremos My Files\\Heiken Ashi\\simpleHeikenAshi.

Luego finalizaremos la función retornando (INIT_SUCCEEDED) para una inicialización exitosa.

int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\Heiken Ashi\\simpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }

Dentro de la función OnDeinit(), usaremos la función print para indicar que el asesor ha sido eliminado.

void OnDeinit(const int reason)
  {
   Print("Heiken Ashi System Removed");
  }

Dentro de la función OnTick(), hemos hecho lo siguiente para finalizar nuestro código:

Hemos creado cuatro variables de tipo doble para los precios de Heiken Ashi (Open, High, Low y Close).

   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[];

Luego hemos obtenido los datos de los búferes del indicador personalizado utilizando la función CopyBuffer. Parámetros:

  • Indicator_handle - manejador del indicador que hemos utilizado (heikenAshi).
  • buffer_num - número del búfer de indicador que hemos utilizado (0 para apertura, 1 para máximo, 2 para mínimo y 3 para cierre).
  • start_pos - primera posición del elemento a copiar, hemos usado 0 para el elemento actual.
  • count - volumen de datos para copiar, hemos usado 1. Eso será suficiente aquí.
  • buffer[] - array usado para copiar. Hemos utilizado (heikenAshiOpen para la apertura, heikenAshiHigh para el máximo, heikenAshiLow para el mínimo y heikenAshiClose para el cierre).

Luego hemos recibido un comentario en el gráfico con los precios actuales de Heiken Ashi (apertura, máximo, mínimo y cierre) utilizando la función de comentario:

   Comment("heikenAshiOpen ",DoubleToString(heikenAshiOpen[0],_Digits),
           "\n heikenAshiHigh ",DoubleToString(heikenAshiHigh[0],_Digits),
           "\n heikenAshiLow ",DoubleToString(heikenAshiLow[0],_Digits),
           "\n heikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));

Tras compilar y ejecutar este código sin errores, podemos encontrar el asesor adjunto al gráfico. Es posible obtener la misma señal en el siguiente ejemplo:

 haSystem

Como podemos ver, los precios de los indicadores se muestran como un comentario en la esquina superior izquierda del gráfico.


Heiken Ashi - Sistema EMA

En este apartado añadiremos otra herramienta técnica para ver si el resultado es mejor o no. La idea consiste en filtrar las señales de los indicadores personalizados utilizando una media móvil exponencial con precios. Existen muchas formas de hacer esto: podemos crear otro indicador personalizado para EMA si queremos añadir más funciones a esta. Luego podremos usarlo en el asesor como iCustom de la misma manera que lo hemos hecho para obtener las señales deseadas. También podemos crear un indicador suavizado, realizando para ello el suavizado de los valores del indicador y luego usando nuestras señales. Podemos usar la función iMA incorporada en nuestro asesor para obtener señales del mismo. Por su simplicidad, aquí usaremos este método.

Necesitamos permitir que el asesor verifique continuamente los valores de las dos EMA actuales (rápida y lenta), la EMA rápida anterior y el precio de cierre de Heiken Ash para determinar las posiciones de cada valor. Si el valor anterior de heikenAshiClose es mayor que el array fastEMA anterior, y el valor fastEMA actual es mayor que el valor actual de SlowEMA, el asesor debería retornar una señal de compra y estos valores deberían mostrarse en el gráfico. Si el anterior valor de heikenAshiClose está por debajo del array fastEMA anterior y el valor de fastEMA actual está por debajo del valor actual de SlowEMA, el asesor debería retornar una señal de venta y estos valores deberían mostrarse en el gráfico.

Aquí tenemos el código completo para crear un asesor:

//+------------------------------------------------------------------+
//|                                          heikenAsh-EMASystem.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
input int fastEMASmoothing=9; // Fast EMA Period
input int slowEMASmoothing=18; // Slow EMA Period
int heikenAshi;
double fastEMAarray[], slowEMAarray[];
int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\Heiken Ashi\\simpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("Heiken Ashi-EMA System Removed");
  }
void OnTick()
  {
   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[];
   CopyBuffer(heikenAshi,0,0,3,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,3,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,3,heikenAshiClose);
   int fastEMA = iMA(_Symbol,_Period,fastEMASmoothing,0,MODE_SMA,PRICE_CLOSE);
   int slowEMA = iMA(_Symbol,_Period,slowEMASmoothing,0,MODE_SMA,PRICE_CLOSE);
   ArraySetAsSeries(fastEMAarray,true);
   ArraySetAsSeries(slowEMAarray,true);
   CopyBuffer(fastEMA,0,0,3,fastEMAarray);
   CopyBuffer(slowEMA,0,0,3,slowEMAarray);
   if(heikenAshiClose[1]>fastEMAarray[1])
     {
      if(fastEMAarray[0]>slowEMAarray[0])
        {
         Comment("Buy Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nprevHeikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }
     }
   if(heikenAshiClose[1]<fastEMAarray[1])
     {
      if(fastEMAarray[0]<slowEMAarray[0])
        {
         Comment("Sell Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nheikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }
     }
  }

Qué ha cambiado en el código con respecto al anterior:

Crearemos datos de entrada personalizados para establecer el periodo de la EMA rápida y el periodo de la EMA lenta según las preferencias del usuario.

input int fastEMASmoothing=9; // Fast EMA Period
input int slowEMASmoothing=18; // Slow EMA Period

Luego crearemos dos arrays para fastEMA y slowEMA,

double fastEMAarray[], slowEMAarray[];

y estableceremos en 3 la cantidad de datos copiados en CopyBuffer para obtener los valores de cierre anteriores del indicador Heiken Ashi.

   CopyBuffer(heikenAshi,0,0,3,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,3,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,3,heikenAshiClose);

Determinaremos la EMA rápida y lenta usando la función iMA incorporada, que devuelve el identificador del indicador de media móvil. Parámetros:

  • symbol - nombre del símbolo, usaremos (_Symbol) para el símbolo actual.
  • period - tiempo que utilizamos (_Period) para la hora actual.
  • ma_period - period para suavizar el valor promedio que utilizamos (fastEMASmoothing y slowEMASmoothing).
  • ma_shift - cambio de indicador, usamos 0.
  • ma_method - tipo de media móvil, usamos MODE_SMA para una media móvil simple.
  • applied_price - tipo de precio requerido para los cálculos, usamos PRICE_CLOSE.
   int fastEMA = iMA(_Symbol,_Period,fastEMASmoothing,0,MODE_SMA,PRICE_CLOSE);
   int slowEMA = iMA(_Symbol,_Period,slowEMASmoothing,0,MODE_SMA,PRICE_CLOSE);

Utilizaremos la función ArraySetAsSeries para configurar el indicador AS_SERIES. Parámetros:

  • array[] - array que utilizamos (fastEMAarray y slowEMA).
  • flag - dirección de indexación del array, usamos true.
   ArraySetAsSeries(fastEMAarray,true);
   ArraySetAsSeries(slowEMAarray,true);

Luego obtendremos los datos del búfer del indicador EMA usando la función CopyBuffer.

   CopyBuffer(fastEMA,0,0,3,fastEMAarray);
   CopyBuffer(slowEMA,0,0,3,slowEMAarray);

Condiciones para retornar señales usando la declaración if:

En caso de una señal de compra

Si heikenAshiClose anterior > el array fastEMA anterior y el array fastEMA actual > el array slowEMA actual, el asesor debería retornar una señal de compra y los siguientes valores:

  • fastEMA
  • slowEMA
  • prevFastEMA
  • prevHeikenAshiClose
   if(heikenAshiClose[1]>fastEMAarray[1])
     {
      if(fastEMAarray[0]>slowEMAarray[0])
        {
         Comment("Buy Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nprevHeikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }

Con una señal de venta:

Si heikenAshiClose anterior < el array fastEMA anterior y el array fastEMA actual < el array slowEMA actual, el asesor debería retornar una señal de venta y los valores de precio:

  • fastEMA
  • slowEMA
  • prevFastEMA
  • prevHeikenAshiClose
   if(heikenAshiClose[1]<fastEMAarray[1])
     {
      if(fastEMAarray[0]<slowEMAarray[0])
        {
         Comment("Sell Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nheikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }
     }

Tras compilar el código y ejecutarlo, podremos obtener nuestras señales como se muestra en los siguientes ejemplos de prueba.

Si hay una señal de compra:

HA con 2EMA - señal de compra

Como podemos ver en el gráfico anterior, en la esquina superior izquierda tenemos como comentario la siguiente señal:

  • Señal de compra
  • fastEMA
  • prevFastEMA
  • prevHeikenAshiClose

Si hay una señal de venta:

HA con 2EMA - señal de venta

Como señal en el gráfico tenemos los valores siguientes:

  • Señal de venta
  • fastEMA
  • prevFastEMA
  • prevHeikenAshiClose

Conclusión

Si ha entendido todo lo que hemos comentado en este artículo, podrá crear su propio indicador Heiken Ashi o incluso añadir algunas características adicionales según sus preferencias. Esto hará más fácil leer los gráficos y tomar decisiones efectivas. Además, podrá utilizar el indicador creado en sus sistemas comerciales como parte de los asesores, ya que lo hemos mencionado y utilizado en dos sistemas comerciales como ejemplo.

  • Sistema Heiken Ashi
  • Sistema Heiken Ashi-EMA

Espero que este artículo le resulte útil y le ayude a alcanzar sus objetivos comerciales. También espero que intente aplicar lo aprendido en este artículo, ya que le será de gran ayuda para entrenar sus habilidades de programación, y la práctica supone un factor esencial en el aprendizaje. Tenga en cuenta que debe probar todo lo aprendido en este artículo u otros recursos antes de usar sus conocimientos en el comercio real. Este artículo tiene fines exclusivamente educativos, por lo que el lector deberá tener cuidado y mostrar prudencia.

En mi perfil podrá encontrar los enlaces a mis otros artículos. Espero que también los encuentre útiles.

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

Archivos adjuntos |
Desarrollamos el indicador True Strength Index personalizado utilizando MQL5 Desarrollamos el indicador True Strength Index personalizado utilizando MQL5
Les presento un nuevo artículo sobre la creación de indicadores personalizados. Esta vez trabajaremos con el True Strength Index (TSI) y crearemos un asesor basado en él.
Cómo detectar tendencias y patrones de gráficos usando MQL5 Cómo detectar tendencias y patrones de gráficos usando MQL5
El artículo presenta un método para detectar automáticamente patrones de acción del precio usando MQL5, tales como tendencias (ascendentes, descendentes, laterales) y patrones de gráficos (pico doble, valle doble).
Comprensión y uso eficaz del simulador de estrategias MQL5 Comprensión y uso eficaz del simulador de estrategias MQL5
Para los desarrolladores de MQL5 resulta imperativo dominar herramientas importantes y valiosas. Una de esas herramientas es el simulador de estrategias. El presente artículo es una guía práctica para utilizar el simulador de estrategias MQL5.
Previsión usando modelos ARIMA en MQL5 Previsión usando modelos ARIMA en MQL5
En este artículo, continuaremos el desarrollo de la clase CArima para construir modelos ARIMA añadiendo métodos de predicción intuitivos.