隔壁老王的EA,怎么像是会"预判"行情?
上周跟一个做外汇的朋友吃饭,他跟我说了件事。
他的一个EA,在非农数据公布前15分钟,自动把仓位砍了一半。不是写死的规则,不是时间过滤器,是EA自己"判断"出来的。
我当时第一反应:这哥们接了ChatGPT的API?
他摇头,打开MetaEditor给我看。EA的文件夹里,除了.mq5源码,还躺着一个.onnx文件。
"机器学习模型,直接跑在MT5里面,不用联网,不用调API。"
我盯着那个文件看了三秒钟,决定回家研究一下。这篇文章,就是研究之后的结果。
ONNX到底是个什么东西?
先说人话。
你用Python训练了一个机器学习模型。可能用的TensorFlow,可能用的PyTorch,也可能用的Scikit-learn。三个框架,三种格式,互相不通。
ONNX就是一个"通用翻译器"。
全称Open Neural Network Exchange,开放神经网络交换格式。微软和Facebook在2017年搞出来的。不管你用什么框架训练模型,都可以导出成.onnx格式。然后任何支持ONNX的软件,都能直接加载运行。
打个比方:TensorFlow的模型是Word文档,PyTorch的模型是Pages文档,Scikit-learn的模型是WPS文档。ONNX就是PDF——谁都能打开。
关键是,MT5现在原生支持ONNX了。
MT5从什么时候开始支持ONNX的?
MetaTrader 5从build 3600开始,内置了ONNX Runtime。
这意味着什么?意味着你可以在MQL5代码里,直接加载一个.onnx模型文件,喂数据进去,拿预测结果出来。整个过程发生在MT5内部,不需要调用任何外部程序。
2026年MetaQuotes又往前走了一步:加入了GPU加速支持。如果你的电脑有NVIDIA显卡,ONNX模型的推理速度还能再快一个量级。
具体有多快?一个中等复杂度的模型,CPU推理大概需要200-500微秒。GPU加速之后可以压到50微秒以内。
50微秒是什么概念?你眨一下眼睛大概需要300毫秒,够这个模型跑6000次了。
对于EA来说,这个速度完全够用。每根K线来的时候跑一次推理,延迟基本可以忽略。
完整工作流长什么样?
整个流程分四步,我一步一步说。
第一步:在Python里训练模型。
你用Pandas处理历史数据,用Scikit-learn或者TensorFlow训练一个模型。这一步跟MT5没有任何关系,就是标准的机器学习流程。
第二步:把模型导出成.onnx文件。
Scikit-learn用skl2onnx库,TensorFlow用tf2onnx,PyTorch自带torch.onnx.export()。一行代码的事。
第三步:把.onnx文件放到MT5的数据目录。
具体路径是MQL5/Files/或者直接作为资源编译进EA。
第四步:在MQL5代码里加载模型,喂数据,拿结果。
用OnnxCreate()加载,OnnxRun()推理,OnnxRelease()释放。三个函数,搞定。
从训练到部署,一个下午就能跑通。当然,训练一个"好用"的模型,那是另一个故事了。
什么类型的模型可以塞进EA?
大致三类。
分类模型: 最直觉的用法。输入当前的技术指标数据,输出三个分类——买入、卖出、观望。随机森林、XGBoost、简单的神经网络,都可以干这个活。
回归模型: 预测具体的数值。比如输入过去20根K线的数据,预测下一根K线的收盘价。或者预测未来4小时的波动幅度。线性回归、LSTM、Transformer都能做。
异常检测模型: 这个比较高级。训练模型识别"正常"的市场状态,当市场行为偏离正常范围时,模型会报警。可以用来检测突发行情、流动性异常、或者价格操纵。Isolation Forest和Autoencoder是常用的选择。
我个人建议从分类模型入手。逻辑简单,效果直观,调试也方便。
手把手:从Python训练到EA部署
来,咱们走一遍最简单的例子。
目标:训练一个模型,根据RSI、MA偏离度、ATR三个特征,预测未来5根K线的方向(涨/跌)。
Python端——训练和导出:
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
# 假设你已经准备好了特征数据
# features: RSI(14), 价格与MA20的偏离百分比, ATR(14)归一化值
# label: 未来5根K线涨=1, 跌=0
X_train = np.array(features_train, dtype=np.float32)
y_train = np.array(labels_train)
# 训练随机森林
model = RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42)
model.fit(X_train, y_train)
# 导出为ONNX
initial_type = [('input', FloatTensorType([None, 3]))] # 3个特征
onnx_model = convert_sklearn(model, initial_types=initial_type)
with open("rf_signal.onnx", "wb") as f:
f.write(onnx_model.SerializeToString())
模型文件大概几百KB到几MB,取决于树的数量和深度。
MQL5端——加载和使用:
#resource "\\Files\\rf_signal.onnx" as uchar OnnxModel[]
long handle = INVALID_HANDLE;
int OnInit()
{
handle = OnnxCreate(OnnxModel, ONNX_DEFAULT);
if(handle == INVALID_HANDLE)
{
Print("ONNX模型加载失败");
return INIT_FAILED;
}
// 设置输入输出shape
ulong inputShape[] = {1, 3};
ulong outputShape[] = {1};
OnnxSetInputShape(handle, 0, inputShape);
OnnxSetOutputShape(handle, 0, outputShape);
return INIT_SUCCEEDED;
}
void OnTick()
{
// 计算特征
double rsi = iRSI(_Symbol, PERIOD_H1, 14, PRICE_CLOSE);
double ma = iMA(_Symbol, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE);
double atr = iATR(_Symbol, PERIOD_H1, 14);
double close = iClose(_Symbol, PERIOD_H1, 0);
// 准备输入数据
float inputData[3];
inputData[0] = (float)rsi;
inputData[1] = (float)((close - ma) / ma * 100);
inputData[2] = (float)(atr / close * 100);
// 推理
long prediction[1];
if(OnnxRun(handle, ONNX_NO_CONVERSION, inputData, prediction))
{
if(prediction[0] == 1)
Print("模型预测:看涨");
else
Print("模型预测:看跌");
}
}
void OnDeinit(const int reason)
{
if(handle != INVALID_HANDLE)
OnnxRelease(handle);
}
这是最精简的框架。实际使用中,你还需要加上特征的标准化处理、预测置信度过滤、仓位管理等等。但核心逻辑就是这些。
三个关键MQL5函数,记住就够了
OnnxCreate() —— 加载模型。可以从文件路径加载,也可以从编译进EA的资源加载。返回一个句柄(handle),后面所有操作都用这个句柄。
OnnxRun() —— 执行推理。把输入数据丢进去,模型算一遍,结果写到输出数组里。这个函数是同步的,调用完直接拿结果。第二个参数可以指定数据类型转换模式,一般用ONNX_NO_CONVERSION或者ONNX_DEFAULT。
OnnxRelease() —— 释放模型。EA卸载的时候调用,释放内存。忘了调这个不会崩溃,但会内存泄漏。
还有两个辅助函数经常用到:
OnnxSetInputShape() —— 设置输入张量的维度。必须跟你Python端导出时定义的一致。
OnnxSetOutputShape() —— 设置输出张量的维度。分类模型的输出通常是一个整数,回归模型的输出是一个浮点数。
说实话,API设计得挺简洁的。比起自己搞DLL调用Python那套方案,优雅了不止一点。
比起调API,本地跑模型好在哪?
很多人的第一反应是:我直接在EA里调OpenAI的API不行吗?
行,但问题不少。
延迟。 一次API调用,从发请求到拿结果,最快也要200-500毫秒。网络波动的时候可能飙到2-3秒。本地ONNX推理?50-500微秒。差了三个数量级。
稳定性。 API依赖网络。你的VPS网络抖一下,EA就卡住了。本地推理不需要网络,MT5开着就能跑。
成本。 API调用按次收费。每根K线来一次,一天下来几千次调用,账单会很好看。本地推理零成本,跑多少次都不要钱。
数据安全。 调API意味着你的交易数据、持仓信息要发到第三方服务器。本地推理所有数据都在你自己机器上,哪儿也不去。
离线能力。 断网了怎么办?API方案直接歇菜。本地ONNX模型该怎么跑还怎么跑。
唯一的劣势:本地模型是"静态"的。它只会你训练时教给它的东西。API背后的大模型知识面更广,还能持续更新。但对于量化交易这种需要确定性和低延迟的场景,本地模型的优势是压倒性的。
别高兴太早,ONNX方案有几个坑
模型会过时。 金融市场是非平稳的。你用2024年的数据训练的模型,到2026年大概率已经失效了。有些模型甚至几周就开始衰减。你需要定期用新数据重新训练,然后替换EA里的.onnx文件。
垃圾进,垃圾出。 这是机器学习的铁律。你的特征选得不好,数据清洗不到位,或者标签定义有问题,模型训练出来就是垃圾。ONNX只是一个部署工具,它不会让一个烂模型变好。
过拟合是大敌。 在历史数据上准确率99%?别激动,大概率是过拟合了。模型把历史数据的噪音都"背"下来了,一到实盘就翻车。一定要留足测试集,最好用Walk-Forward方法验证。
特征工程比模型选择重要10倍。 很多人纠结用随机森林还是XGBoost还是神经网络。其实用什么模型差别没那么大。真正决定效果的是你喂给模型的特征。RSI、MACD这些常规指标,信息量有限。你需要花大量时间研究什么样的特征能捕捉到市场的微观结构。
不要迷信复杂模型。 一个精心调参的随机森林,在很多场景下表现不输深度学习。而且随机森林训练快、不容易过拟合、推理速度也更快。先从简单模型开始,确认思路靠谱了再上复杂的。
对模型效果该有什么预期?
我说句大实话:如果有人告诉你,用机器学习模型做外汇交易可以稳定月化10%以上,他不是在骗你就是在骗自己。
机器学习在交易中的真正价值,不是"预测未来",而是"提升信号质量"。
什么意思?
假设你原来的EA基于均线交叉开仓,胜率是48%,盈亏比是1.5:1。加上一个训练得当的ONNX模型做信号过滤,胜率可能提升到52-55%。
别小看这几个百分点。在足够多的交易次数下,48%胜率和53%胜率的资金曲线差距是巨大的。前者可能缓慢亏损,后者可能稳定盈利。
机器学习擅长的是在大量数据中找到人眼看不到的统计规律。它不擅长预测黑天鹅事件,不擅长处理从未见过的市场状态,更不擅长保证每一笔交易都赚钱。
把它当成你交易系统里的一个"滤网"或者"评分卡",期望会合理很多。
常见问题
Q:我不会Python,能用ONNX吗?
严格来说,你需要Python来训练和导出模型。MQL5端的代码不复杂,但Python端的数据处理和模型训练是绕不过去的。好消息是,Python的机器学习入门门槛不高。Scikit-learn的文档写得非常好,跟着官方教程走,一两周就能上手基本操作。你不需要成为机器学习专家,能训练一个随机森林分类器就够起步了。
Q:模型多久需要重新训练一次?
没有标准答案,取决于你的策略和市场状态。保守建议:每个月用最近的数据重新训练一次。同时监控模型在实盘中的预测准确率,如果连续两周准确率明显下降,就该重新训练了。有些人搞自动化,写个Python脚本定期抓数据、训练、导出,然后手动替换EA里的模型文件。
Q:ONNX模型能在MT5策略测试器里回测吗?
可以。MT5的策略测试器完全支持ONNX推理。你可以像正常EA一样回测,模型会在每个tick或每根K线上执行推理。但要注意一个陷阱:如果你用2020-2025年的数据训练模型,然后用同一段数据回测,结果肯定漂亮得不真实。一定要确保训练数据和回测数据不重叠。
Q:一个EA里能同时跑多个ONNX模型吗?
可以。每个OnnxCreate()返回一个独立的句柄,你想加载多少个就加载多少个。比如一个模型负责判断趋势方向,另一个模型负责评估波动率,第三个模型负责过滤假信号。多模型协作的效果通常比单模型好,但也更复杂。建议先把一个模型跑通、跑稳,再考虑加第二个。
Q:模型文件太大会不会影响EA性能?
加载模型的时候会多花一点时间,但这只发生在EA初始化阶段(OnInit),不影响运行时性能。运行时推理速度主要取决于模型的计算复杂度,跟文件大小关系不大。一个50MB的随机森林和一个5MB的小型神经网络,推理速度可能差不多。一般来说,只要模型不超过200MB,都不会有问题。
总结一下,这条路值不值得走?
如果你已经有一个能跑的EA,想在不增加延迟和外部依赖的前提下提升信号质量,ONNX方案绝对值得研究。
它不是银弹,不会让一个烂策略起死回生。但它给了你一个把机器学习无缝嵌入交易系统的通道,成本低、速度快、稳定性好。
我的建议是:从最简单的开始。用Scikit-learn训练一个随机森林,三个特征,二分类。先跑通整个流程,再慢慢优化。
别一上来就搞LSTM、Transformer,那些东西对数据量和调参功夫的要求高得多。先把基础打好。
最后,如果你对MT5的进阶用法感兴趣,可以去FXTool看看,上面有不少关于MQL5开发和量化交易的实用内容。