Introducción a MQL5 (Parte 13): Guía para principiantes sobre cómo crear indicadores personalizados (II)
Introducción
¡Bienvenidos de nuevo a nuestra serie MQL5! La parte 12 de esta serie exploró los fundamentos de la creación de indicadores personalizados en MQL5. Creamos un indicador de media móvil desde cero, implementando su lógica manualmente en lugar de depender de funciones integradas. A continuación, ampliamos estos conocimientos transformándolos en una media móvil en formato de velas, mostrando cómo manipular elementos gráficos dentro de un indicador.
Partiendo de esa base, este artículo presentará conceptos más interesantes sobre el desarrollo de indicadores. Como siempre, utilizaremos un enfoque basado en proyectos para asegurarnos de que comprendas los temas poniéndolos en práctica. La creación de un indicador Heikin Ashi y el cálculo de una media móvil utilizando sus datos serán los objetivos principales. Una vez creados estos indicadores, desarrollaremos un asesor experto que incorpore los indicadores Heikin Ashi y de medias móviles. Incluso aquellos que sean nuevos en MQL5 pueden seguirlo, ya que se trata de un artículo apto para principiantes. Para ayudarle a comprender no solo cómo funciona la implementación, sino también por qué es necesario cada paso, se explicará detalladamente cada línea de código.
Este artículo tratará sobre una estrategia que tiene fines exclusivamente educativos. No pretende ser una estrategia comercial que garantice el éxito ni un asesoramiento financiero. Antes de utilizar estrategias en operaciones reales, pruébalas siempre en un entorno sin riesgos.
Heikin Ashi (HA) y media móvil HA

En este artículo aprenderás:
- Cómo crear un indicador Heikin Ashi personalizado desde cero en MQL5.
- Utilizar los datos de las velas Heikin Ashi para calcular la media móvil Heikin Ashi.
- Uso de la función iCustom() para acceder a indicadores no integrados e integrar sus datos en estrategias de negociación.
- Definición de las condiciones de entrada utilizando Heikin Ashi y cruces de MA.
- Gestionar el riesgo de forma eficaz estableciendo niveles de stop-loss y take-profit de forma dinámica mediante cálculos basados en Heikin Ashi.
- Aplicar un mecanismo de stop dinámico utilizando patrones de velas Heikin Ashi para asegurar las ganancias a medida que se desarrollan las tendencias.
1. Indicador Heikin Ashi
1.1. Comprender el indicador Heikin Ashi
El indicador Heikin Ashi (HA) facilita la visualización de las tendencias. HA utiliza una técnica única para determinar nuevos valores basados en datos históricos promediados de precios, a diferencia de los gráficos de velas típicos, que muestran los precios exactos de apertura, máximo, mínimo y cierre de cada período. Esto ayuda a los operadores a ordenar la información y concentrarse en lo importante, al ofrecer una imagen más clara y comprensible de los movimientos del mercado.
Cada vela en un gráfico de velas típico muestra el movimiento del precio durante un período determinado. Mientras que una vela roja (bajista) significa lo contrario, una vela verde (alcista) muestra que el precio cerró más alto que cuando abrió. Las finas mechas situadas por encima y por debajo del cuerpo de la vela, que muestran los precios más altos y más bajos alcanzados durante ese tiempo, proporcionan a los operadores una visión general de la volatilidad del mercado.
Pero las velas Heikin Ashi funcionan de manera diferente. Utilizan un cálculo especial para suavizar las tendencias en lugar de informar con precisión sobre los movimientos de los precios. Las velas verdes más largas con menos mechas son indicativas de una tendencia alcista, lo que facilita la identificación y el seguimiento del impulso alcista. Del mismo modo, las velas rojas se vuelven más visibles durante una tendencia bajista, lo que indica claramente oscilaciones negativas. Las velas más pequeñas con mechas en ambos extremos suelen aparecer cuando el mercado se encuentra en un rango o carece de un impulso significativo, lo que indica la vacilación o indecisión de los operadores.
El indicador HA es único, ya que modifica los cálculos convencionales de las velas japonesas mediante el uso de una técnica de promediado. Produce nuevos valores que ofrecen una representación más suave y consistente del movimiento de los precios, en lugar de trazar directamente los precios de apertura, máximo, mínimo y cierre del mercado. Al eliminar el «ruido» de las pequeñas fluctuaciones de precios, los operadores pueden detectar mejor las tendencias y tomar decisiones más acertadas.
Cierre Heikin Ashi
El promedio de los valores de apertura, máximo, mínimo y cierre del período actual se utiliza para determinar el precio de cierre de Heikin Ashi. Las velas japonesas estándar, que simplemente utilizan el precio de cierre, ofrecen una perspectiva más equilibrada del cambio de precios.La fórmula es:

El Heikin Ashi Close suaviza las fluctuaciones de precios calculando la media de estos cuatro valores, lo que hace que los patrones sean más evidentes a simple vista.
Apertura Heikin Ashi
Para determinar el precio de apertura de Heikin Ashi se utiliza la vela Heikin Ashi anterior, no la apertura real del mercado. Se determina promediando los valores anteriores de apertura y cierre de Heikin Ashi:

Heikin Ashi reduce los saltos impredecibles que se producen con frecuencia en los gráficos de velas convencionales, estableciendo un flujo continuo del movimiento de los precios mediante la vinculación del valor de apertura de cada nueva vela con el de la anterior.
Heikin Ashi Alto
El precio máximo de Heikin Ashi es el valor más alto alcanzado a lo largo del tiempo; sin embargo, tiene en cuenta tres valores: el máximo del período actual, la apertura de Heikin Ashi y el cierre de Heikin Ashi, en lugar de solo el máximo real del mercado. De estos tres, se selecciona el más alto:

Heikin Ashi Bajo
Del mismo modo, el precio mínimo de Heikin Ashi se calcula seleccionando el valor más bajo entre el cierre de Heikin Ashi, la apertura de Heikin Ashi y el mínimo real del periodo:

Este enfoque mantiene la coherencia con los métodos de suavizado, al tiempo que garantiza que el Heikin Ashi Low capta el punto más bajo de la fluctuación del precio. Heikin Ashi elimina las oscilaciones menores y ofrece una imagen más precisa de la dirección del mercado mediante el empleo de estos cálculos. Utilizaremos este razonamiento para construir nuestro propio indicador Heikin Ashi en MQL5 en la siguiente parte.
1.2. Ventajas de utilizar Heikin Ashi
Debido a que puede eliminar pequeñas fluctuaciones de precios, el indicador Heikin Ashi es uno de los favoritos entre los operadores y facilita mucho la identificación de tendencias. Debido a sus rápidos cambios de color, los gráficos tradicionales de velas japonesas pueden ser difíciles de interpretar y, con frecuencia, dejan a los operadores con la incertidumbre de si el mercado se dirige al alza o a la baja. Al emplear datos de precios promediados para suavizar el gráfico, Heikin Ashi aborda este problema y le ayuda a evitar perderse en los detalles.
Una serie de velas rojas indica una tendencia bajista, mientras que una serie de velas verdes suele indicar una fuerte tendencia alcista. Gracias a esta claridad, resulta más sencillo distinguir entre los cambios reales y duraderos del mercado y las caídas breves. Heikin Ashi le ayuda a reducir las señales falsas, evitando operaciones innecesarias causadas por fluctuaciones de precios a corto plazo. Al utilizar datos históricos, filtra el ruido del mercado y ofrece una confirmación más fiable de las tendencias. Muchos operadores lo combinan con herramientas como el RSI o las medias móviles para mejorar sus estrategias. Con su visión más clara de la evolución de los precios, Heikin Ashi facilita la decisión de cuándo entrar o salir de las operaciones.
1.3. Implementación de Heikin Ashi en MQL5
La implementación del indicador Heikin Ashi en MQL5 es el siguiente paso después de aprender sobre su funcionamiento. Crearemos nuestro propio indicador Heikin Ashi desde cero, ya que MetaTrader 5 no dispone de uno. Para ello, las fórmulas de Heikin Ashi deben codificarse, aplicarse a los datos de precios y mostrarse la indicación en el gráfico.
Como siempre, el desarrollo de un programa comienza con la redacción de un pseudocódigo que describe la lógica antes de empezar a escribir el código. Esto garantiza que comprendamos cada fase antes de poner en marcha el programa y nos ayuda a estructurarlo adecuadamente.
Pseudocódigo:
CONFIGURACIÓN DEL INDICADOR
- Configure el indicador para que se represente en una ventana de gráfico independiente.
- Configuración del gráfico para velas Heikin Ashi
- Defina 4 búferes para almacenar los valores de Heikin Ashi (apertura, máximo, mínimo y cierre).
Crear búferes para almacenar los valores calculados para:
- Apertura Heikin Ashi
- Heikin Ashi Alto
- Heikin Ashi Bajo
- Cierre Heikin Ashi
CALCULAR LOS VALORES DE HEIKIN ASHI
Recorra los datos históricos de precios para calcular los valores de Heikin Ashi utilizando las fórmulas:
- HA Close = (Open + High + Low + Close) / 4
- HA Open = (Previous HA Open + Previous HA Close) / 2
- HA High = Maximum of (High, HA Open, HA Close)
- HA Low = Minimum of (Low, HA Open, HA Close)
1.3.1. Creación y personalización de Heikin Ashi
Ahora debemos avanzar en la programación tras crear un pseudocódigo. Como se explicó en el último artículo, el primer paso para diseñar y modificar una indicación es imaginar cómo debería verse en el gráfico. El trazado del indicador, la visualización de las velas Heikin Ashi y la inclusión de cualquier otro componente, como colores para las tendencias alcistas y bajistas, deben decidirse antes de crear cualquier código.
Debemos asegurarnos de que nuestro indicador personalizado sustituya adecuadamente sus propios valores calculados por los gráficos de velas normales, ya que Heikin Ashi altera la apariencia de las velas. Esto implica establecer búferes para los precios de apertura, máximo, mínimo y cierre, así como asegurarse de que los colores cambien dinámicamente para mostrar tanto las tendencias bajistas como las alcistas. Podemos especificar la estructura del indicador y empezar a escribir el código tan pronto como tengamos esta visualización clara. Debemos definir la configuración de las propiedades del indicador Heikin Ashi antes de poder aplicar su lógica. Estos parámetros determinan el estilo de los elementos trazados (como las velas Heikin Ashi), el número de búferes que utilizará el indicador y cómo aparecerá la indicación en el gráfico.
Ejemplo:
// PROPERTY SETTINGS #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 // PLOT SETTINGS FOR HEIKIN ASHI CANDLES #property indicator_label1 "Heikin Ashi" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen, clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1
Explicación:
Configuración de propiedades#property indicator_separate_window
Esto indica a MetaTrader 5 que, en lugar de superponerse al gráfico principal, el indicador debe mostrarse en una ventana diferente. Esta línea se eliminaría si quisiéramos que apareciera directamente en el gráfico de precios.
Analogía
Considere su gráfico de operaciones como una estación de trabajo en la que examina los cambios en el mercado. Las herramientas esenciales, como las velas de precios y los indicadores convencionales, se colocan en el gráfico principal, que funciona de manera similar a una mesa. Ahora, imagínate trabajando en un proyecto paralelo meticuloso que necesita un área específica, como una pequeña pizarra blanca al lado de tu escritorio. Al trasladar esta actividad concreta a la pizarra, puedes concentrarte en ella de forma independiente, en lugar de saturar el espacio de trabajo principal.
En la misma línea, #property indicator_separate_window facilita el análisis de tendencias sin interferir con los datos estándar de las velas japonesas, ya que mueve el indicador Heikin Ashi a su propia ventana en lugar de superponerlo en el gráfico de precios principal.
#property indicator_buffers 5
Esto especifica cuántos búferes utilizará el indicador. En este caso se utilizan cinco búferes, uno para la representación del color y otro para almacenar los valores calculados de Heikin Ashi (apertura, máximo, mínimo y cierre).
Analogía
Ahora que tienes una pizarra diferente junto a tu banco de trabajo para tu proyecto paralelo, imagínate que necesitas cinco bandejas diferentes para llevar un control de tu trabajo. Los bocetos, las medidas, las notas, etc. se guardan en diferentes bandejas. Esto mantiene todo organizado para que puedas obtener rápidamente la información relevante cuando la necesites.
De forma similar a estas bandejas, #property indicator_buffers 5 garantiza que los distintos puntos de datos de Heikin Ashi se mantengan separados. Aquí tenemos cinco buffers: uno para la representación del color y cuatro para los valores Heikin Ashi (apertura, máximo, mínimo y cierre). Estos búferes mantienen estructurados los cálculos del indicador, lo que facilita la visualización de los datos correctos en el gráfico, de forma muy similar a como las bandejas mantienen ordenado tu espacio de trabajo.
#property indicator_plots 1
Esto indica cuántos gráficos mostrará el indicador. Solo necesitamos un gráfico porque estamos trazando velas Heikin Ashi como una sola unidad.
Analogía
Después de organizar tus materiales en bandejas diferenciadas y preparar tu espacio de trabajo con la pizarra blanca, el siguiente paso es elegir cómo mostrar tu trabajo. diagrama que unifica todos los datos en una única representación visual comprensible. En lugar de crear varios gráficos distintos, imagínese creando un único diagrama completo que unifique todos los datos en una única representación visual comprensible.
Del mismo modo, MetaTrader 5 recibe la información del indicador #property indicator_plots 1 de que el indicador Heikin Ashi se mostrará como un único elemento trazado. Al igual que en tu diagrama único en la pizarra, varios búferes contienen datos distintos (apertura, máximo, mínimo, cierre y color), pero todos ellos se combinan para crear un único conjunto de velas japonesas. Solo necesitamos un gráfico para mostrar las velas Heikin Ashi en el gráfico, ya que solo las estamos representando.
Configuración de gráficos
#property indicator_label1 "Heikin Ashi" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen, clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1
Analogía
Después de organizar tus materiales y preparar tu pizarra blanca, es importante transmitir tus conclusiones de forma clara y comprensible. Para que las tendencias sean más evidentes, optas por emplear símbolos codificados por colores en lugar de escribir texto sin formato o crear diseños abstractos. Identifica claramente lo que simboliza su diagrama etiquetándolo como «Heikin Ashi» para cualquiera que observe la pizarra. Del mismo modo, #property indicator_label1 «Heikin Ashi» le da un nombre al indicador y garantiza que aparezca en la lista de indicadores de MetaTrader 5. De esta manera, los operadores pueden identificarlo rápidamente en sus gráficos entre otros indicadores.
#property indicator_type1 DRAW_COLOR_CANDLES indica a MetaTrader 5 que utilice velas codificadas por colores en lugar de líneas o histogramas. Los colores se definen mediante #property indicator_color1 clrGreen, clrRed, donde el verde representa las velas alcistas y el rojo representa las velas bajistas. Esta claridad visual facilita la identificación de tendencias de un solo vistazo. Para mantener la pizarra ordenada y legible, decides utilizar un trazo de rotulador continuo en lugar de líneas discontinuas o punteadas.
Del mismo modo, #property indicator_style1 STYLE_SOLID garantiza que las velas Heikin Ashi se rellenen con un color sólido, lo que las hace visualmente distintas. Por último, al igual que evitas que tus líneas sean demasiado gruesas para que no saturen tu diagrama, #property indicator_width1 1 mantiene los contornos de las velas con un ancho razonable para mayor claridad sin saturar el gráfico. Al configurar el indicador Heikin Ashi de esta manera, creamos una representación clara, estructurada y visualmente intuitiva de las tendencias del mercado, tal y como has hecho con tu espacio de trabajo bien organizado en la pizarra.
Ahora que hemos configurado las propiedades del indicador y los ajustes del gráfico, el siguiente paso es definir los búferes que almacenarán los precios de las velas Heikin Ashi. Los búferes actúan como contenedores de almacenamiento para los valores calculados del indicador, lo que permite a MetaTrader 5 mostrarlos en el gráfico. En este caso, necesitamos búferes para almacenar los precios de apertura, máximo, mínimo y cierre de Heikin Ashi, así como un búfer adicional para la representación del color. También estableceremos sus respectivos índices de búfer para garantizar que cada búfer se corresponda correctamente con los datos previstos.
Ejemplo:
// PROPERTY SETTINGS #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 // PLOT SETTINGS FOR HEIKIN ASHI CANDLES #property indicator_label1 "Heikin Ashi" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen, clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 // INDICATOR BUFFERS double HA_Open[]; double HA_High[]; double HA_Low[]; double HA_Close[]; double ColorBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { // SET BUFFERS SetIndexBuffer(0, HA_Open, INDICATOR_DATA); SetIndexBuffer(1, HA_High, INDICATOR_DATA); SetIndexBuffer(2, HA_Low, INDICATOR_DATA); SetIndexBuffer(3, HA_Close, INDICATOR_DATA); SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX); 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[]) { return(rates_total); }
Explicación:
Creamos matrices (búferes) que mantendrán los precios de apertura, máximo, mínimo y cierre de las velas modificadas para almacenar los valores calculados del indicador Heikin Ashi. También controlamos el color de cada vela utilizando un búfer diferente.
double HA_Open[]; double HA_High[]; double HA_Low[]; double HA_Close[]; double ColorBuffer[];
El búfer HA_Open[] contiene el precio de apertura Heikin Ashi de cada vela, mientras que HA_High[] contiene el precio más alto de la vela Heikin Ashi. Del mismo modo, el precio de cierre de la vela Heikin Ashi se mantiene en HA_Close[], mientras que el precio más bajo se registra en HA_Low[]. Además, se utiliza ColorBuffer[] para decidir el color de cada vela y distinguir entre velas alcistas (verdes) y bajistas (rojas). El gráfico puede guardar y mostrar las velas Heikin Ashi actualizadas gracias al funcionamiento conjunto de estos búferes.
SetIndexBuffer(0, HA_Open, INDICATOR_DATA); SetIndexBuffer(1, HA_High, INDICATOR_DATA); SetIndexBuffer(2, HA_Low, INDICATOR_DATA); SetIndexBuffer(3, HA_Close, INDICATOR_DATA); SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX);
La función SetIndexBuffer de MetaTrader 5 vincula determinados búferes a sus índices correspondientes, lo que garantiza que los datos de Heikin Ashi se gestionen y muestren con precisión. Según la estructura de velas japonesas de la plataforma, el precio de apertura siempre se asigna al índice 0, y los valores máximo, mínimo y de cierre se asignan a los índices 1, 2 y 3. Si no se realiza una indexación adecuada, MetaTrader 5 podría no identificar los datos como velas legítimas, lo que podría provocar la pérdida de elementos del gráfico o problemas de visualización.
SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX) especifica el color de cada vela, indicando movimientos alcistas (verde) o bajistas (rojo), para diferenciar visualmente las tendencias. La indicación Heikin Ashi garantiza una representación correcta de los precios y un estilo visual adecuado mediante la indexación adecuada de estos búferes, lo que permite a los operadores analizar rápidamente las tendencias y tomar decisiones bien informadas.
Ahora debemos realizar los cálculos que producen los valores de Heikin Ashi después de configurar las propiedades del indicador, definir los búferes y conectarlos a los índices adecuados.
Ejemplo:
// PROPERTY SETTINGS #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 // PLOT SETTINGS FOR HEIKIN ASHI CANDLES #property indicator_label1 "Heikin Ashi" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen, clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 // INDICATOR BUFFERS double HA_Open[]; double HA_High[]; double HA_Low[]; double HA_Close[]; double ColorBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { // SET BUFFERS SetIndexBuffer(0, HA_Open, INDICATOR_DATA); SetIndexBuffer(1, HA_High, INDICATOR_DATA); SetIndexBuffer(2, HA_Low, INDICATOR_DATA); SetIndexBuffer(3, HA_Close, INDICATOR_DATA); SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX); 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[]) { if(rates_total < 2) return 0; // ENSURE ENOUGH DATA for(int i = 1; i < rates_total; i++) // START FROM SECOND BAR { // HEIKIN ASHI CLOSE FORMULA HA_Close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0; // HEIKIN ASHI OPEN FORMULA HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0; // HEIKIN ASHI HIGH FORMULA HA_High[i] = MathMax(high[i], MathMax(HA_Open[i], HA_Close[i])); // HEIKIN ASHI LOW FORMULA HA_Low[i] = MathMin(low[i], MathMin(HA_Open[i], HA_Close[i])); // SET COLOR: GREEN FOR BULLISH, RED FOR BEARISH ColorBuffer[i] = (HA_Close[i] >= HA_Open[i]) ? 0 : 1; } return(rates_total); }
Dado que la primera barra no contiene datos anteriores, este método calcula los valores de Heikin Ashi a partir de la segunda barra. Para suavizar las fluctuaciones de precios, el precio de cierre es la media de los precios de apertura, máximo, mínimo y cierre de la barra actual. El precio de apertura garantiza transiciones fluidas al promediar la apertura y el cierre de Heikin Ashi de la barra anterior. El máximo/mínimo de la barra actual y la apertura/cierre de Heikin Ashi son las cifras más altas y más bajas a partir de las cuales se calculan los precios máximos y mínimos. Por último, las velas se colorean de rojo (bajista) en caso contrario, o de verde (alcista) si el cierre es inferior o igual a la apertura. Esto ayuda a los operadores a ver las tendencias al reducir el ruido del mercado.

2. Creación de una media móvil a partir de datos Heikin Ashi
Ahora que hemos generado con éxito las velas Heikin Ashi, el siguiente paso es crear una media móvil (MA) basada en los valores Heikin Ashi en lugar de los datos de precios estándar.
Pseudocódigo:
MODIFICAR LAS PROPIEDADES DEL INDICADOR
-
Ajuste el recuento del búfer de cinco a seis para dejar espacio para la media móvil Heikin Ashi.
-
Cambia el número de gráficos (plots) de 1 a 2 para que se puedan ver juntas las velas y la media móvil Heikin Ashi.
DEFINIR EL BÚFER PARA LA MEDIA MÓVIL DE HEIKIN ASHI
- Crear un búfer para almacenar los valores de la media móvil Heikin Ashi.
- Defina una variable de entrada para el período de la media móvil (por ejemplo, 20).
CONFIGURAR EL BÚFER PARA LA MEDIA MÓVIL DE HEIKIN ASHI
- Vincule el búfer a un índice para almacenar los valores MA calculados.
- Establezca el índice del gráfico para que comience en el período de la media móvil y así garantizar una visualización adecuada.
CALCULAR LA MEDIA MÓVIL DE HEIKIN ASHI
- Comience el bucle desde (period - 1) para garantizar que haya suficientes puntos de datos.
- Calcula la suma de los últimos «n» valores de cierre de Heikin Ashi.
- Divida la suma por el período y almacene el resultado en el búfer.
Ejemplo:
// PROPERTY SETTINGS #property indicator_separate_window #property indicator_buffers 6 #property indicator_plots 2 // PLOT SETTINGS FOR HEIKIN ASHI CANDLES #property indicator_label1 "Heikin Ashi" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen, clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //PROPERTIES OF THE Heikin MA #property indicator_label2 "Heikin MA" #property indicator_type2 DRAW_LINE #property indicator_style2 STYLE_DASH #property indicator_width2 1 #property indicator_color2 clrBrown // INDICATOR BUFFERS double HA_Open[]; double HA_High[]; double HA_Low[]; double HA_Close[]; double ColorBuffer[]; double Heikin_MA_Buffer[]; int input heikin_ma_period = 20; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { // SET BUFFERS SetIndexBuffer(0, HA_Open, INDICATOR_DATA); SetIndexBuffer(1, HA_High, INDICATOR_DATA); SetIndexBuffer(2, HA_Low, INDICATOR_DATA); SetIndexBuffer(3, HA_Close, INDICATOR_DATA); SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX); SetIndexBuffer(5, Heikin_MA_Buffer, INDICATOR_DATA); PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, heikin_ma_period); 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[]) { if (rates_total < 2) return 0; // ENSURE ENOUGH DATA for (int i = 1; i < rates_total; i++) // START FROM SECOND BAR { // HEIKIN ASHI CLOSE FORMULA HA_Close[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0; // HEIKIN ASHI OPEN FORMULA HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0; // HEIKIN ASHI HIGH FORMULA HA_High[i] = MathMax(high[i], MathMax(HA_Open[i], HA_Close[i])); // HEIKIN ASHI LOW FORMULA HA_Low[i] = MathMin(low[i], MathMin(HA_Open[i], HA_Close[i])); // SET COLOR: GREEN FOR BULLISH, RED FOR BEARISH ColorBuffer[i] = (HA_Close[i] >= HA_Open[i]) ? 0 : 1; } for(int i = heikin_ma_period - 1; i < rates_total; i++) { double sum = 0.0; for(int j = 0; j < heikin_ma_period; j++) { sum += HA_Close[i - j]; } Heikin_MA_Buffer[i] = sum / heikin_ma_period; } return rates_total; }
Explicación:
Primero debemos modificar la configuración del búfer y del gráfico para incorporar la media móvil Heikin Ashi (HA MA) al indicador. Al utilizar #property indicator_buffers 6, el recuento de búferes aumenta de 5 a 6, lo que garantiza que haya un búfer libre para almacenar los datos de la media móvil de Heikin. Las velas Heikin Ashi y el Heikin MA pueden verse en el gráfico utilizando #property indicator_plots 2 para cambiar el recuento de tramas de 1 a 2. Esto garantiza que el indicador pueda manejar eficazmente ambos conjuntos de datos.
A continuación, se configuran las propiedades del gráfico Heikin MA. #property indicator_label2 es la etiqueta. Al darle un nombre a la media móvil, «Heikin MA», esta destaca en la lista de indicadores. Para definir que la media móvil se muestre como una línea en lugar de velas japonesas, el tipo se establece utilizando #property indicator_type2 DRAW_LINE. Establecemos #property indicator_style2 STYLE_DASH para que la línea sea discontinua y utilizamos #property indicator_width2 1 para determinar su anchura y aumentar la visibilidad. Al utilizar #property indicator_color2 clrBrown, el color se establece en marrón, lo que garantiza un contraste espectacular con las velas Heikin Ashi.
Después de configurar las propiedades, definimos un parámetro de entrada "input int heikin_ma_period = 20;" que permite a los usuarios cambiar el período y declarar una matriz double Heikin_MA_Buffer[]; para almacenar los datos de la media móvil. SetIndexBuffer(5, Heikin_MA_Buffer, INDICATOR_DATA); se utiliza para vincular el búfer al indicador, lo que permite a MetaTrader 5 gestionar y mostrar los valores de forma adecuada. PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, heikin_ma_period); también garantiza que la media móvil solo se trace cuando haya suficientes barras disponibles.
El cálculo de la media móvil Heikin Ashi es el último paso. Para garantizar que disponemos de suficientes puntos de datos para el cálculo, el bucle comienza en heikin_ma_period -1. La media móvil se calcula dentro del bucle sumando los últimos n valores de cierre de Heikin Ashi y dividiendo el total por el período. A continuación, el indicador traza la media móvil junto con las velas Heikin Ashi después de almacenar el resultado en Heikin_MA_Buffer[i], lo que proporciona a los operadores una herramienta suavizada para seguir las tendencias.

3. Integración de un indicador personalizado en un asesor experto
Quizás se pregunte, ahora que hemos creado un indicador personalizado, cómo podemos utilizarlo para crear un asesor experto. Utilizando la indicación Heikin Ashi creada en el capítulo anterior, continuaremos con nuestro enfoque basado en proyectos en este capítulo y diseñaremos un EA. Nuestra técnica se materializará en un bot de trading operativo gracias al uso que hace este EA de las señales Heikin Ashi para automatizar las decisiones de trading.
Una estrategia cruzada sencilla basada en la media móvil Heikin Ashi (HA MA) y las velas Heikin Ashi (HA) será nuestra estrategia de trading. Esta técnica ayuda a identificar posibles reversiones de tendencia y señales de continuación al observar la relación entre el precio de cierre de la vela Heikin Ashi y la media móvil Heikin Ashi. Una tendencia alcista y una posible oportunidad de compra se indican cuando una vela Heikin Ashi cierra por encima de la media móvil Heikin Ashi. Por el contrario, una vela Heikin Ashi que cierre por debajo de la media móvil Heikin Ashi genera una señal de venta, lo que sugiere un cambio de tendencia bajista y una posible oportunidad de venta.

3.1. Recuperación de datos del indicador
Lo primero que debes tener en cuenta al integrar un indicador personalizado en un EA es cómo introducir los datos del indicador en tu EA. El EA no puede basar sus decisiones comerciales en el indicador si sus valores son inaccesibles. Por ejemplo, los cuatro valores que componen una vela Heikin Ashi deben importarse a nuestra estrategia de cruce de medias móviles Heikin Ashi:
- Precio de apertura HA (HA Open)
- Precio alto HA (HA High)
- Precio bajo HA (HA Low)
- Precio de cierre HA (HA Close)
Nuestras señales de trading se basan en estos parámetros, que se utilizarán para evaluar si una vela Heikin Ashi ha cruzado por encima o por debajo de la HA MA.
Ejemplo:
// Declare arrays to store Heikin Ashi data from the custom indicator double heikin_open[]; // Stores Heikin Ashi Open prices double heikin_close[]; // Stores Heikin Ashi Close prices double heikin_low[]; // Stores Heikin Ashi Low prices double heikin_high[]; // Stores Heikin Ashi High prices double heikin_ma[]; // Stores Heikin Ashi Moving Average values int heikin_handle; // Handle for the custom Heikin Ashi indicator //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Ensure arrays store data in a time series format (most recent data first) ArraySetAsSeries(heikin_open, true); ArraySetAsSeries(heikin_close, true); ArraySetAsSeries(heikin_low, true); ArraySetAsSeries(heikin_high, true); ArraySetAsSeries(heikin_ma, true); // Load the custom Heikin Ashi indicator and get its handle heikin_handle = iCustom(_Symbol, PERIOD_CURRENT, "Project7 Heikin Ashi Indicator.ex5"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Nothing to clean up in this case, but can be used for resource management if needed } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Copy the latest 3 values of each buffer from the Heikin Ashi indicator CopyBuffer(heikin_handle, 0, 0, 3, heikin_open); // Get HA Open values CopyBuffer(heikin_handle, 1, 0, 3, heikin_high); // Get HA High values CopyBuffer(heikin_handle, 2, 0, 3, heikin_low); // Get HA Low values CopyBuffer(heikin_handle, 3, 0, 3, heikin_close); // Get HA Close values CopyBuffer(heikin_handle, 5, 0, 3, heikin_ma); // Get HA Moving Average values // Print index 0 values to the terminal Print("HA Open: ", heikin_open[0], "\nHA High: ", heikin_high[0], "\nHA Low: ", heikin_low[0], "\nHA Close: ", heikin_close[0], "\nHA MA: ", heikin_ma[0]); }
Explicación:
Declaración de matrices para almacenar datos de Heikin Ashi
Declarar matrices para almacenar los datos recopilados del indicador es el primer paso para integrar un indicador personalizado en un asesor experto. En este caso se declaran cinco matrices para almacenar los distintos componentes del indicador Heikin Ashi:
- heikin_open[]: Almacena los precios de apertura de Heikin Ashi.
- heikin_close[]: Almacena los precios de cierre de Heikin Ashi.
- heikin_low[]: Almacena los precios bajos de Heikin Ashi.
- heikin_high[]: Almacena los precios altos de Heikin Ashi.
- heikin_ma[]: Almacena los valores de la media móvil Heikin Ashi.
Estas matrices son cruciales, ya que proporcionan al EA acceso a los valores Heikin Ashi tanto pasados como actuales. El EA puede evaluar los movimientos históricos de los precios y ajustar las decisiones de negociación almacenando estos datos. Estas matrices no necesitan inicializarse con valores fijos, ya que se rellenarán con datos del indicador personalizado; en su lugar, se actualizarán dinámicamente a medida que haya nuevos datos disponibles.
Declaración del identificador (handle) del indicador
El identificador del indicador Heikin Ashi personalizado se almacena en la variable heikin_handle. Un identificador en MQL5 es una referencia distinta a una instancia de indicador que se ejecuta en segundo plano. Este controlador es esencial, ya que permite al EA interactuar con el indicador y solicitar datos según sea necesario. El EA no tendría acceso a los valores de Heikin Ashi sin un identificador. Más tarde, cuando se ejecute la función iCustom(), se establecerá un valor para el identificador. El indicador no se ha cargado correctamente si el identificador no es válido (devuelve -1), lo que impide que el EA recupere los datos necesarios.
Inicialización de matrices en formato de series temporales
Las matrices deben construirse de manera que los datos más recientes estén siempre en el índice 0 cuando se declaran. Para ello se utiliza la función ArraySetAsSeries(), que ordena los componentes de la matriz en orden descendente, de modo que los datos más recientes se mantienen en primer lugar.
La función se aplica a cada una de las cinco matrices de la siguiente manera:
ArraySetAsSeries(heikin_open, true); ArraySetAsSeries(heikin_close, true); ArraySetAsSeries(heikin_low, true); ArraySetAsSeries(heikin_high, true); ArraySetAsSeries(heikin_ma, true);
Al convertir estas matrices a un formato de serie temporal, el índice 0 permite al EA acceder siempre a los datos más recientes de Heikin Ashi. A la hora de poner en práctica técnicas de trading, esto resulta especialmente útil, ya que garantiza que el EA responda a los movimientos actuales del mercado en lugar de a datos históricos.
Cargar el indicador personalizado Heikin Ashi con iCustom()
Al establecerlo, necesitamos un medio para acceder a los datos con el fin de incorporar un indicador personalizado en un asesor experto (EA). Podemos cargar un indicador personalizado y recibir un identificador que el EA puede utilizar para solicitar valores del indicador mediante la función iCustom(). El EA no podría acceder a los datos del indicador sin este identificador.
heikin_handle = iCustom(_Symbol, PERIOD_CURRENT, "Project7 Heikin Ashi Indicator.ex5");
- _Symbol: Indica a la función que aplique el indicador al símbolo de negociación actual (por ejemplo, EURUSD, GBPJPY, etc.). Esto garantiza que el indicador procese datos para el mismo activo en el que se ejecuta el EA.
- PERIOD_CURRENT: Esto aplica el indicador al mismo marco temporal que el EA. Si el EA se ejecuta en un gráfico H1, el indicador también se aplicará a H1.
- "Project7 Heikin Ashi Indicator.ex5": Esto especifica el nombre del archivo del indicador personalizado que debe utilizar el EA. La extensión .ex5 indica que se trata de un archivo de indicador MQL5 compilado.
Es esencial asegurarse de que el archivo indicador se guarde en el directorio MetaTrader 5 adecuado. El indicador debe estar en la carpeta Indicators del directorio MQL5. La ruta completa de este directorio es:
MQL5/Indicators/
En resumen, la función principal que conecta un indicador personalizado con un EA es iCustom(). Proporciona al EA una herramienta que permite la extracción dinámica de los valores de los indicadores. La función no funcionará correctamente a menos que el indicador se coloque adecuadamente en el directorio Indicators (o en una subcarpeta dentro de él).
Copiar datos del indicador en las matrices
Después de obtener el identificador, el EA puede recuperar los valores más recientes de Heikin Ashi del indicador utilizando la función CopyBuffer(). Los datos se copian en las matrices del EA desde los búferes internos de un indicador utilizando la función CopyBuffer(). Este EA llama al método cinco veces, una por cada dato:
CopyBuffer(heikin_handle, 0, 0, 3, heikin_open); // Get HA Open values CopyBuffer(heikin_handle, 1, 0, 3, heikin_high); // Get HA High values CopyBuffer(heikin_handle, 2, 0, 3, heikin_low); // Get HA Low values CopyBuffer(heikin_handle, 3, 0, 3, heikin_close); // Get HA Close values CopyBuffer(heikin_handle, 5, 0, 3, heikin_ma); // Get HA Moving Average values
Los datos se recuperan del indicador personalizado utilizando la misma estructura para cada llamada a CopyBuffer(). El identificador recuperado de la función iCustom() es el primer parámetro, heikin_handle. El EA puede acceder a los datos del indicador personalizado Heikin Ashi utilizando este identificador como referencia. El EA no podría solicitar valores de indicador sin este identificador. Los índices de búfer para los distintos componentes del indicador Heikin Ashi se representan mediante el siguiente conjunto de parámetros (0, 1, 2, 3, 5). En MQL5, los indicadores utilizan búferes para almacenar sus datos, y a cada búfer se le asigna un índice único. El precio de apertura de Heikin Ashi en este caso está representado por el búfer 0, el máximo por el búfer 1, el mínimo por el búfer 2, el cierre por el búfer 3 y la media móvil de Heikin Ashi por el búfer 5. Garantizamos que se obtienen los datos correctos del indicador al proporcionar estos índices.
Los datos deben duplicarse comenzando por la barra más reciente (vela actual), según la tercera opción, 0. Esto garantiza que el EA siempre utilice los datos de mercado más recientes, lo cual es necesario para tomar decisiones de trading en tiempo real. Se deben replicar tres puntos de datos, según el cuarto parámetro, 3. La recuperación de valores múltiples permite al EA examinar tanto los datos históricos como los actuales de Heikin Ashi, lo que resulta útil para descubrir patrones o validar tendencias.
Por último, las matrices asociadas —heikin_open, heikin_high, heikin_low, heikin_close y heikin_ma— se utilizan para almacenar los datos recuperados. Los valores recuperados se almacenan en estas matrices para que el EA pueda procesarlos y utilizarlos en su lógica de negociación. Para que el EA pueda tomar decisiones comerciales bien informadas basadas en las tendencias de los precios, es imprescindible que disponga de información actualizada sobre el indicador Heikin Ashi.
3.2. Utilización de datos de indicadores en nuestra estrategia comercial
Después de aprender a extraer datos del indicador personalizado, ahora debemos comprender cómo aplicar estos datos a nuestra estrategia de trading. Esto nos permitirá utilizar con éxito el indicador Heikin Ashi en un EA y mostrar cómo basar las decisiones de trading en los números que se obtienen. Además, este procedimiento ofrece la oportunidad de investigar ciertas ideas importantes de MQL5, lo que mejora nuestra comprensión a medida que avanzamos en este texto.
Sin embargo, no podemos aplicar simplemente el razonamiento sin tener en cuenta elementos cruciales de la EA. Una administración comercial adecuada requiere la incorporación de características específicas. Esto incluye controlar la cantidad de posiciones abiertas, establecer trailing stops, controlar los parámetros de riesgo y asegurarse de que el EA ejecute las operaciones de forma metódica. Al incluir estos elementos esenciales, creamos un sistema de negociación más fiable y útil que puede funcionar bien en un entorno real.
3.2.1. Seguimiento de posiciones abiertas de compra y venta en el asesor experto
Debemos asegurarnos de que solo haya una posición de compra y una de venta abiertas al mismo tiempo para que la técnica de negociación funcione correctamente. Esto reduce el riesgo innecesario derivado de muchas posiciones en la misma dirección y ayuda a mantener el control sobre la ejecución de las posiciones. El EA puede decidir si establecer una nueva posición o esperar a que se cierre una existente antes de ejecutar otra, supervisando el número de posiciones abiertas. Este método garantiza que la estrategia funcione según lo previsto y mejora la gestión de posiciones.
Ejemplo:
int totalPositions = 0; int position_type_buy = 0; int position_type_sell = 0; for(int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(ChartID()) { totalPositions++; if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { position_type_buy++; } if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { position_type_sell++; } } } }
El EA cuenta el número de operaciones de compra, venta y total para realizar un seguimiento de las posiciones abiertas. Recorre las posiciones abiertas, las clasifica como compra o venta y utiliza el número mágico y el símbolo del gráfico para confirmar que se ajustan a la estrategia. Al permitir solo una compra y una venta a la vez, se garantiza una gestión controlada de las posiciones.
3.2.2. Seguimiento de los límites diarios de operaciones en el asesor experto
El tema principal de esta sección es la suma de las operaciones realizadas durante una sesión bursátil determinada. El asesor experto se asegura de que la estrategia no supere el límite diario de operaciones permitido estableciendo un período de tiempo predeterminado y contabilizando las operaciones de compra y venta. Al evitar el exceso de operaciones durante el tiempo asignado, esta estrategia ayuda a mantener un comportamiento comercial controlado.
Ejemplo:
input int daily_trades = 6; // Total Daily Trades // Start and end time for string start = "00:00"; string end = "23:50"; //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { datetime start_time = StringToTime(start); datetime end_time = StringToTime(end); bool success = HistorySelect(start_time, end_time); // Getting total trades int totalDeal = 0; int deal_type_buy = 0; int deal_type_sell = 0; if(success) { for(int i = 0; i < HistoryDealsTotal(); i++) { ulong ticket = HistoryDealGetTicket(i); if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == MagicNumber && HistoryDealGetString(ticket,DEAL_SYMBOL) == ChartSymbol(chart_id)) { if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_IN) { totalDeal++; if(HistoryDealGetInteger(ticket, DEAL_TYPE) == DEAL_TYPE_BUY) { deal_type_buy++; } if(HistoryDealGetInteger(ticket, DEAL_TYPE) == DEAL_TYPE_SELL) { deal_type_sell++; } } } } } }
Explicación:
El asesor experto traduce inicialmente las horas de inicio y finalización especificadas al formato de fecha y hora para realizar un seguimiento del número total de operaciones realizadas durante una sesión de negociación determinada. A continuación, se utiliza la función HistorySelect() para seleccionar el historial de operaciones que se encuentra dentro de este intervalo de tiempo. El EA establece contadores para registrar el número total de operaciones realizadas y el número de operaciones de compra y venta de forma independiente si la selección tiene éxito.
A continuación, el EA extrae el número de ticket de cada operación iterando sobre el historial de operaciones. Para asegurarse de que solo se contabilizan las operaciones pertinentes, verifica si la operación se abrió utilizando el mismo número mágico y símbolo que el gráfico actual. El número total de operaciones aumenta si se determina que la operación es una operación de entrada. Después de decidir si se ha realizado la operación, el EA actualiza los contadores correspondientes. Esto garantiza que la estrategia supervise las transacciones que se ejecutan y evita que se supere el límite diario de operaciones.
3.2.3. Prevenir operaciones repetidas dentro de la misma vela japonesa
En algunos casos, el EA puede abrir una nueva operación inmediatamente después de cerrar una posición existente si desea que las nuevas operaciones se completen solo al precio de apertura de una nueva barra. Esto es especialmente cierto si las condiciones comerciales siguen siendo las mismas. Esto puede dar lugar a operaciones consecutivas no intencionadas dentro de la misma vela. En esta parte veremos formas de evitarlo, como asegurarnos de que las operaciones solo se ejecuten al precio de apertura de la barra siguiente, mejorar el control de las operaciones y evitar reentradas innecesarias.
Ejemplo:
// Declare an array to store time data datetime time[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Ensure the time array is structured as a time series (most recent data first) ArraySetAsSeries(time, true); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Retrieve the latest three time values from the current symbol and timeframe CopyTime(_Symbol, PERIOD_CURRENT, 0, 3, time); // Select trading history from the earliest recorded time to the current time bool trade_control = HistorySelect(time[0], TimeCurrent()); // Variable to count the number of closed trades int total_deals_out = 0; // If the trading history selection is successful, process the data if(trade_control) { // Loop through all closed trades in the history for(int i = 0; i < HistoryDealsTotal(); i++) { // Get the ticket number of the historical trade ulong ticket = HistoryDealGetTicket(i); // Check if the trade matches the current EA's Magic Number and symbol if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == MagicNumber && HistoryDealGetString(ticket, DEAL_SYMBOL) == ChartSymbol(chart_id)) { // If the trade was an exit trade, increment the counter if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT) { total_deals_out++; } } } } }
Explicación:
Esta función impide que el EA abra una operación dentro de la misma vela después de cerrar una. Utilizando CopyTime(), que proporciona las marcas de tiempo de las barras más recientes, el procedimiento primero recupera los valores de tiempo más recientes del gráfico. A continuación, desde el primer tiempo de barra registrado (time[0]) hasta el tiempo de mercado actual (TimeCurrent()), el EA elige el historial de operaciones dentro del marco temporal.
Para encontrar operaciones cerradas que coincidan con el número mágico y el símbolo del EA, se repite el proceso a través del historial de operaciones. El contador total_deals_out aumenta si se encuentra una operación cerrada, más concretamente, una operación de salida (DEAL_ENTRY_OUT). Si recientemente se ha cerrado una operación dentro de la misma vela, este contador puede ayudarte a averiguarlo. Para garantizar que las operaciones solo se ejecuten al inicio de una nueva barra y evitar reentradas inmediatas no deseadas, el EA se abstendrá de iniciar una nueva operación hasta que comience una nueva vela.
3.2.4. Implementación de la gestión de riesgos y la ejecución de operaciones con Heikin Ashi
Para garantizar que las operaciones de compra y venta se ejecuten de acuerdo con las señales de Heikin Ashi, especificaremos los requisitos para la ejecución de operaciones en esta sección. Además, al determinar los tamaños de los lotes según un riesgo predeterminado en dólares por operación y una relación riesgo-recompensa (RRR), integraremos la gestión de riesgos. Esta estrategia evita una exposición indebida al riesgo, al tiempo que mantiene un control sobre las operaciones.
Ejemplo:
input double dollar_risk = 12.0; // How Many Dollars($) Per Trade? input double RRR = 3; double ask_price; double lot_size; double point_risk; double take_profit; // Variable to store the time of the last executed trade datetime lastTradeBarTime = 0; //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Get the opening time of the current bar datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0); // Check conditions for opening a buy position // Ensures Heikin Ashi candle crosses above the moving average // Limits trades per day and prevents multiple trades in the same candlestick if(heikin_open[1] < heikin_ma[1] && heikin_close[1] > heikin_ma[1] && deal_type_buy < (daily_trades / 2) && total_deals_out < 1 && totalPositions < 1 && currentBarTime != lastTradeBarTime) { // Calculate risk in points (distance from entry to stop loss) point_risk = ask_price - heikin_low[1]; // Calculate take profit based on risk-to-reward ratio (RRR) take_profit = ((ask_price - heikin_low[1]) * RRR) + ask_price; // Determine lot size based on the dollar risk per trade lot_size = CalculateLotSize(_Symbol, dollar_risk, point_risk); // Execute a buy trade trade.Buy(lot_size, _Symbol, ask_price, heikin_low[1], take_profit); // Store the current bar time to prevent multiple trades in the same candle lastTradeBarTime = currentBarTime; } // Check conditions for opening a sell position // Ensures Heikin Ashi candle crosses below the moving average // Limits trades per day and prevents multiple trades in the same candlestick if(heikin_open[1] > heikin_ma[1] && heikin_close[1] < heikin_ma[1] && deal_type_sell < (daily_trades / 2) && total_deals_out < 1 && totalPositions < 1 && currentBarTime != lastTradeBarTime) { // Calculate risk in points (distance from entry to stop loss) point_risk = heikin_high[1] - ask_price; // Calculate take profit based on risk-to-reward ratio (RRR) take_profit = MathAbs(((heikin_high[1] - ask_price) * RRR) - ask_price); // Determine lot size based on the dollar risk per trade lot_size = CalculateLotSize(_Symbol, dollar_risk, point_risk); // Execute a sell trade trade.Sell(lot_size, _Symbol, ask_price, heikin_high[1], take_profit); // Store the current bar time to prevent multiple trades in the same candle lastTradeBarTime = currentBarTime; } } //+------------------------------------------------------------------+ //| Function to calculate the lot size based on risk amount and stop loss //+------------------------------------------------------------------+ double CalculateLotSize(string symbol, double riskAmount, double stopLossPips) { // Get symbol information double point = SymbolInfoDouble(symbol, SYMBOL_POINT); double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); // Calculate pip value per lot double pipValuePerLot = tickValue / point; // Calculate the stop loss value in currency double stopLossValue = stopLossPips * pipValuePerLot; // Calculate the lot size double lotSize = riskAmount / stopLossValue; // Round the lot size to the nearest acceptable lot step double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); lotSize = MathFloor(lotSize / lotStep) * lotStep; return lotSize; }
Explicación:
Para validar las tendencias, la lógica de ejecución de operaciones depende de que las velas Heikin Ashi crucen una media móvil (MA). Se indica una reversión alcista cuando el precio de apertura está por debajo de la media móvil y el cierre está por encima, y una venta cuando ocurre lo contrario. El sistema restringe las operaciones diarias, se asegura de que no haya posiciones abiertas y solo realiza operaciones con velas nuevas para evitar el trading excesivo. Los stop loss en los máximos o mínimos anteriores de Heikin Ashi, la toma de ganancias basada en una relación riesgo-recompensa (RRR) y el tamaño dinámico de los lotes son todos componentes de la gestión de riesgos.
3.2.5. Uso de velas Heikin Ashi para establecer un trailing stop
La implementación de un mecanismo de trailing stop utilizando velas Heikin Ashi es el objetivo principal de esta sección. Garantiza que los niveles de stop-loss se ajusten dinámicamente en respuesta a los cambios en el precio Heikin Ashi..
Ejemplo:
input bool allow_trailing = false; // Do you Allow Trailing Stop? //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Check if trailing stop is enabled if(allow_trailing == true) { // Variables to store trade-related information double positionProfit = 0; double positionopen = 0; double positionTP = 0; double positionSL = 0; // Loop through all open positions for(int i = 0; i < PositionsTotal(); i++) { // Get the ticket number of the position ulong ticket = PositionGetTicket(i); // Select the position using its ticket number if(PositionSelectByTicket(ticket)) { // Check if the position belongs to the EA by verifying the magic number and symbol if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { // Retrieve trade details: open price, take profit, profit, and stop loss positionopen = PositionGetDouble(POSITION_PRICE_OPEN); positionTP = PositionGetDouble(POSITION_TP); positionProfit = PositionGetDouble(POSITION_PROFIT); positionSL = PositionGetDouble(POSITION_SL); // Apply trailing stop logic for buy positions if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { // Adjust stop loss if Heikin Ashi low is above the entry price and the candle is bullish if(heikin_low[1] > positionopen && heikin_close[1] > heikin_open[1]) { trade.PositionModify(ticket, heikin_low[1], positionTP); } } // Apply trailing stop logic for sell positions if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { // Adjust stop loss if Heikin Ashi high is below the entry price and the candle is bearish if(heikin_high[1] < positionopen && heikin_close[1] < heikin_open[1]) { trade.PositionModify(ticket, heikin_high[1], positionTP); } } } } } } }
Explicación:
Para asegurar las ganancias y ajustar dinámicamente los niveles de stop-loss, esta sección utiliza velas Heikin Ashi para implementar un sistema de trailing stop. La variable de entrada allow_trailing controla si la función de stop dinámico está habilitada; si se establece en verdadero, el sistema recorre todas las posiciones abiertas, recupera sus detalles y verifica que pertenecen al EA comprobando el número mágico y el símbolo. Para simplificar la lógica del trailing stop, se extrae la información clave de la operación, incluyendo el precio de apertura, el take profit, el beneficio y el stop loss.
Al verificar que el mínimo anterior de Heikin Ashi es superior al precio de entrada y que el cierre de Heikin Ashi es superior a su apertura, el sistema verifica las posiciones abiertas y confirma una tendencia alcista. Para proteger las ganancias y permitir un movimiento alcista adicional, el stop loss se establece en el mínimo de Heikin Ashi si se alcanza. Al garantizar que el máximo anterior de Heikin Ashi esté por debajo del precio de entrada y que el cierre de Heikin Ashi esté por debajo de su apertura, se valida una tendencia bajista para las operaciones de venta. Para proteger la operación y aprovechar más las oscilaciones del mercado, el stop loss se establece en el máximo de Heikin Ashi si se cumplen estas condiciones.
Conclusión
En este artículo, hemos creado un indicador Heikin Ashi desde cero, lo hemos integrado con una media móvil que utiliza datos de velas Heikin Ashi y hemos explorado cómo incorporar un indicador personalizado en un EA, garantizando una integración perfecta para el trading automatizado. Implementamos técnicas de gestión de riesgos, como limitar las operaciones diarias, evitar múltiples operaciones cerradas dentro de la misma vela y calcular dinámicamente los tamaños de los lotes. Además, hemos introducido un mecanismo de trailing stop utilizando velas Heikin Ashi para ajustar los niveles de stop-loss. Estos conceptos proporcionan una base sólida para crear y perfeccionar estrategias de trading automatizadas en MQL5.
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/17296
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.
Utilizando redes neuronales en MetaTrader
Introducción a MQL5 (Parte 11): Guía de trabajo con indicadores incorporados en MQL5 para principiantes (II)
Particularidades del trabajo con números del tipo double en MQL4
Redes neuronales en el trading: Detección adaptativa de anomalías del mercado (DADA)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Hola Isreal,
Gracias por el blog, el tiempo y el esfuerzo.
Me gustaría preguntarte sobre tu código de indicador personalizado Heikin Ashi.
Sobre la fórmula Heikin Ashi Open :
// HEIKIN ASHI OPEN FORMULA
HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;
Como no has calculado el HA_Open[i - 1). ¿No sería 0?
Mi sugerencia :
if (i == 1){
HA_Open[i] = (open[i - 1] + close[i - 1])/2.0; // En la primera barra de HA solo usa los datos normales de apertura/cierre
}
else{
// FÓRMULA DE APERTURA HEIKIN ASHI
HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;
}
En la fórmula Heikin Ashi Open :
// HEIKIN ASHI OPEN FORMULA
HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;
Como no has calculado el HA_Open[i - 1). ¿No sería 0?
Mi sugerencia :
if (i == 1){
HA_Open[i] = (open[i - 1] + close[i - 1])/2.0; // En la primera barra de HA utiliza los datos normales de apertura/cierre
}
else{
// FÓRMULA DE APERTURA HEIKIN ASHI
HA_Open[i] = (HA_Open[i - 1] + HA_Close[i - 1]) / 2.0;
}