Página 1 de 1

Calculo de la media de un indicador

Publicado: 08 Nov 2024 18:57
por CactusJavv
Buenas tardes/noches.
El año pasado por estas fechas me encontré por Youtube un video antiguo donde relataban una posible estrategia para Forex y que procedí a implementar en MT4.

El tema es que dicha estrategia tenía entre su Setup de entrada una condición y era la siguiente:

"Cuando el valor de la media exponencial de 4 periodos del ATR de 14 periodos supera un determinado nivel"
(Donde los periodos de la media 4, y del ATR se pueden optimizar)

Estuve buscando por la web si había algún indicador parecido o función que hiciera eso mismo pero al no encontrar ninguno me puse a hacerlo yo.

Para obtener ese valor de EMA4(ATR14) hice el siguiente código en MT4:

Código: Seleccionar todo

double MA_ATR(int period, int position, ENUM_MA_METHOD MAMethod) {

   double MAATR   =  0.0;
   double atr_array[];
   ArraySetAsSeries(atr_array, true);
   ArrayResize(atr_array, period + 1);
   SetIndexBuffer(0, atr_array);
   
   for (int i = 0; i <= period; i++) {
      atr_array[i]   =  iATR(Symbol(), Period(), 14, i);
   }
   
   MAATR          =  iMAOnArray(atr_array, 0, period, 0, MAMethod, position);
   
   return (MAATR);

}


El problema con el que me encontré es que con las optimizaciónes esto se eternizaba, la ejecución que me podrían llevar minutos en cuanto ponía a optimizar con esta media me tardaban horas.

¿Alguien ha hecho algo parecido?
¿Alguien tiene alguna idea para hacer ese proceso más rápido?

Ojo, creo que el código funciona pero he tenido que reconstruir mi repositorio de código y es posible que esta no sea la versión correcta............. no me hago responsable de "valores raros" ;-)

Y la última pregunta, ¿Creéis que este tipo de "indicadores/valores" no son una sobreoptimización por si mismos? Vamos si ¿merece la pena investigarlos?

Gracias

Re: Calculo de la media de un indicador

Publicado: 09 Nov 2024 13:51
por Foréxitos
Hola Cactus, no es necesario el SetIndexBuffer, y se ralentiza la optimización porque la memoria, calcula todo el ATR cuando la media solo necesita la cantidad exacta de valores del ATR para obtener el mismo resultado. Igualmente no está mal hecho. Acá te dejo el indicador completo para que lo puedas usar sin problemas. Cualquier cosa por aquí me tienes, Saludos.

Código: Seleccionar todo

//+------------------------------------------------------------------+
//|                                                      MA_ATR.mq4  |
//|                        Copyright © 2024, Foréxitos®              |
//|                        https://www.forexitos.com                 |
//+------------------------------------------------------------------+
#property copyright "Copyright© 2024, Foréxitos®"
#property link      "https://www.forexitos.com"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Blue

// Buffers del indicador
double atr_ma_buffer[];

// Parámetros de entrada
input int ATR_Period = 14;           // Período del ATR
input int MA_Period = 4;            // Período de la media móvil
input ENUM_MA_METHOD MA_Method = MODE_EMA; // Método de la media móvil

//+------------------------------------------------------------------+
//| Inicialización del indicador                                     |
//+------------------------------------------------------------------+
int OnInit() {
   // Configuración de buffer del indicador
   SetIndexBuffer(0, atr_ma_buffer);
   ArraySetAsSeries(atr_ma_buffer, true);
   IndicatorShortName("MA en ATR (" + IntegerToString(ATR_Period) + ", " + IntegerToString(MA_Period) + ")");

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Cálculo del indicador                                            |
//+------------------------------------------------------------------+
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[]) {

   // Verificar si hay suficientes barras para el cálculo
   if (rates_total < ATR_Period + MA_Period) {
      return(0);
   }

   // Crear y redimensionar array temporal para almacenar ATRs
   double atr_array[];
   ArraySetAsSeries(atr_array, true);
   ArrayResize(atr_array, rates_total);

   // Calcular el ATR para cada barra si es la primera vez o hay nuevos datos
   int start = MathMax(prev_calculated - 1, ATR_Period);
   for (int i = start; i < rates_total; i++) {
      atr_array[i] = iATR(NULL, 0, ATR_Period, i);
   }

   // Calcular la media móvil sobre el array de ATRs
   for (int e = start; e < rates_total; e++) {
      atr_ma_buffer[e] = iMAOnArray(atr_array, 0, MA_Period, 0, MA_Method, e);
   }

   return(rates_total);
}

Re: Calculo de la media de un indicador

Publicado: 09 Nov 2024 14:18
por Foréxitos
Perdón, con respecto a las demás preguntas, no es necesario ponerle una media al ATR ya que el mismo ATR promedia en periodos y optimizar esto no daría buenos resultados, pero si es importante en cualquier operativa tener en cuenta la volatilidad ya que el ATR es un indicador que "la mide".... entre comillas.... se entiende, no? Lo mejor es tener en cuenta la volatilidad sobre la acción del precio, en el preciso momento, ya que es parte del calculo del VaR.

Re: Calculo de la media de un indicador

Publicado: 10 Nov 2024 10:31
por Trader_en_pelotas
Hola CactusJavv

Por lo que comentas, parece que el problema de velocidad en tu código viene del uso del bucle for, que recorre los periodos uno a uno. Esto puede volverse lento, especialmente cuando estás optimizando, porque cada ciclo del bucle añade más carga de cálculo.

En Python podemoss hacer el mismo cálculo de forma mucho más eficiente gracias a la vectorización, que nos permite operar sobre toda una serie de datos sin necesidad de bucles. De esta forma, reducimos el tiempo de ejecución considerablemente.

Aquí tienes cómo lo haríamos en Python, suponiendo que tenemos un DataFrame (df) con datos OHLCV:

Código: Seleccionar todo

# Calcula la EMA de 4 periodos del ATR de 14 periodos en una sola línea
df['ema_4_atr_14'] = df[['high', 'low', 'close']].apply(
    lambda row: max(row['high'] - row['low'], 
                    abs(row['high'] - row['close'].shift()), 
                    abs(row['low'] - row['close'].shift())),
    axis=1
).ewm(span=14, adjust=False).mean().ewm(span=4, adjust=False).mean()

Aquí evitamos el uso de bucles, por lo que es mucho más rápido en comparación. La cuestión es que no se si en MT4 tienes alguna forma de aplicar vectorización de este estilo, pero si encuentras una manera, definitivamente aumentaría el rendimiento de tu código.

¡Espero que te sirva!

Re: Calculo de la media de un indicador

Publicado: 11 Nov 2024 16:31
por CactusJavv
Foréxitos escribió: 09 Nov 2024 14:18 Perdón, con respecto a las demás preguntas, no es necesario ponerle una media al ATR ya que el mismo ATR promedia en periodos y optimizar esto no daría buenos resultados, pero si es importante en cualquier operativa tener en cuenta la volatilidad ya que el ATR es un indicador que "la mide".... entre comillas.... se entiende, no? Lo mejor es tener en cuenta la volatilidad sobre la acción del precio, en el preciso momento, ya que es parte del calculo del VaR.
Si, se entiende, gracias!!

Re: Calculo de la media de un indicador

Publicado: 11 Nov 2024 16:32
por CactusJavv
Trader_en_pelotas escribió: 10 Nov 2024 10:31 Hola CactusJavv

Por lo que comentas, parece que el problema de velocidad en tu código viene del uso del bucle for, que recorre los periodos uno a uno. Esto puede volverse lento, especialmente cuando estás optimizando, porque cada ciclo del bucle añade más carga de cálculo.

En Python podemoss hacer el mismo cálculo de forma mucho más eficiente gracias a la vectorización, que nos permite operar sobre toda una serie de datos sin necesidad de bucles. De esta forma, reducimos el tiempo de ejecución considerablemente.

Aquí tienes cómo lo haríamos en Python, suponiendo que tenemos un DataFrame (df) con datos OHLCV:

Código: Seleccionar todo

# Calcula la EMA de 4 periodos del ATR de 14 periodos en una sola línea
df['ema_4_atr_14'] = df[['high', 'low', 'close']].apply(
    lambda row: max(row['high'] - row['low'], 
                    abs(row['high'] - row['close'].shift()), 
                    abs(row['low'] - row['close'].shift())),
    axis=1
).ewm(span=14, adjust=False).mean().ewm(span=4, adjust=False).mean()

Aquí evitamos el uso de bucles, por lo que es mucho más rápido en comparación. La cuestión es que no se si en MT4 tienes alguna forma de aplicar vectorización de este estilo, pero si encuentras una manera, definitivamente aumentaría el rendimiento de tu código.

¡Espero que te sirva!
Python está todavía en mis "tareas pendientes".......... No me suena de que se pueda hacer eso en MT4, lo revisaré, muchas gracias!

Re: Calculo de la media de un indicador

Publicado: 11 Nov 2024 17:16
por X-Trader
Hola CactusJavv, te paso código ya hecho para calcular diferentes tipos de medias sobre el ATR, creo que si lo revisas encontrarás la solución a tus problemas :-D.


Saludos,
X-Trader