Имхо конечно, но использование Савицкого_Голея не сильно отличается от использования мува. Фильтр СГ - это средняя точка полиномиальной регресии в заданном скользящем окне, с указанной степенью полинома. Для степени 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 removedreturn 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
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.
разберу подробнее - спасибо за статью! курю материал!
это замечательно: По итогу статьи можно будет обучать разные модели машинного обучения на языке Python и конвертировать их в торговые системы для торгового терминала МetaТrader 5.
разберу подробнее - спасибо за статью! курю материал!
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.
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.
Имхо конечно, но использование Савицкого_Голея не сильно отличается от использования мува. Фильтр СГ - это средняя точка полиномиальной регресии в заданном скользящем окне, с указанной степенью полинома. Для степени 1 - полное совпадение с мувом соответствующего периода.
Для идентификации возврата к среднему, более разумно, на мой взгляд, использовать амплитудную фильтрацию - ренко, ренджи, зигзаги. Лучше всего, я думаю,подходят рэнджи - у них разница между Hg и Lw - константа. Ну или ЗЗ постоянного размера, что в общем-то тоже самое.
Фурье и сингулярное разложение показывают себя неплохо в качестве фильтров. Не занимался подбором параметров, первые варианты.
Пример добавления экспоненциального затухания в процесс фильтрации, за основу взята самая первая функция разметки из статьи. Последним примерам придается бОльший вес в разметке, для подстройки под более свежие данные.
Для обучения на более коротких интервалах, например с 2018 по 2024 год, может получаться мало сделок, если в гиперпараметрах n_clusters = 10. Уменьшение количества кластеров, например до 5-3, помогает получить больше сделок.
Таким путем можно обучаться на более коротких временных промежутках и искать на них хорошие модели, варьируя различные параметры.
Еще можно уменьшать периоды фильтрации (фильтра Савицкого-Голея или сплайнов) сэмплеров сделок.
Thanks, I'll try to do something interesting and maybe useful in the future :)
это замечательно: По итогу статьи можно будет обучать разные модели машинного обучения на языке Python и конвертировать их в торговые системы для торгового терминала МetaТrader 5.
разберу подробнее - спасибо за статью! курю материал!
это замечательно: По итогу статьи можно будет обучать разные модели машинного обучения на языке 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
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