MQL4通用EA架构与优化实战
🤖

MQL4通用EA架构与优化实战

从大众交易系统到模块化编程与策略测试

MQL5 编程 难度 · 进阶 2026-06-17 7 分钟阅读
#MQL4#EA架构#策略优化#交易系统

为什么需要通用EA构建方案

大部分外汇书籍只给出最简单的交易系统作为教学案例,但很少以现成Expert Advisor形式正确实现。这导致新手编写者不得不从零开始重复造轮子,无法评估系统实用价值。本文作者提出一种基于自身指标库的通用EA方案,让交易者直接复用经过验证的模块,把精力放在策略逻辑而非底层交易函数上。

该理念的核心是把EA拆成固定结构的块:信号计算块、交易执行块、风控块。所有EA都遵循同一套方案,买入信号是行情方向从下跌变上升,卖出信号相反。系统仅处理已闭合的柱,用第三、第二和第一个柱上的移动值计算趋势,零柱忽略不计。

✦ 新手建议
不要一上来就写完整EA,先理解本文的通用函数库,用几行调用即可完成交易执行,大幅降低出错概率。

基于移动方向变化的交易系统原理

文中系统使用自定义指标JFATL作为移动指标,它是带JMA平滑的简单数字FATL过滤器。互联网流传FATL方向变化必赚几点,但现实并非如此高效。EA用两个独立算法分别处理多空,经验证明比单一算法检测双向信号利润更大。EA可同时多空各建一仓作为交易对,用StopLoss和TakeProfit平仓,反向趋势信号可强平。

信号计算使用iCustom调用JFATL,取三个倒数第二的柱加第四个零柱。为避免每次价格变动重算,EA仅在柱变化时计算,用静态变量LastBars_Up记住上次柱数,BUY_Sign和BUY_Stop保留值至交易或柱变。MinBar_Up初始化为4+39+30,确保有足够柱数计算FATL与JMA。

//---- Initialization of variables             
MinBar_Up = 4 + 39 + 30;
//---- Checking the bars enough
if (IBARS_Up >= MinBar_Up)
//---- Only on new bar
if (LastBars_Up != IBARS_Up)

Lite_EXPERT1.mqh函数库详解

为最大化效益,作者把所有通用交易函数放到Lite_EXPERT1.mqh,通过#include引入。OpenBuyOrder1()建多仓,要求BUY_Signal为true且无同幻数仓,StopLoss和TakeProfit为点数,Money_Management 0到1表示可用保证金比例,小于0则直接当手数。每11秒仅允许一个交易命令发服务器。类似有OpenSellOrder1()。

CloseOrder1()在Stop_Signal为true且幻数匹配时平仓。StopCorrect()检查止损最小允许值并修正。MarginCheck()在保证金不足时缩减手数。GetFreeMargin()返回可用保证金。CountLastTime()记录错误导致的时间暂停。此外还有挂单函数OpenBuyLimitOrder1等、OpenBuyOrder2/OpenSellOrder2先建仓后改止损适应当不允许市价带止损的经纪商,以及Make_TreilingStop标准追踪止损。

bool OpenBuyOrder1
( 
  bool BUY_Signal, int MagicNumber, 
             double Money_Management, int STOPLOSS, int TAKEPROFIT
)
bool OpenSellOrder1
( 
  bool SELL_Signal, int MagicNumber, 
             double Money_Management, int STOPLOSS, int TAKEPROFIT
)
bool CloseOrder1
( 
  bool Stop_Signal, int MagicNumber
)
int StopCorrect
( 
  string symbol, int Stop
)
bool MarginCheck
(
  string symbol, int Cmd, double& Lot
)
double GetFreeMargin()
⚠ 常见坑
三个核心函数执行后会将外部BUY_Signal等置false,若在循环中误用会导致只开一次仓。LastTime为全局变量,控制11秒节流。

EA主体代码结构与信号模块

Exp_1.mq4包含两组几乎相同算法。以多头为例,init()中校验Timeframe_Up仅限1/5/15/30/60/240/1440,否则打印错误。MinBar_Up=4+39+30来自JFATL需39柱算一个FATL,JMA需30值,加3倒数柱与零柱。start()中若IBARS_Up>=MinBar_Up且LastBars_Up!=IBARS_Up才重算信号。

交易执行段调用OpenBuyOrder1(BUY_Sign,1,Money_Management_Up,STOPLOSS_Up,TAKEPROFIT_Up),若ClosePos_Up则CloseOrder1(BUY_Stop,1)。未用挂单与追踪函数时编译有警告,可忽略或删减。新手应重点读注释与静态变量声明,理解信号保持机制。

//----+ EXECUTION OF TRADES
if (!OpenBuyOrder1(BUY_Sign, 1, Money_Management_Up, 
                              STOPLOSS_Up, TAKEPROFIT_Up))
                             return(-1);
if (ClosePos_Up)
      if (!CloseOrder1(BUY_Stop, 1))
                          return(-1);

更换移动指标与多指标扩展

EA可轻松换用作者库内J2JMA指标,即双重JMA平滑。需改外部参数块为Length1_Up、Phase1_Up、Length2_Up、Phase2_Up,MinBar_Up变为4+30+30。iCustom调用变为双平滑参数。同理可用振荡指标。此模块化让策略迭代极快,不必重写交易底层。

//----+ CALCULATING INDICATOR VALUES
for(bar = 1; bar <= 3; bar++)
  Mov[bar - 1]=                  
    iCustom(NULL, Timeframe_Up, 
           "J2JMA", Length1_Up, Length2_Up,
                Phase1_Up, Phase2_Up,  
                    0, IPC_Up, 0, bar);
✦ 灵活度
不仅可换移动,还可接振荡器,只要输出方向信号即可,交易块完全复用。

EA参数分离优化方法

EA有Test_Up和Test_Dn两个逻辑变量,设false可禁某方向计算,从而单独优化多头或空头,节省时间。先优化一个方向,互换变量值再优化另一方向,最后都设true测试。策略测试程序中选择EA、货币对、周期、遗传优化。Expert属性-测试定义保证金、方向、算法;输入选项卡分配Test_Up/Dn,设Timeframe、Money_Management,标记优化变量范围。

作者指出MT4属性窗口不能最大化,提供OpenExp.exe最大化以Exp_c开头的窗口。优化时段不能超历史数据,否则报历史不足错。控制点建模对柱变信号EA足够,不必对每个tick建模。Length_Up类似SMA周期,1到150有意义,越大趋势越稳,与SL/TP有隐性依赖:Length小如4在分钟图可抓10-15点波动,大SL/TP好结果只是市场强趋势巧合,非系统属性。

⚠ 优化陷阱
若Length_Up=4却设SL=50/TP=100优异,多为优化期趋势强而非系统有效,实盘难重现。

实盘定位与后续学习

文末强调这些EA过于简单不能全自动化实盘,但适合交易者离开终端时自动执行孤立操作。下篇将讲优化结果分析与功能扩展。本文主旨是展示模块化EA编写法,给新手通用代码骨架。理解本架构后,可基于此接任意指标,把交易系统属性与经纪商规则解耦。

对比从零写EA,复用Lite_EXPERT1库能避开水位、最小止损、手数步长等大量隐性错误。相较于纯策略脚本,本文方案明确分离信号与执行,便于回测与对比不同指标。需注意MQL4与MQL5差异,本库为mqh含mq4兼容语法,移植MT5需改写OrderSend为CTrade类。

常见问题

把Lite_EXPERT1.mqh用#include引入,在start()里调用OpenBuyOrder1(BUY_Sign, Magic, Money_Management, SL, TP)和CloseOrder1(),配合iCustom取信号,几行即可完成底层交易,不需重写手数计算和经纪商限制处理。
设外部变量Test_Up=true、Test_Dn=false仅优化多头;反之优化空头。在策略测试输入选项卡标记对应方向变量并设另一个false,优化完互换值再跑一次,最后都设true做整体测试。
JFATL指标算一个FATL值需39根柱,JMA平滑需至少30个FATL值,EA算法用3根倒数柱加零柱共4根,合计73根才能保证指标与信号计算有效,避免历史不足报错。
用Lite库里的OpenBuyOrder2/OpenSellOrder2,它们先市价建仓不挂SL/TP,再用OrderModify修改已建仓位追加止损获利,适配仅允许修改仓位的经纪商。
周期不能超可用历史数据下限,否则测试器报历史不足。一般选涵盖多种行情的一段,如1-3年,配合控制点建模即可,不必用所有tick建模浪费时间。