English Русский 中文 Deutsch 日本語 Português
preview
¿Puede Heiken Ashi dar buenas señales en combinación con las medias móviles?

¿Puede Heiken Ashi dar buenas señales en combinación con las medias móviles?

MetaTrader 5Sistemas comerciales | 28 noviembre 2023, 16:58
765 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Introducción

Las combinaciones de estrategias pueden mejorar el rendimiento de las transacciones. Podemos combinar indicadores y patrones para obtener confirmaciones adicionales. En este artículo, veremos cómo usar el gráfico Heiken Ashi junto con las medias móviles como método de confirmación de una tendencia. Al final, analizaremos varias opciones de optimización.

portada



Velas Heiken Ashi

Las velas suponen una forma rápida y sencilla de interpretar los datos OHLC (apertura, máximo, mínimo, cierre) y descubrir patrones. Las velas alcistas (normalmente verdes) aparecen cuando el mercado cierra por encima del precio de apertura. Las velas bajistas (normalmente rojas) aparecen cuando el mercado cierra por debajo del precio de apertura.


candle ohlc


patrones comerciales


Echemos un vistazo el gráfico para comprenderlo mejor. La tendencia es claramente alcista, hay correcciones alrededor de las velas rojas. Preste atención a las velas pequeñas con un precio de apertura casi igual al precio de cierre. Se denominan dojis e indican un carácter indeciso y un posible retroceso o consolidación.

velas


Las velas Heiken Ashi tienden a aclarar el panorama y mostrar una tendencia más clara suavizando los datos de OHLC. Aquí vemos cómo se realiza el cálculo de las velas Heiken Ashi:

(open + high + low + close)  ÷  4


Heikin-Ashi High=Valor máximo (High-0, Open-0 y Close-0) 

Heikin-Ashi Low=Valor mínimo (Low-0, Open-0 y Close-0)


Heikin Ashi es un indicador japonés. Traducido literalmente del japonés, significa "ritmo medio". Los gráficos Heikin-Ashi se parecen a los gráficos de velas, pero tienen un aspecto más suave porque siguen un rango de movimientos de precios en lugar de seguir cada movimiento del mismo, como sucede con las velas normales. Heikin Ashi fue creado en el siglo XVIII por Munehisa Homma, que también creó el gráfico de velas. Los tráders e inversores utilizan estos gráficos para identificar y predecir los movimientos del precio.

Al igual que las velas estándar, la vela Heikin Ashi tiene un cuerpo y una sombra, pero el propósito de su aplicación es distinto. El último precio de una vela Heikin-Ashi se calcula usando el precio medio de la barra o marco temporal actual (por ejemplo, en un marco temporal diario, cada barra representaría el movimiento del precio en ese día concreto). La fórmula para el precio de la última barra Heikin Ashi será la siguiente: (open + high + low + close)  ÷  4. Heikin Ashi se abre en la mitad de la vela anterior según la fórmula: (apertura de la barra anterior + cierre de la barra anterior) ÷ 2. Los puntos de precio más alto y más bajo están representados por sombras, igual que las velas.

Las fórmulas anteriores suavizan las velas, ofreciéndonos una tendencia más clara y definida.


heiken ashi (1) candles(2)


Estos dos gráficos suponen la comparación de un gráfico de velas regular y un gráfico Heiken Ashi. Podemos ver las semejanzas, pero también que el primer gráfico es más suave. Como el método Heiken Ashi muestra un valor medio, el precio mostrado podría no ser el verdadero precio de mercado.


Medias móviles

Las medias móviles nos ayudan a confirmar tendencias y seguirlas. Se trata del indicador técnico más famoso, lo cual se explica por su sencillez y su probada eficacia de análisis. Podemos utilizarlo para encontrar niveles de apoyo y resistencia, niveles stop y objetivo, y también para descubrir la tendencia básica. Esta versatilidad convierte a la media móvil en una herramienta indispensable en nuestro arsenal comercial.

En estadística, las medias móviles suponen un cálculo para analizar los puntos de datos mediante la creación de una serie de medias a partir de diferentes muestras de un conjunto completo de datos. El indicador es un tipo de filtro con una característica de impulso finita. Se distingue entre medias móviles simples, acumulativas y ponderadas (descritas más abajo).

Un filtro de media móvil se denomina a veces filtro de caja (boxcar filter), sobre todo si va seguido de un diezmado (downsample).

Dada una serie de números y un tamaño de subconjunto fijo, el primer elemento de la media móvil se obtiene usando la media del subconjunto fijo original de la serie de números. A continuación, el subconjunto se modifica mediante "desplazamiento hacia delante", es decir, excluyendo el primer valor de la serie e incluyendo el siguiente valor del subconjunto.

Las medias móviles se suelen usar con datos de series temporales para suavizar las fluctuaciones a corto plazo y resaltar las tendencias o ciclos a largo plazo. El umbral entre las fluctuaciones a corto y largo plazo dependerá de la aplicación y los parámetros de la media móvil se ajustarán en consecuencia. El indicador también se usa en economía para estudiar el producto interior bruto, el empleo u otras series temporales macroeconómicas. Desde un punto de vista matemático, la media móvil es un tipo de convolución, por lo que puede considerarse un ejemplo de filtro de paso bajo usado en el tratamiento de señales. Al utilizarse con datos que no sean series temporales, la media móvil filtra los componentes de alta frecuencia sin ninguna relación específica con el tiempo, aunque suele implicar algún tipo de clasificación. Simplificando, esto puede considerarse un suavizado de datos.


ma


Como su nombre indica, es una media simple que se usa en estadística y en casi todos los demás ámbitos de nuestra vida. Supone simplemente el valor total de las observaciones dividido por el número de las mismas. Matemáticamente, puede representarse de la forma que sigue:

ma form


Podemos ver que la media móvil ofrece unos niveles de apoyo y resistencia dinámicos bastante decentes, que sirven como punto de partida para colocar órdenes si el mercado cae.



Plan

compra


Como sucede con cualquier método de investigación, nuestro objetivo consiste en probar la estrategia y ver si merece la pena utilizarla como complemento a nuestro sistema comercial actual o no.

El primer paso será crear las reglas del juego. ¿Cuándo comprará y venderá el sistema? En otras palabras, ¿cuándo se dará una señal que indique al sistema que el mercado actual subirá o bajará?

Condiciones comerciales:

  • Compraremos siempre que el gráfico Heikin-Ashi sea alcista y el mercado cruce la media móvil de 100 periodos.
  • Venderemos siempre que el gráfico Heikin Ashi sea bajista y el mercado cruce la media móvil de 100 periodos.

Al desarrollar un algoritmo comercial, deberemos tener en cuenta la frecuencia de las señales, así como la función de señal utilizada para generar los activadores basados en las condiciones mencionadas.



Resultados

Estos son los resultados para EURUSD M30 del 1 de enero de 2022 al 5 de julio de 2023. Podemos obtener mejores resultados optimizando en otros marcos temporales. Tendremos que optimizarlo y probarlo para poder utilizarlo con todos los símbolos.

Gráfico

Informe del simulador de estrategias



Código

int OnInit()
  {
//---
   handle_iCustomMA=iCustom(_Symbol,my_timeframe,"\\folder/s where you have the indicator\\sma",MAPeriod,MAShift);
   handle_iCustomHeiken=iCustom(_Symbol,my_timeframe_Heiken,"\\folder/s where you have the indicator\\Heiken_Ashi_copy");
//---
   if(handle_iCustomMA==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d",
                  _Symbol,
                  EnumToString(my_timeframe),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
   if(handle_iCustomHeiken==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d",
                  _Symbol,
                  EnumToString(my_timeframe_Heiken),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
   return(INIT_SUCCEEDED);
  }

Este código se usa para inicializar dos indicadores personalizados en MQL5. El primer indicador será una media móvil simple (SMA) con los parámetros MAPeriod y MAShift. El segundo indicador será una copia de Heiken Ashi. El código creará manejadores para cada indicador y comprobará si hay errores. Si se detecta un error, se mostrará un código de error y se retornará INIT_FAILED. Si no se detectan errores, el código retornará INIT_SUCCEED.

void OnTick()
  {
   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[];
   CopyBuffer(handle_iCustomHeiken,0,0,2,heikenAshiOpen);
   CopyBuffer(handle_iCustomHeiken,1,0,2,heikenAshiHigh);
   CopyBuffer(handle_iCustomHeiken,2,0,2,heikenAshiLow);
   CopyBuffer(handle_iCustomHeiken,3,0,2,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));
//---
   MqlTick tick;
   double last_price = tick.ask;
   SymbolInfoTick(_Symbol,tick);
   int total = PositionsTotal();
//---
// Retrieve the current value
   MqlTradeResult  result;
   MqlRates rates[];
//---
   double array_ma[];
   ArraySetAsSeries(array_ma,true);
   int start_pos2=0,count2=5;
   if(!iGetArray2(handle_iCustomMA,0,start_pos2,count2,array_ma))
      return;
//------------------------------------------------------------------------------
     {
      if(DoubleToString(heikenAshiClose[0],_Digits) < DoubleToString(heikenAshiOpen[0],_Digits) && (DoubleToString(heikenAshiClose[1],_Digits) > DoubleToString(heikenAshiOpen[1],_Digits)))
        {
         Print("Open Order Buy");
         Alert(" Buying");
         Orden="Buy";
         sl=NormalizeDouble(tick.ask - ptsl*_Point,_Digits);
         tp=NormalizeDouble(tick.bid + pttp*_Point,_Digits);
         trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,get_lot(tick.bid),tick.bid,sl,tp,"Buy");
         return;
        }
     }
     {
      if(DoubleToString(heikenAshiClose[0],_Digits) > DoubleToString(heikenAshiOpen[0],_Digits) && (DoubleToString(heikenAshiClose[1],_Digits) < DoubleToString(heikenAshiOpen[1],_Digits)))
        {
         Print("Open Order Sell");
         Alert(" Selling");
         Orden="Sell";
         sl=NormalizeDouble(tick.bid + ptsl*_Point,_Digits);
         tp=NormalizeDouble(tick.ask - pttp*_Point,_Digits);
         trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,get_lot(tick.ask),tick.ask,sl,tp,"Sell");
         return;
        }
     }
   if(total>0)
     {
      if(Orden=="Sell" &&(DoubleToString(heikenAshiClose[0],_Digits) < DoubleToString(heikenAshiOpen[0],_Digits) ))
        {
         trade.PositionClose(_Symbol,5);
         Print("cerró sell");
         return;
        }
      if(Orden=="Buy" &&(DoubleToString(heikenAshiClose[0],_Digits) > DoubleToString(heikenAshiOpen[0],_Digits) ))
        {
         trade.PositionClose(_Symbol,5);
         Print("cerró buy");
         return;
        }
     }
  }

Este fragmento de código supone un script en MQL5 que se utilizará para abrir y cerrar posiciones en el mercado Fórex. Comienza declarando cuatro arrays dobles (heikenAshiOpen, heikenAshiHigh, heikenAshiLow y heikenAshiClose) y copiando los valores del indicador personalizado iCustomHeiken. A continuación, extraerá los datos de ticks actuales del símbolo y declarará los arrays MqlTradeResult y MqlRates. Después declarará un array para la media móvil (array_ma) y establecerá el array como una serie. Luego extraerá los valores del indicador personalizado iCustomMA y los almacenará en array_ma. Finalmente comprobará si el cierre de Heiken Ashi actual está por debajo de la apertura, mientras que el cierre de Heiken Ashi anterior está por encima de la apertura, y si es así, abrirá una orden de compra con el stop loss y take profit especificados. También comprobará si el cierre de Heiken Ashi actual está por encima de la apertura, mientras que el cierre de Heiken Ashi anterior está por debajo de la apertura, y si es así, abrirá una orden de venta con el stop loss y take profit especificados. Si hay posiciones abiertas, comprobará si el cierre de Heiken Ashi está por debajo de la apertura para una orden de venta, y si está por encima de la apertura para una orden de compra, y si es así, cerrará la posición.

El primer entero CopyBuffer será el valor a partir del cual se comenzará el conteo, mientras que el segundo entero CopyBuffer será el valor del número de conteos. Hemos utilizado dos en lugar de uno para tener en cuenta el 1-n (en este caso, la vela Heiken Ashi inmediatamente anterior). Esto era necesario para que la estrategia viera el cambio de color en la condición if (abrir o no abrir una orden).

Las dos condiciones if para abrir/cerrar órdenes es lo que usted deberá cambiar en el código. Podrá, por ejemplo, utilizar más velas del mismo color antes de abrir una orden o cambiar a una segunda vela de otro color para cerrar órdenes.

Otra buena solución para cerrar órdenes sería utilizar otra SMA con un periodo diferente y utilizar señales cruzadas para cerrar órdenes, como en el ejemplo de la imagen:

heiken ashi 2 ma


//+------------------------------------------------------------------+
double get_lot(double price)
  {
   if(inp_lot_type==LOT_TYPE_FIX)
      return(normalize_lot(inp_lot_fix));
   double one_lot_margin;
   if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,one_lot_margin))
      return(inp_lot_fix);
   return(normalize_lot((AccountInfoDouble(ACCOUNT_BALANCE)*(inp_lot_risk/100))/ one_lot_margin));
  }
double normalize_lot(double lt)
  {
   double lot_step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   lt = MathFloor(lt / lot_step) * lot_step;
   double lot_minimum = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   lt = MathMax(lt, lot_minimum);
   return(lt);
  }
bool iGetArray2(const int handle2,const int buffer2,const int start_pos2,
                const int count2,double &arr_buffer2[])
  {
   bool result2=true;
   if(!ArrayIsDynamic(arr_buffer2))
     {
      //if(InpPrintLog)
      PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__);
      return(false);
     }
   ArrayFree(arr_buffer2);
//--- reset error code
   ResetLastError();
//--- fill a part of the iBands array with values from the indicator buffer
   int copied2=CopyBuffer(handle2,buffer2,start_pos2,count2,arr_buffer2);
   if(copied2!=count2)
     {
      //--- if the copying fails, tell the error code
      //if(InpPrintLog)
      PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d",
                  __FILE__,__FUNCTION__,count2,copied2,GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
   return(result2);
  }

Este código supone una función MQL5 que calcula el tamaño del lote para una transacción. La función toma una variable double llamada precio y la utiliza para calcular el tamaño del lote. 

La función comprueba primero si el tipo de lote es fijo y, en caso afirmativo, retorna el tamaño de lote normalizado. Si no, calculará el margen para un solo lote y, a continuación, calculará el tamaño del lote según el balance de la cuenta y del porcentaje de riesgo. A continuación, retornará el tamaño de lote normalizado. 

Después se utilizará la función normalize_lot para redondear el tamaño de lote al tamaño de paso más próximo y garantizar que el tamaño de lote no sea inferior al tamaño de lote mínimo. 

Luego se utilizará la función iGetArray2 para copiar los valores del búfer de indicador y comprobar si hay errores. Si se detecta un error, la función retornará false.



Conclusión

Hoy hemos visto cómo se puede utilizar Heiken Ashi con otro indicador.

Obviamente, aquí podemos realizar optimizaciones adicionales para ajustar la frecuencia de las señales y mejorar su calidad:

  • Podemos elegir una condición relacionada con el gráfico Heikin Ashi donde activemos la señal después de velas consecutivas.
  • Asimismo, podemos configurar el periodo de análisis retrospectivo de las medias móviles. También podemos añadir otras medias móviles y cambiar la estrategia a un cruce de medias móviles en lugar del cruce simple del precio de mercado y una media móvil.
  • Podemos incluir en Heikin Ashi gráficos de velas y combinarlos con medias móviles.
  • También podemos incluir la distancia entre Heikin Ashi y la media móvil como una medida del riesgo o incluso como un disparador opuesto.
  • Además, podemos utilizar la anchura del cuerpo de la vela como medida de la fuerza de la tendencia, o podemos incluir la pendiente de la media móvil en la fórmula.

Hoy hemos aprendido a aplicar esta estrategia y también a aplicar indicadores personalizados. Asimismo, hemos aprendido a utilizar el lote fijo y el lote con porcentaje de riesgo. También hemos aprendido a abrir y cerrar órdenes y a utilizar las condiciones de las órdenes. Además, hemos utilizado un búfer de copiado para Heiken Ashi y la media móvil, y hemos hecho una prueba rentable y visto los resultados. También hemos analizado la posibilidad de añadir puntos de stop loss y take profit y de normalizar el número de decimales. Para normalizar los lotes, hemos utilizado el paso de volumen de los símbolos y el volumen mínimo de los mismos.

Espero que le haya gustado el artículo.

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

Archivos adjuntos |
sma.mq5 (1.78 KB)
Crear paneles gráficos en MQL5 es ahora más fácil Crear paneles gráficos en MQL5 es ahora más fácil
En este artículo, ofreceremos una guía sencilla y comprensible para cualquier usuario que quiera crear una de las herramientas más valiosas y útiles en el trading: un panel gráfico que facilite las tareas comerciales. Los paneles gráficos nos permiten ahorrar tiempo y centrarnos más en las operaciones en sí.
Redes neuronales: así de sencillo (Parte 48): Métodos para reducir la sobreestimación de los valores de la función Q Redes neuronales: así de sencillo (Parte 48): Métodos para reducir la sobreestimación de los valores de la función Q
En el artículo anterior, presentamos el método DDPG, que nos permite entrenar modelos en un espacio de acción continuo. Sin embargo, al igual que otros métodos de aprendizaje Q, el DDPG tiende a sobreestimar los valores de la función Q. Con frecuencia, este problema provoca que entrenemos los agentes con una estrategia subóptima. En el presente artículo, analizaremos algunos enfoques para superar el problema mencionado.
Redes neuronales: así de sencillo (Parte 49): Soft Actor-Critic Redes neuronales: así de sencillo (Parte 49): Soft Actor-Critic
Continuamos nuestro análisis de los algoritmos de aprendizaje por refuerzo en problemas de espacio continuo de acciones. En este artículo, le propongo introducir el algoritmo Soft Astog-Critic (SAC). La principal ventaja del SAC es su capacidad para encontrar políticas óptimas que no solo maximicen la recompensa esperada, sino que también tengan la máxima entropía (diversidad) de acciones.
Mejore sus gráficos comerciales con una GUI interactiva basada en MQL5 (Parte II): Interfaz móvil (II) Mejore sus gráficos comerciales con una GUI interactiva basada en MQL5 (Parte II): Interfaz móvil (II)
Descubra el potencial de la presentación dinámica de datos en sus estrategias y utilidades comerciales con nuestra guía detallada para crear GUI móviles en MQL5. Sumérjase en los principios fundamentales de la programación orientada a objetos y aprenda a diseñar y utilizar de manera fácil y eficiente una o más GUI móviles en un solo gráfico.