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

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

(2/3)· 下载全量tick、做季节性切片、训ONNX,再看哪个周期真的把噪声滤干净了

含代码示例实战向 第 2/3 篇
很多交易者把ONNX模型直接塞进EA就跑,从没怀疑过喂给模型的时间周期本身带了多少季节噪声。用错周期,深度学习学到的不是规律而是日历幻觉,回测好看实盘照样被扫。

连续报价间隔里的自相关有多强

自相关衡量的是同一序列在不同时间间隔上的相似度,值越靠近 1,说明前后时段的数值越像、惯性越明显。对外汇和贵金属这种高波动品种,先看自相关再谈策略,能少踩很多坑——这类品种杠杆高,惯性误判可能直接放大亏损。 下面这组从分钟级报价里算出的自相关系数,前 36 个滞后阶全部高于 0.9:首阶 0.99736,第 10 阶还有 0.97356,到第 36 阶降到 0.90826。这种衰减极慢的形态,说明短期价格记忆很强,均值回复类手法在裸跑时大概率会被趋势拖垮。 真要验证你手上的货币对,别只看 EURUSD,把 XAUUSD 也拉进来自算一遍,黄金的自相关结构和币种常常不是一回事。

MQL5 / C++
[<span class="number">class="num">1</span>.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="number">class="num">0.99736147</span> <span class="number">class="num">0.99472432</span> <span class="number">class="num">0.99206626</span> <span class="number">class="num">0.98937664</span> <span class="number">class="num">0.98671649</span>
 <span class="number">class="num">0.98405706</span> <span class="number">class="num">0.98144222</span> <span class="number">class="num">0.9787753</span>&nbsp;&nbsp;<span class="number">class="num">0.97615525</span> <span class="number">class="num">0.97356318</span> <span class="number">class="num">0.97099777</span>
 <span class="number">class="num">0.96848029</span> <span class="number">class="num">0.96602671</span> <span class="number">class="num">0.96360361</span> <span class="number">class="num">0.96113539</span> <span class="number">class="num">0.95865344</span> <span class="number">class="num">0.95615626</span>
 <span class="number">class="num">0.95362417</span> <span class="number">class="num">0.95108177</span> <span class="number">class="num">0.94854957</span> <span class="number">class="num">0.94599045</span> <span class="number">class="num">0.94346076</span> <span class="number">class="num">0.94091564</span>
 <span class="number">class="num">0.93837742</span> <span class="number">class="num">0.93583734</span> <span class="number">class="num">0.9332909</span>&nbsp;&nbsp;<span class="number">class="num">0.93074655</span> <span class="number">class="num">0.92826504</span> <span class="number">class="num">0.92579028</span>
 <span class="number">class="num">0.92330505</span> <span class="number">class="num">0.92084645</span> <span class="number">class="num">0.91834403</span> <span class="number">class="num">0.91581296</span> <span class="number">class="num">0.91328091</span> <span class="number">class="num">0.91076099</span>
 <span class="number">class="num">0.90826447</span>]

「把二月行情压成一个可训练的CSV」

做二月的 ONNX 模型,第一步不是直接训网络,而是先把分散的季节性数据并成一张表。用 concat_seasonal.py 把各来源数据拼进 seasonal_feb_concat.zip 里的单一 CSV,这一步没做对,后面 LSTM 读到的是错位样本。 训练侧调用 onnx_LSTM_simple_EURUSD_concat_seasonals.py,它直接吃上面那份合并 CSV,产出可用于 MT5 推理的 ONNX 权重。欧元兑美元属高杠杆品种,模型在样本外仅代表概率倾向,实盘前务必用历史数据回测验证过拟合程度。 附带的 create_concat_seasonal_data.py 是合并逻辑的可复现脚本,改路径就能套到别的月份。开 MT5 前先确认 CSV 行数与脚本日志一致,否则 ONNX 初始化会报维度错。

◍ 季节性模型跑分:负夏普占比只有五分之一

把季节性模型单独拉出来看,整体表现谈不上惊艳,但胜在稳。在回测表格里,夏普比率为负的品种并不多,和带 120 天(1 小时)过滤的模型放一起对比更有意思:过滤模型优化结果里约一半是负夏普,季节性模型里负夏普只占大概五分之一。 值得老手留意的是,季节性模型即便 r2 只有 0.72 上下,看上去解释力一般,却更倾向产出正回报,属于低 r2 高鲁棒的那一类。我没去测去掉止损止盈的版本,实盘里 EA 始终挂 SL/TP 更不容易被极端跳空洗掉。 附在下面的 ONNX 模型和 mq5 源文件可直接拖进 MT5 跑 EURUSD H1 验证。关键拟合指标如下,R2 卡在 0.7167,RMSE 约 0.0131,样本内误差可控。 外汇与贵金属杠杆高、滑点跳空频繁,上述回测不代表未来概率,复制前先开 MT5 用历史中心数据重跑一遍。

MQL5 / C++
RMSE         : class="num">0.013137568368684325
MSE          : class="num">0.00017259570264185493
R2 score     : class="num">0.7166764010650979

周期拉长,结果更稳

EURUSD 上把过滤器微调后,策略按周期做了分段回测:1小时跑的是 2024 年 2 月整月,30分钟只跑 2 月 1 日至 15 日,15分钟则分带过滤器与不带过滤器两组对照。带过滤的 15分钟用了 LSTM.15m.EURUSD.120.0.98.onnx 配合 ONNX.eurusd.H1.120.15m_eurusd.mq5,30分钟与 1小时均切到 LSTM.30m.EURUSD.120.0.94.onnx 并固定启用过滤器。 对比下来,15分钟加过滤器在夏普比率上整体优于裸跑;而 2天周期不可直接用,便退到 1天周期给 EA 喂后续天数的值,2小时文件单独打包(2h.zip),超过 32 个文件的部分只能塞进文件夹上传。 一个明显倾向是:周期越大,各档 TP 与 SL 组合下的净值曲线越不容易塌。外汇与贵金属属高风险品种,这种稳健只是概率层面的回测现象,实盘仍可能背离。 下面这段是过滤器本身的低通处理,cutoff 取 0.1(相对奈奎斯特频率的比例),order=1,先 MinMax 缩放到 0~1 再走 butter 低通,最后反缩放回价格量纲。

MQL5 / C++
cutoff_frequency = class="num">0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist
order = class="num">1
from sklearn.preprocessing class="kw">import MinMaxScaler
from scipy.signal class="kw">import butter, lfilter
# Parámetros del filtro pasa bajo
cutoff_frequency = class="num">0.1  # Frecuencia de corte en proporción a la frecuencia de Nyquist
order = class="num">1
# Aplicar filtro pasa bajo
def butter_lowpass_filter(data, cutoff, fs, order):
    nyquist = class="num">0.5 * fs
    normal_cutoff = cutoff / nyquist
    b, a = butter(order, normal_cutoff, btype=&class="macro">#x27;low&class="macro">#x27;, analog=False)
    print("Coeficientes del filtro - b:", b)
    print("Coeficientes del filtro - a:", a)
    y = lfilter(b, a, data)
    class="kw">return y
scaled = MinMaxScaler(feature_range=(class="num">0,class="num">1))
valores_df1 = df.filter([&class="macro">#x27;close&class="macro">#x27;]).values
valores_df1 = pd.DataFrame(valores_df1)
x_features1 = valores_df1[[class="num">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=class="num">1, order=order)
print("filtered_data_low",filtered_data_low)
filtered_data_low_unscaled = scaled.inverse_transform(filtered_data_low)
把tick下载和切片交给小布
这些诊断小布盯盘的AIGC已内置,打开对应品种页即可看到季节性波动带与周期噪声提示,你把Python脚本跑完的CSV丢进去就能直接比对,不必自己手画滤波区间。

常见问题

把文内的全量变动下载脚本挂到目标品种图表,不到一小时会在该品种文件目录生成CSV,之后用Python按日期截取所需区间即可。
可以,小布的品种页已内置季节性带与周期对照,你导入自己训好的模型预测序列就能直观看到哪段被季节噪声带偏。
二月存在独立的节日与天气季节性结构,全年模型会把其他月份模式混进来,单独切片训练更可能捕捉到该月可重复的规律。
120天过滤按滑动窗口去趋势,季节性过滤按日历锚定重复区间,前者看近期结构后者看年历结构,文中用同EA对比了两者收益曲线。