MQL4通用EA架构与优化实战
从大众交易系统到模块化编程与策略测试
为什么需要通用EA构建方案
大部分外汇书籍只给出最简单的交易系统作为教学案例,但很少以现成Expert Advisor形式正确实现。这导致新手编写者不得不从零开始重复造轮子,无法评估系统实用价值。本文作者提出一种基于自身指标库的通用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标准追踪止损。
- OpenBuyOrder1/OpenSellOrder1:市价建仓带SL/TP
- OpenBuyOrder2/OpenSellOrder2:市价建仓后追加SL/TP
- CloseOrder1:按幻数平仓
- StopCorrect:修正止损至 broker 最小值
- MarginCheck:保证金不足缩减手数
- 挂单与删单:Limit/Stop及DeleteOrder1
- 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()
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好结果只是市场强趋势巧合,非系统属性。
- 用Test_Up/Test_Dn隔离多空优化
- 遗传算法+控制点建模提速
- 优化周期须在历史数据内
- Length与SL/TP需逻辑匹配
- Phase最佳经验值+100
- IPC选价类型影响指标计算
实盘定位与后续学习
文末强调这些EA过于简单不能全自动化实盘,但适合交易者离开终端时自动执行孤立操作。下篇将讲优化结果分析与功能扩展。本文主旨是展示模块化EA编写法,给新手通用代码骨架。理解本架构后,可基于此接任意指标,把交易系统属性与经纪商规则解耦。
对比从零写EA,复用Lite_EXPERT1库能避开水位、最小止损、手数步长等大量隐性错误。相较于纯策略脚本,本文方案明确分离信号与执行,便于回测与对比不同指标。需注意MQL4与MQL5差异,本库为mqh含mq4兼容语法,移植MT5需改写OrderSend为CTrade类。