Discusión sobre el artículo "Creación de una estrategia de retorno a la media basada en el aprendizaje automático" - página 8

[Eliminado]  
sibirqk #:

Imho por supuesto, pero el uso de Savitsky_Golay no es muy diferente de la utilización de muve. El filtro SG es el punto medio de una regresión polinómica en una ventana deslizante dada, con un grado de polinomio especificado. Para el grado 1, coincide perfectamente con el muve del periodo correspondiente.

Para identificar el retorno a la media, tiene más sentido, en mi opinión, utilizar el filtrado de amplitud - renko, renji, zigzags. Creo que los rangos son los mejores - la diferencia entre Hg y Lw es una constante. Bueno, o un tamaño constante ZZ, que es básicamente lo mismo.

Bueno, el ZZ ha demostrado ser peor.
[Eliminado]  

Fourier y la descomposición de valor singular se muestran bastante bien como filtros. No he participado en la selección de parámetros, primeras variantes.


[Eliminado]  

Un ejemplo de adición de decaimiento exponencial al proceso de filtrado, basado en la primera función de marcado del artículo. Los últimos ejemplos tienen más peso en el marcado, para ajustarse a los datos más recientes.

def get_labels_filter(dataset, rolling=200, quantiles=[.45, .55], polyorder=3, decay_factor=0.95) -> pd.DataFrame:
    """
    Generates labels for a financial dataset based on price deviation from a Savitzky-Golay filter,
    with exponential weighting applied to prioritize recent data.

    Args:
        dataset (pd.DataFrame): DataFrame containing financial data with a 'close' column.
        rolling (int, optional): Window size for the Savitzky-Golay filter. Defaults to 200.
        quantiles (list, optional): Quantiles to define the "reversion zone". Defaults to [.45, .55].
        polyorder (int, optional): Polynomial order for the Savitzky-Golay filter. Defaults to 3.
        decay_factor (float, optional): Exponential decay factor for weighting past data. 
                                        Lower values prioritize recent data more. Defaults to 0.95.

    Returns:
        pd.DataFrame: The original DataFrame with a new 'labels' column and filtered rows:
                       - 'labels' column: 
                            - 0: Buy
                            - 1: Sell
                       - Rows where 'labels' is 2 (no signal) are removed.
                       - Rows with missing values (NaN) are removed.
                       - The temporary 'lvl' column is removed. 
    """

    # Calcular los precios suavizados utilizando el filtro Savitzky-Golay.
    smoothed_prices = savgol_filter(dataset['close'].values, window_length=rolling, polyorder=polyorder)
    
    # Calcular la diferencia entre los precios de cierre reales y los precios suavizados.
    diff = dataset['close'] - smoothed_prices
    
    # Aplicar ponderación exponencial a los valores 'diff
    weighted_diff = diff * np.exp(np.arange(len(diff)) * decay_factor / len(diff)) 
    dataset['lvl'] = weighted_diff # Añade la diferencia ponderada como 'lvl'

    # Eliminar las filas con valores NaN 
    dataset = dataset.dropna()
    
    # Calcular los cuantiles de la columna 'lvl' (desviación del precio)
    q = dataset['lvl'].quantile(quantiles).to_list() 

    # Extraer los precios de cierre y los valores 'lvl' calculados como arrays NumPy
    close = dataset['close'].values
    lvl = dataset['lvl'].values
    
    # Calcular las etiquetas de compra/venta utilizando la función 'calculate_labels_filter 
    labels = calculate_labels_filter(close, lvl, q) 

    # Recorta el conjunto de datos para que coincida con la longitud de las etiquetas calculadas
    dataset = dataset.iloc[:len(labels)].copy()
    
    # Añade las etiquetas calculadas como una nueva columna 'labels' al DataFrame
    dataset['labels'] = labels
    
    # Eliminar las filas con valores NaN
    dataset = dataset.dropna()
    
    # Elimina las filas en las que la columna "etiquetas" tiene un valor de 2,0 (señales de venta)
    dataset = dataset.drop(dataset[dataset.labels == 2.0].index)
    
    # Devuelve el DataFrame modificado con la columna 'lvl' eliminada
    return dataset.drop(columns=['lvl'])


  • El parámetro decay_factor (por defecto 0,95) se añade al código para controlar el peso que se da a los datos pasados.
  • Para cada punto de datos, calculamos el peso utilizando np.exp(np.exp(np.arange(len(diff)))) * decay_factor / len(diff)), y lo multiplicamos por los valores de diff. Esto da más peso a las diferencias recientes y menos a las antiguas. Columna 'lvl' ponderada: La columna lvl almacena ahora diferencias ponderadas exponencialmente, lo que hace que el proceso de marcado sea más sensible a los movimientos recientes de los precios.
  • Un valor de decay_factor menor (más cercano a 0) hará que la ponderación sea más agresiva, resaltando con más fuerza los cambios de precios recientes. Esto significa que el algoritmo reaccionará más rápido a las desviaciones recientes de la tendencia de precios suavizada.
  • Un valor de decay_factor mayor (más cercano a 1) hará que la ponderación sea más suave, dando más peso a los datos pasados. Esto puede ser útil para reducir la influencia del ruido a corto plazo e identificar tendencias a largo plazo.
[Eliminado]  

Para el entrenamiento en intervalos más cortos, por ejemplo de 2018 a 2024, pueden obtenerse pocas operaciones si n_clusters = 10 en los hiperparámetros. Reducir el número de clusters, por ejemplo a 5-3, ayuda a obtener más operaciones.

De esta forma, se puede entrenar en periodos de tiempo más cortos y buscar buenos patrones en ellos variando diferentes parámetros.

También puede reducir los periodos de filtrado (filtro Savitzky-Golei o splines) de los muestreadores de operaciones.


 
¡Hola Max! Te escribo para decirte que espero con impaciencia los artículos de "Maxim Dmitrievsky". Estudiar cada artículo que publique, he estado siguiendo de cerca su trabajo durante los últimos 2 años. Soy de Brasil, estudio y aprendo algo nuevo y valioso.

Espero de todo corazón que tú, Maxim, continúes compartiendo la investigación de conocimientos y que el equipo de MetaQuotes te valore como un autor respetado y 'comparta las ganancias' para animarte a continuar con el increíble trabajo. ¡Espero que seas el mejor, Maxim!

Por favor, @MetaQuotes y el equipo @MetaQuotes @alexx, ¡dénle un aumento a este tipo! Se lo merece <3

Saludos desde Brasil
Maxim Dmitrievsky
Maxim Dmitrievsky
  • 2025.03.07
  • www.mql5.com
Профиль трейдера
[Eliminado]  
Vinicius Barenho Pereira #:
¡Hola Max! Te escribo para decirte que espero con impaciencia los artículos de "Maxim Dmitrievsky". Para estudiar cada artículo que publique, he estado siguiendo de cerca su trabajo durante los últimos 2 años. Soy de Brasil, estudio y aprendo algo nuevo y valioso.

Espero de todo corazón que tú, Maxim, continúes compartiendo la investigación de conocimientos y que el equipo de MetaQuotes te valore como un autor respetado y 'comparta las ganancias' para animarte a continuar con el increíble trabajo. ¡Espero que seas el mejor, Maxim!

Por favor, @MetaQuotes y el equipo @MetaQuotes @alexx, ¡dénle un aumento a este tipo! Se lo merece <3

Saludos desde Brasil

Gracias, voy a tratar de hacer algo interesante y tal vez útil en el futuro :)

 

esto es genial: Al final del artículo será posible entrenar diferentes modelos de aprendizaje automático en Python y convertirlos en sistemas de comercio para el terminal de comercio MetaTrader 5.

¡Voy a mirar en él con más detalle - gracias por el artículo!

[Eliminado]  
Roman Shiredchenko modelos de aprendizaje automático en Python y convertirlos en sistemas de trading para el terminal de trading MetaTrader 5.

Lo estudiaré con más detalle - ¡gracias por el artículo!

De nada, a veces incluso ganar dinero )
 

Hola Maxim,

He encontrado un problema con la generación de valores en la función get_features en Python y en MetaTrader 5.

El problema radica en la estadística "skew" en Python y "skewness" en MQL5. De las pruebas que he realizado, los valores generados por los dos lenguajes son ligeramente diferentes. Por ejemplo:

-0.087111
En MQL5, y
-0.092592
En Python

Puede parecer algo menor, pero tras la clasificación de las meta_etiquetas, esto conlleva un retraso en la predicción, provocando que el EA suela entrar una vela tarde, lo que hace que la estrategia no sea efectiva. Recomiendo no usar esta estadística en MQL5, o intentar calcularla manualmente para que coincida con los mismos valores.

Saludos desde Brasil

[Eliminado]  
KleversonGerhardt #:

Hola Maxim,

He encontrado un problema con la generación de valores en la función get_features en Python y en MetaTrader 5.

El problema radica en la estadística "skew" en Python y "skewness" en MQL5. De las pruebas que he realizado, los valores generados por los dos lenguajes son ligeramente diferentes. Por ejemplo:

-0.087111
En MQL5, y
-0.092592
En Python

Puede parecer algo menor, pero tras la clasificación de las meta_etiquetas, esto conlleva un retraso en la predicción, provocando que el EA suela entrar una vela tarde, lo que hace que la estrategia no sea efectiva. Recomiendo no utilizar esta estadística en MQL5, o intentar calcularla manualmente para que coincida con los mismos valores.

Saludos desde Brasil

¡Hola, gracias! Voy a comprobarlo.