English Русский Español Deutsch 日本語 Português
preview
利用Python进行季节性过滤并为EA的ONNX深度学习模型选择时间周期

利用Python进行季节性过滤并为EA的ONNX深度学习模型选择时间周期

MetaTrader 5EA交易 | 4 十一月 2024, 14:32
340 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

简介

在阅读了《利用外汇市场季节性因素获利》一文后,我决定撰写另一篇文章,对比加入季节性因素与未加入季节性因素的交易策略(Expert Advisor,简称EA),以探究季节性因素是否能带来优势。 

我早已知晓市场会受到季节性因素的影响。当我了解到马克·扎克伯格用一位投资者的资金为Facebook提供资金时,这一点变得尤为明显。这位投资者曾用他在Bar Mitzvah(犹太男孩13岁时的成年礼)收到的钱投资石油股票,预测加勒比海地区预期的飓风会导致油价上涨。他分析了天气预报,指出那段时间将有恶劣天气。

我非常自豪且有兴趣撰写这篇文章,旨在探讨市场和季节性因素是相互关联的。将两者结合起来的一个好方法是将它们融入一个EA中,但我们已经有一篇关于此的文章,链接如下:如何在mql5中集成ONNX模型的示例

首先,我们将使用EA对比有数据过滤和无数据过滤的模型,以观察数据过滤是否会产生影响。之后,我们将通过图表讨论季节性因素,并以2024年2月为例,展示加入和未加入季节性因素的实际效果。在文章的最后部分(我认为非常有趣),我们将讨论对已有EA的其他方法:如何在MQL5中使用ONNX模型,并探讨我们是否可以通过微调这些EA和ONNX模型来获得优势。我现在就可以告诉你,答案是肯定的,我们可以。

为了实现这一目标,我们将首先使用以下脚本下载数据(所有价格变动):从某个交易品种下载所有数据。我们只需将该脚本添加到需要研究的交易品种图表上,一段时间后(不到一小时),我们就能在该交易品种的“文件”文件夹中下载到所有历史价格变动数据。

当我们下载完所有价格变动数据后,我们将处理该CSV文件,并仅提取我们所需或想要的数据(在本例中,为2015年1月至2023年2月期间的数据)。


季节性

交易中的季节性主要是指识别资产价格在一年中可预测地发生的规律性起伏。这就像认识到某些股票在特定时间往往表现更好一样。让我们来详细探讨一下这个概念。

理解交易中的季节性:

  • 定义:季节性是指注意到价格如何根据一年中的时间以重复的模式波动。这可能与实际季节(如夏季或冬季)、商业季节(如节日购物旺季)甚至特定月份有关。
  • 示例:聪明的投资者会关注这些模式,因为它们通常可靠且有利可图。以下是几个例子:
    • 与天气相关的季节性:就像天气影响农作物的生长季节一样,它也影响着商品价格和相关股票。例如,一家销售海滩装备的公司可能在夏季销量大增,但在较冷的月份销量下降,从而影响其股价。
    • 节日季节性:零售股在节日购物热潮期间通常会上涨。那些依赖节日销售的公司,如礼品店,往往在这段时间内表现出色。
    • 季度收益季节性:上市公司每季度公布收益,而这些季节期间其股价的反应往往是可预测的。
    • 税收季节性:与税收相关的事件可能会扰乱市场,特别是对于那些与金融相关的行业。
    • 自然周期:像旅游或能源等行业有自己的季节性需求模式,如夏季度假或冬季供暖需求。

基于季节性的交易策略:

  • 交易者可以通过以下几种方式利用季节性:
    • 识别季节性模式:深入研究过去的数据,以发现一年中重复出现的趋势。
    • 把握交易时机:根据这些季节性趋势进行买卖操作。
    • 把握交易时机:根据这些季节性趋势进行买卖操作。
    • 板块轮动:在一年中不同时间表现更好的板块之间进行投资切换。


过滤数据

我们采用低通滤波器。根据维基百科:

低通滤波器是一种滤波器,它允许频率低于选定截止频率的信号通过,并衰减频率高于截止频率的信号。滤波器的确切频率响应取决于滤波器的设计。在音频应用中,该滤波器有时被称为高频消减滤波器或高音削减滤波器。低通滤波器是高通滤波器的互补滤波器。

在算法交易中,我们为什么选择低通滤波器而不是高通滤波器?算法交易中对低通滤波器的偏好源于以下几个关键优势:
  1. 信号平滑:低通滤波器能够有效地平滑掉价格波动中的噪声波动,强调长期趋势而非短期波动。
  2. 减少高频噪声:它们有助于衰减高频噪声,这些噪声对于交易策略可能不提供有意义的信息。
  3. 降低交易成本:通过关注长期趋势,低通滤波器可以导致更少、更具战略性的交易,从而可能降低交易成本。
  4. 更好的风险管理:低通滤波器有助于制定更稳定、可预测的交易策略,减少短期市场波动的影响。
  5. 与投资期限相符:它们非常适合具有长期投资期限的策略,能够有效地捕捉长期趋势。

我个人使用低通滤波器来过滤高频信号。在这里使用高通滤波器没有太多意义。

这是我们将要使用的(注:我在文章最后一部分将顺序(order)和截止频率(cutoff_frequency)参数更改为0.1的截止频率和顺序等于1,因为这样的设置最终给出了更好的结果。此外,用于滤波的正确.py文件是文章最后一部分中提到的那些(在那里,我不仅使用了更好的参数,还使用了minmaxscaler进行拟合和逆变换)。

# Low-pass filter parameters
cutoff_frequency = 0.01  # Cutoff frequency as a proportion of the Nyquist frequency
order = 4

# Apply the low-pass filter
def butter_lowpass_filter(data, cutoff, fs, order):
    nyquist = 0.5 * fs
    normal_cutoff = cutoff / nyquist
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    print("Filter coefficients - b:", b)
    print("Filter coefficients - a:", a)
    y = lfilter(b, a, data)
    return y

filtered_data_low = butter_lowpass_filter(df2['close'], cutoff_frequency, fs=1, order=order)

我们将使用“onnx_LSTM_simple_filtered.py”和“onnx_LSTM_simple_not_filtered.py”来制作ONNX模型并进行比较。

注意:我使用了具有不同低通滤波器参数的模型v1和模型v2。

结果如下:

我们对这些EA采用相同的输入参数

输入

输入2

研究的时间段将从2月1日到3月1日。

对于未经过滤的模型:

RMSE         : 0.0010798043714784716
MSE          : 1.165977480664017e-06
R2 score     : 0.8799146678247277

无过滤


过滤 v1

# Parámetros del filtro pasa bajo

cutoff_frequency = 0.01  # Frecuencia de corte en proporción a la frecuencia de Nyquist

order = 4


RMSE         : 0.0010228999869332884
MSE          : 1.0463243832681218e-06
R2 score     : 0.8922378749062259


过滤 v1


过滤 v2

cutoff_frequency = 0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist

order = 2

RMSE         : 0.0010899163515744447
MSE          : 1.1879176534293484e-06
R2 score     : 0.8775550550819025

过滤 v2


关于过滤的结论

仅当使用正确的参数时,过滤才会产生更好的结果。

因此,没错。使用过滤是很方便的。

使用的代码和模型:


货币对们有季节性规律吗?

对于这一部分,我们首先将通过图表来观察,我们将获取从2015年至2023年2月份的数据,并将其添加到图表中,以查看这些数据在那些周如何波动。

这是我们在那个时间段内可以观察到的:

2月份总和

结论:

我们可以看到它有一些趋势,或者至少我们没有看到一条水平的黑线(总和线)。每条线之间都有间隔,因为该符号全年都在交易,其价格会波动。这就是为什么在文章的下一部分中,我们将按年份将所有货币对的2月份数据连接起来,并且这就是为什么我们需要使用过滤器的原因。过滤器可以防止高频数据(例如,从2022年的最后一天到2023年2月的第一天)的传递,并且当AI训练时(例如,训练星期五的收盘价和星期一的开盘价),它不会研究这些变化,而是寻求更平滑的数据。

使用的脚本和数据:


这些货币对的数据之间有相关性吗?

自相关是数据的一种特性,它显示了连续时间间隔内数值之间的相似程度。

接近1的值表示存在很大的正相关。

以下是我们使用autocorrelation.py获得的结果。

[1.         0.99736147 0.99472432 0.99206626 0.98937664 0.98671649
 0.98405706 0.98144222 0.9787753  0.97615525 0.97356318 0.97099777
 0.96848029 0.96602671 0.96360361 0.96113539 0.95865344 0.95615626
 0.95362417 0.95108177 0.94854957 0.94599045 0.94346076 0.94091564
 0.93837742 0.93583734 0.9332909  0.93074655 0.92826504 0.92579028
 0.92330505 0.92084645 0.91834403 0.91581296 0.91328091 0.91076099
 0.90826447]


为二月创建ONNX模型

对于这项任务,我们只需将所有数据合并到一个CSV文件中,并用它来创建一个模型。

我们将使用创建的concat_seasonal.py脚本来生成一个CSV文件,该文件将被添加到zip文件seasonal_feb_concat中。然后,我们将使用onnx_LSTM_..._seasonals.py脚本来训练和创建模型。

使用的脚本和数据(全部附在下面):


季节性模型的测试结果以及与120天(1小时)过滤模型的比较。

季节性模型

RMSE         : 0.013137568368684325
MSE          : 0.00017259570264185493
R2 score     : 0.7166764010650979

尽管并不惊人,但总体来看结果还不错(夏普比率为负值的并不多)。

夏普比率

夏普比率2

季节性优化


如果我们把它同带过滤的模型相比较,

带过滤的夏普比率

带过滤的夏普比率2d

过滤优化


我发现一个有趣的现象是,在过滤模型的优化结果中,负夏普比率值占据了表格的一半,而在季节性模型中,负夏普比率值只占据了表格的五分之一左右。这一点值得注意,因为即使r2值较低,它似乎也是一个能够产生盈利回报的稳健模型。

我本来也可以测试不使用止损(SL)和止盈(TP)的EA,但我认为在EA中始终使用它们是一种更好的做法。


所使用的代码和ONNX模型(均附于下方):

ONNX.eurusd.H1.120.Prediction_seasonal.mq5 EURUSD_LSTM_270_1h_filtered_seasonal0.72.onnx onnx_LSTM_simple_EURUSD_concat_seasonals.py



使用什么时间周期呢?

对于文章的这一部分,我已经对过滤器进行了微调,以使其对EURUSD产生更好的结果。

cutoff_frequency = 0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist
order = 1

我还修改了过滤器:

from sklearn.preprocessing import MinMaxScaler
from scipy.signal import butter, lfilter

# Parámetros del filtro pasa bajo
cutoff_frequency = 0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist
order = 1

# Aplicar filtro pasa bajo
def butter_lowpass_filter(data, cutoff, fs, order):
    nyquist = 0.5 * fs
    normal_cutoff = cutoff / nyquist
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    print("Coeficientes del filtro - b:", b)
    print("Coeficientes del filtro - a:", a)
    y = lfilter(b, a, data)
    return y

scaled = MinMaxScaler(feature_range=(0,1))

valores_df1 = df.filter(['close']).values
valores_df1 = pd.DataFrame(valores_df1)
x_features1 = valores_df1[[0]]
valores_df2 = x_features1.values


data_escalada = scaled.fit_transform(valores_df2)

print(data_escalada)

filtered_data_low = butter_lowpass_filter(data_escalada, cutoff_frequency, fs=1, order=order)
print("filtered_data_low",filtered_data_low)

filtered_data_low_unscaled = scaled.inverse_transform(filtered_data_low)

订单的价格必须四舍五入到整数。
该策略针对1小时的时间间隔,在2024年2月进行了为期一个月的测试。对于30分钟的时间间隔,测试从2月1日至2月15日进行,以此类推。

对于15分钟的时间间隔,我分别进行了有过滤器和无过滤器的测试。结果表明,使用经过微调的过滤器可以获得更好的结果(至少是总体上的)。

15分钟带过滤器(夏普比率)

15分钟带过滤器的测试


测试器 2d 15 min

测试15分钟带过滤器


LTSM_simple_15m_filtrado.py LSTM.15m.EURUSD.120.0.98.onnx ONNX.eurusd.H1.120.15m_eurusd.mq5


15分钟不带过滤器

15分钟不带过滤器的测试

2d 15分钟不带过滤器

15分钟带过滤器的测试

LTSM_simple_15m_filtrado_sin.py LSTM.15m.EURUSD.120.0.98.onnx ONNX.eurusd.H1.120.15m_eurusd.mq5


30分钟带过滤器(现在开始我将一直使用过滤器)

30分钟测试器

30分钟测试器 2d

测试30分钟周期


LSTM.30m.EURUSD.120.0.94.onnx
LTSM_simple_30m_filtrado.py ONNX.eurusd.H1.120.30m_eurusd.mq5


1小時

1小时的测试

1小时测试的热力图

1小时的测试


1 hour files.zip (815.64 KB)


2 小时

由于我不能使用2天的时间周期,我使用一天的周期(用于EA中接下来几天的值)。

测试器 2小时h

2小时热力图

2小时的测试

2小时图形

在2小时上回测


2h.zip

我无法加载超过32个文件,剩下的文件将打包在文件夹中上传。


结论

似乎使用这种策略时,随着时间周期的加大,对于所有盈利水平(TPs)和止损水平(SLs)来说,结果看起来更加稳健。


NextDays变量

我采用了这篇文章中的策略:如何在mql5中使用ONNX模型5,但由于我在使用2小时策略时取得了不错的结果,并且在该策略中我使用了1天周期接下来,我们将研究“NextDays”变量的其他取值。

   if(TimeCurrent()>=ExtNextDay)
     {
      GetMinMax();
      //--- set next day time
      ExtNextDay=TimeCurrent();
      ExtNextDay-=ExtNextDay%PeriodSeconds(PERIOD_D1);
      ExtNextDay+=PeriodSeconds(PERIOD_D1);
     }
void GetMinMax(void)
  {
   vectorf close;
   close.CopyRates(_Symbol,PERIOD_D1,COPY_RATES_CLOSE,0,SAMPLE_SIZE);
   ExtMin=close.Min();
   ExtMax=close.Max();
  }

我们现在将研究使用30分钟周期和过滤数据的EURUSD,并尝试不同的NextDay周期(我们将使用1天、12小时和6小时),然后讨论结果。

1天30分钟周期

1D 30min

1D heatmap 30min

1D tests


12小时30分钟周期

12h 30 min tests

12h heatmap

12h tests 30 min


6小时30分钟周期

6小时30分钟周期

6h heatmap 30 min period

h6 30 min tests


当微调NextDay变量后结果看上去更好。让我们看看在较短的NextDay周期变量下情况如何。

NextDay为4小时的30分钟周期

4h periods

4h period heatmaps

tests 4h periods


NextDay为2小时的30分钟周期

30 min 2 h periods

30 min 2h nextday periods heatmap

2h period tests


NextDay为1小时的30分钟周期

h1 periods 30 min

h1 heatmap 30 min

tests 1h 30 min


看起来,在至少30分钟的周期内,大约8到12个30分钟的K线(或称为柱形图)能给出更好的结果。


由于这个“游戏”的目的是赢得更多的钱,而实现这一目标的方法之一就是拥有更多的盈利交易和一个稳健的策略。让我们看看是否可以利用这个起点,在5分钟的周期内获胜。因此,我们将尝试这个策略,将NextDay变量的周期设置为5分钟、1小时和30分钟。

输入

NextDay变量为1小时的5分钟周期

tester 1 h (5 min period)

heatmap 1h (5 min period)

results test 1h (5 min)



NextDay变量为30分钟的5分钟周期

tester 30 min (5 min)

heatmap 30 min (5 min)

testing 30 min (5 min)

文件:Last files.zip

其他时间周期似乎更加可靠,但是,如果你想要另一个EA,你有更多的选择可以使用。


最后,我们可以对策略进行调整,以期获得更好的结果或更稳定的结果。例如,在1小时的周期内,我们可以设定时间或K线数量的限制。对于使用次日12小时周期,我们可以规定一旦订单成交,持有时间不得超过12小时。

   if(ExtPredictedClass>=0)
     {
      if(PositionSelect(_Symbol))
         CheckForClose();
      else
        {
         CheckForOpen();
         started_time1 = rates[0].time;
         string started_time1_str = TimeToString(started_time1);
int total = PositionsTotal();
   if(total>0)
     {
      datetime started_time2 = rates[0].time;
      string started_time2_str = TimeToString(started_time2);
      int segundos = started_time2 - started_time1;
      Print("Tiempo 1: ", started_time1_str);
      Print("Tiempo 2: ", started_time2_str);
      Print("Diferencia en segundos: ", segundos);
      if((segundos >= days*PeriodSeconds(PERIOD_H12)) && segundos != 0)
        {
         Print("closing position----------------");
         ExtTrade.PositionClose(_Symbol,3);

        }
     }

测试器

热力图

测试

图形


ONNX.eurusd.120.1h_H12_eurusd.v3.mq5
 (9.23 KB)


结论

我们已经进行了调整、筛选和模型对比,尝试了不同的EA和参数设置,试图通过微调来获得更好的结果。我希望你阅读这篇文章时感到愉快,就像我撰写它时一样享受这个过程。 


本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/14424

种群优化算法:人工多社区搜索对象(MSO) 种群优化算法:人工多社区搜索对象(MSO)
这是上一篇研究社群概念文章的延续。本文使用迁徙和记忆算法探讨社群的演化。结果将有助于理解社区系统的演化,并将其应用于优化和寻找解。
种群优化算法:鲸鱼优化算法(WOA) 种群优化算法:鲸鱼优化算法(WOA)
鲸鱼优化算法(WOA)是一种受座头鲸行为和捕食策略启发的元启发式算法。该算法的核心思想在于模仿所谓的“气泡网”捕食方法,即鲸鱼在猎物周围制造气泡,然后以螺旋运动的方式攻击猎物。
练习开发交易策略 练习开发交易策略
在本文中,我们将尝试开发自己的交易策略。任何交易策略都必须以某种统计优势为基础。而且,这种优势应该长期存在。
开发多币种 EA 交易 (第 5 部分):可变仓位大小 开发多币种 EA 交易 (第 5 部分):可变仓位大小
在前面的部分中,我们正在开发的智能交易系统 (EA) 只能使用固定的仓位大小进行交易。这对于测试来说是可以接受的,但在真实账户交易时并不建议这样做。让我们能够使用可变的仓位大小进行交易。