使用MQL5和Python构建自优化EA(第二部分):调整深度神经网络(基础篇)
◍ 用MQL5+Python给DNN调参起手
想让深度神经网络在MT5里真正跑顺,第一步不是堆层数,而是把MQL5的信号提取和Python的训练闭环打通。原文示例发布于2025年2月26日,截至发稿被查看1175次,说明这类自优化EA的实操需求在交易圈并不冷门。 具体路径是:MQL5端负责行情抓取与特征构造,Python端用scikit-learn或PyTorch做网络权重更新,再把结果回写EA参数。外汇与贵金属杠杆高、滑点跳变频繁,这套链路里任何一段延迟都可能让训练样本偏离实盘分布,概率上会造成过拟合。 建议直接开MT5建一个测试EA,先只传RSI和ATR两个序列去Python,验证socket通了再扩特征,比一上来就喂几十维数据更稳。
「为什么默认 AI 参数在外汇里常失灵」
把通用 AI 模型直接丢进 MT5 做贵金属或外汇,多数时候只是凑合跑。模型内部有一组可调超参,它们对行情适应度影响很大;在震荡 EURUSD 上表现不错的数值,放到 XAUUSD 趋势段可能直接退化。 社区里做策略的人早就发现,针对单一品种调参比换模型更划算。本文后续会用 Nelder-Mead 这类无梯度优化算法,基于 MT5 终端拉到的真实报价去微调深度网络,再把权重导成 ONNX 给 EA 调用。 外汇与贵金属杠杆高、跳空频繁,任何参数优化都只是提升概率,不保证样本外稳定。新手若看不懂优化步骤,文中会拆开讲清楚每一步在终端里怎么落。
不用求导也能搜最优:Nelder-Mead 的单纯形玩法
Nelder-Mead 是 1965 年由 John Nelder 与 Roger Mead 在《函数最小化的单纯形法》里提出的模式搜索法,专门对付噪声大、不可微分、非线性的多模态优化问题。它对 EA 参数寻优很实用:不依赖任何导数信息,只靠几何形状的变形在参数空间里瞎探。 算法核心是一个叫单纯形(simplex)的几何体。维度规则很死:顶点数 = 输入变量数 + 1。比如调 3 个参数,单纯形就是 4 个顶点;每个顶点对应一组参数,算完目标函数后按固定规则挪点、缩边、翻面。 最大坑在起始点。给定单一起点,算法极可能掉进局部最优的陷阱。实测中换 5~10 个不同起点各跑一遍,命中全局较优解的概率明显更高。停止条件通常是达到最大迭代次数,或相邻评估值变化低于阈值——没改进就停,不会无限跑。 外汇与贵金属市场高风险,参数回测优解不预示实盘表现,开 MT5 用多起点跑完务必做样本外验证。
◍ 把调好的神经网络塞进 MT5 的 ONNX 通道
从 MT5 终端导出的 CSV 只是起点。在上下文菜单点「符号」→「柱形图」搜到品种后导出的数据,配合下面这段代码就能在 Python 里打标签、做时序交叉验证,再转成 ONNX 给 MQL5 调用。
[CODE] 段里的 brent["Target"] = brent["Close"].shift(-look_ahead) 用 20 根 K 线后的收盘价当标签,look_ahead=20 是硬参数;TimeSeriesSplit(n_splits=5,gap=20) 把数据切成 5 段、段间空 20 根防泄露。直接抄去改路径就能跑。
超参数寻优那一轮,Nelder-Mead 因 nfev=600 触发「Maximum number of function evaluations has been exceeded」,最终 fun: 0.1202,x 落在 [0.7575, 0.3577, 0.2621]。由于目标函数内含 5 折交叉验证,600 次评估等于把神经网络拟合了 3000 次,单轮优化耗时 1332.99 秒——真机跑之前先掂量 CPU。
同数据集上定制模型对比默认模型,前 10 次 CV RMSE 里定制模型有多组低于 0.55、默认模型却出现 82.18 这类爆炸值;但两者共用训练集评估,结论只能说定制网络「倾向」更稳,不能当泛化证明。外汇与贵金属数据噪声大,实盘前务必拆训练/测试集重测。
转 ONNX 后用 Netron 看元数据:输入 float_input 形状 [1,4] 对应 Open/High/Low/Close,输出 variable 形状 [1,1] 即未来价位预测。确认完形状,MQL5 侧就能用 ONNX 推理接口接这个文件,不必重训。
class="macro">#class="kw">import libraries we need class="kw">import pandas as pd class="kw">import numpy as np from numpy.random class="kw">import randn,rand class="kw">import seaborn as sns class="macro">#Read in our market data brent = pd.read_csv("/home/volatily/market_data/Market Data UK Brent Oil.csv", sep="\t") class="macro">#Preparing to label the data look_ahead = class="num">20 class="macro">#Defining the target brent["Target"] = brent["Close"].shift(-look_ahead) class="macro">#Drop missing values brent.dropna(inplace=True) class="macro">#In this article we will cover some techniques for hyper-parameter tuning from scipy.optimize class="kw">import minimize from sklearn.neural_network class="kw">import MLPRegressor from sklearn.model_selection class="kw">import TimeSeriesSplit from sklearn.metrics class="kw">import root_mean_squared_error class="kw">import time class="macro">#Define the time series split parameters splits = class="num">5 gap = look_ahead class="macro">#Create the time series split object tscv = TimeSeriesSplit(n_splits=splits,gap=gap) class="macro">#Create a dataframe to store our accuracy current_error_rate = pd.DataFrame(index = np.arange(class="num">0,splits),columns=["Current Error"]) class="macro">#Define the predictors and the target predictors = ["Open","High","Low","Close"] target = "Target" class="macro">#Define the objective function def objective(x): class="macro">#The parameter x represents a new value for our neural network&class="macro">#x27;s settings class="macro">#In order to find optimal settings, we will perform class="num">10 fold cross validation using the new setting class="macro">#And class="kw">return the average RMSE from all class="num">10 tests class="macro">#We will first turn the model&class="macro">#x27;s Alpha parameter, which controls the amount of L2 regularization model = MLPRegressor(hidden_layer_sizes=(class="num">5,class="num">2),alpha=x[class="num">0],early_stopping=True,shuffle=False,learning_rate_init=x[class="num">1],tol=x[class="num">2]) class="macro">#Now we will cross validate the model for i,(train,test) in enumerate(tscv.split(brent)): class="macro">#The data