用 Simulink 为 EA 做模型驱动开发:MATLAB 到 MQL5
为什么用 Simulink 做模型驱动开发
作者自述“不是专业程序员”,核心诉求是把交易系统的逻辑先用框图可视化,再尽量少手写代码地转成 MQL5。Simulink(MATLAB 的建模包)让你拖块连線表达“指标计算→信号判定→下单动作”,逻辑一目了然;当系统要加新条件时,看框图比读几百行代码更清晰。
现实流程:模型→手动翻译,而非一键生成
必须澄清:本文并不是“点一下就吐出 MQL5”的自动代码生成。Simulink 负责建模与历史回测,之后作者把框块/状态机逻辑手动翻译成 MQL5 代码。文中用到 Simulink 库浏览器、Model Explorer、Bus Editor(定义 InputBus/OutputBus 虚拟总线)、Stateflow(画状态机),以及 mex -setup 选编译器做加速仿真,但并未用 Embedded Coder/TLC 直接产出 MQL5。
模型里如何表达指标、信号、下单
MATLAB 端用 movavg 算 EMA: [ema21,ema55]=movavg(close,21,55,'e')。Simulink 里用 FromWorkspace 把价格/EMA 打包成 Bus;emas 微分块(Add 设 +−)算两线差值;K Delay 块延迟 K=3 根;Stateflow Chart 定义 Buy/Sell 事件(Falling/Rising 触发),在 Position handling 子系统里转成 OpenBuy/OpenSell 调用,设置 PositionDir、OpenPrice、TP/SL 并写回 OutputBus。
对应到 MQL5,指标用 iMA 句柄+动态数组,信号用 bool 比较,下单用 CTrade/OrderSend:
int ma1=iMA(_Symbol,_Period,21,0,MODE_EMA,PRICE_CLOSE); int ma2=iMA(_Symbol,_Period,55,0,MODE_EMA,PRICE_CLOSE); double v1[],v2[]; CopyBuffer(ma1,0,0,count,v1); CopyBuffer(ma2,0,0,count,v2); bool Buy = ((v2[K]-v1[K])>=0 && (v2[K-1]-v1[K-1])<0); bool Sell= ((v2[K]-v1[K])<=0 && (v2[K-1]-v1[K-1])>0);
输入/输出端口如何映射到 OnTick
Simulink 的 FromWorkspace 输入(open/ema/high/low/TP/SL)在 MQL5 中没有显式块:价格由 OnTick 实时取,指标句柄+CopyBuffer 得到的值等价于缓冲区。Stateflow 的 Buy/Sell 事件映射到 OnCalculate/OnTick 里算出的 bool;OpenBuy/OpenSell 映射到“if(Buy){ OrderSend(...) }”。ToWorkspace 输出的 AccountBalance 在 MT5 中由策略测试器记录,不需手写。
验证与仿真步骤
- 用 MT5 脚本 testClose.mq5 导历史(O/H/L/C/点差)到 MATLAB,算 ema21/55、num、K=3、sl=0.0065、tp=0.0295。
- 建空模型,设 Fixed-step、discrete、step=1;搭 FromWorkspace 子系统、Stateflow 状态机、ToWorkspace。
- mex -setup 选编译器后点 Start simulation,约 6 万根柱处理 <40 秒。
- 把逻辑手写成 MQL5 EA,用 MT5 历史数据回测验证。