Обсуждение статьи "Cоздание стратегии возврата к среднему на основе машинного обучения" - страница 8

[Удален]  
sibirqk #:

Имхо конечно, но использование Савицкого_Голея не сильно отличается от использования мува. Фильтр СГ - это средняя точка полиномиальной регресии в заданном скользящем окне, с указанной степенью полинома. Для степени 1 - полное совпадение с мувом соответствующего периода. 

Для идентификации возврата к среднему, более разумно, на мой взгляд, использовать амплитудную фильтрацию - ренко, ренджи, зигзаги. Лучше всего, я думаю,подходят рэнджи - у них разница между Hg и Lw - константа. Ну или ЗЗ постоянного размера, что в общем-то тоже самое.   

Ну ЗЗ показал себя хуже.
[Удален]  

Фурье и сингулярное разложение показывают себя неплохо в качестве фильтров. Не занимался подбором параметров, первые варианты.


[Удален]  

Пример добавления экспоненциального затухания в процесс фильтрации, за основу взята самая первая функция разметки из статьи. Последним примерам придается бОльший вес в разметке, для подстройки под более свежие данные.

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. 
    """

    # Calculate smoothed prices using the Savitzky-Golay filter
    smoothed_prices = savgol_filter(dataset['close'].values, window_length=rolling, polyorder=polyorder)
    
    # Calculate the difference between the actual closing prices and the smoothed prices
    diff = dataset['close'] - smoothed_prices
    
    # Apply exponential weighting to the 'diff' values
    weighted_diff = diff * np.exp(np.arange(len(diff)) * decay_factor / len(diff)) 
    dataset['lvl'] = weighted_diff # Add the weighted difference as 'lvl'

    # Remove any rows with NaN values 
    dataset = dataset.dropna()
    
    # Calculate the quantiles of the 'lvl' column (price deviation)
    q = dataset['lvl'].quantile(quantiles).to_list() 

    # Extract the closing prices and the calculated 'lvl' values as NumPy arrays
    close = dataset['close'].values
    lvl = dataset['lvl'].values
    
    # Calculate buy/sell labels using the 'calculate_labels_filter' function 
    labels = calculate_labels_filter(close, lvl, q) 

    # Trim the dataset to match the length of the calculated labels
    dataset = dataset.iloc[:len(labels)].copy()
    
    # Add the calculated labels as a new 'labels' column to the DataFrame
    dataset['labels'] = labels
    
    # Remove any rows with NaN values
    dataset = dataset.dropna()
    
    # Remove rows where the 'labels' column has a value of 2.0 (sell signals)
    dataset = dataset.drop(dataset[dataset.labels == 2.0].index)
    
    # Return the modified DataFrame with the 'lvl' column removed
    return dataset.drop(columns=['lvl'])


  • В код добавлен параметр decay_factor (по умолчанию 0.95), который контролирует вес, придаваемый прошлым данным.
  • Для каждой точки данных мы рассчитываем вес, используя  np.exp(np.arange(len(diff)) * decay_factor / len(diff)), и умножаем его на значения diff.  Это придаёт больший вес недавним разницам и меньший вес - более старым. Взвешенный столбец 'lvl': Столбец lvl теперь хранит экспоненциально взвешенные разницы, что делает процесс разметки более чувствительным к недавним движениям цены.
  • Меньшее значение decay_factor (ближе к 0) сделает взвешивание более агрессивным, сильнее выделяя недавние изменения цен. Это означает, что алгоритм будет быстрее реагировать на недавние отклонения от сглаженного ценового тренда.
  • Большее значение decay_factor (ближе к 1) приведёт к более плавному взвешиванию, придавая большее значение прошлым данным. Это может быть полезно для уменьшения влияния краткосрочного шума и выявления долгосрочных трендов.
[Удален]  

Для обучения на более коротких интервалах, например с 2018 по 2024 год, может получаться мало сделок, если в гиперпараметрах n_clusters = 10. Уменьшение количества кластеров, например до 5-3, помогает получить больше сделок.

Таким путем можно обучаться на более коротких временных промежутках и искать на них хорошие модели, варьируя различные параметры.

Еще можно уменьшать периоды фильтрации (фильтра Савицкого-Голея или сплайнов) сэмплеров сделок.


 
Hello Max! I'm writing to say that I'm looking forward to articles by 'Maxim Dmitrievsky'. To study each article you post, I've been closely following your work for the past 2 years. I'm from Brazil, I study and learn something new and valuable.

I hope from the bottom of my heart that you, Maxim, continue sharing knowledge research and that the MetaQuotes team values you as a respected author and 'shares the profits' to encourage you to continue the amazing work. I hope you're the best, Maxim!

Please, @MetaQuotes and the @MetaQuotes @alexx  team , give this guy a raise! He deserves it <3

Greetings from Brazil
Maxim Dmitrievsky
Maxim Dmitrievsky
  • 2025.03.07
  • www.mql5.com
Профиль трейдера
[Удален]  
Vinicius Barenho Pereira #:
Hello Max! I'm writing to say that I'm looking forward to articles by 'Maxim Dmitrievsky'. To study each article you post, I've been closely following your work for the past 2 years. I'm from Brazil, I study and learn something new and valuable.

I hope from the bottom of my heart that you, Maxim, continue sharing knowledge research and that the MetaQuotes team values you as a respected author and 'shares the profits' to encourage you to continue the amazing work. I hope you're the best, Maxim!

Please, @MetaQuotes and the @MetaQuotes @alexx  team , give this guy a raise! He deserves it <3

Greetings from Brazil

Thanks, I'll try to do something interesting and maybe useful in the future :)

 

это замечательно: По итогу статьи можно будет обучать разные модели машинного обучения на языке Python и конвертировать их в торговые системы для торгового терминала МetaТrader 5.

разберу подробнее - спасибо за статью! курю материал!

[Удален]  
Roman Shiredchenko #:

это замечательно: По итогу статьи можно будет обучать разные модели машинного обучения на языке Python и конвертировать их в торговые системы для торгового терминала МetaТrader 5.

разберу подробнее - спасибо за статью! курю материал!

Пожалуйста, они иногда даже зарабатывают )
 

Hello Maxim,

I found an issue with the value generation in the get_features function in Python and in MetaTrader 5.

The problem lies in the "skew" statistic in Python and "skewness" in MQL5. From the tests I performed, the values generated by the two languages are slightly different. For example:

-0.087111
In MQL5, and
-0.092592
In Python

It may seem minor, but after the classification of the meta_labels, this leads to a delayed prediction, causing the EA to usually enter one candle late, which makes the strategy ineffective. I recommend not using this statistic in MQL5, or attempting to calculate it manually to match the same values.

Greetings from Brazil

[Удален]  
KleversonGerhardt #:

Hello Maxim,

I found an issue with the value generation in the get_features function in Python and in MetaTrader 5.

The problem lies in the "skew" statistic in Python and "skewness" in MQL5. From the tests I performed, the values generated by the two languages are slightly different. For example:

-0.087111
In MQL5, and
-0.092592
In Python

It may seem minor, but after the classification of the meta_labels, this leads to a delayed prediction, causing the EA to usually enter one candle late, which makes the strategy ineffective. I recommend not using this statistic in MQL5, or attempting to calculate it manually to match the same values.

Greetings from Brazil

Hi, thank you! I will check it.