Summary: 一套完整的EA策略包含四个核心模块:参数配置、策略逻辑、订单执行和风险管理。本文从原理到代码,详解如何构建一个稳健的外汇交易机器人,并附MQL4实际代码示例。




从手工到自动:理解EA策略原理

专家顾问(EA)通过消除情绪化决策,彻底改变了外汇交易。但EA不是“印钞机”——它是一套被翻译成代码的规则。在部署任何自动化系统之前,理解EA策略设计的基本原则至关重要。

本文分解专业EA的四个核心模块,并提供可直接测试的MQL4代码示例。

模块一:配置与参数化(控制面板)

每个稳健的EA都必须向用户暴露关键参数,而无需修改代码。在MQL4中,使用`extern`关键字(MQL5中用`input`)实现。这些参数充当EA的控制面板。

必要的外部参数:

| 参数 | 用途 | 示例值 |
|------|------|--------|
| `Lots` | 固定或计算的手数 | 0.1 |
| `StopLoss` | 以点数为单位的最大亏损 | 150 |
| `TakeProfit` | 以点数表示的止盈目标 | 300 |
| `Slippage` | 最大可接受价格偏差 | 3 |
| `MagicNumber` | 唯一的EA标识符 | 12345 |
| `FastMAPeriod` | 快速均线周期 | 10 |
| `SlowMAPeriod` | 慢速均线周期 | 30 |

为什么参数化很重要: 硬编码的EA缺乏灵活性。当市场条件变化(波动率飙升、趋势强度改变)时,你需要调整参数而无需重新编译代码。参数化还能实现对不同货币对和时间周期的优化。

MQL4代码示例:
```mql4
//---- 外部参数(用户可调整)
extern double Lots = 0.1; // 交易手数
extern int StopLoss = 150; // 止损点数
extern int TakeProfit = 300; // 止盈点数
extern int Slippage = 3; // 滑点容忍度
extern int MagicNumber = 12345; // EA唯一标识
extern int FastMAPeriod = 10; // 快线周期
extern int SlowMAPeriod = 30; // 慢线周期
```

模块二:策略逻辑(大脑)

策略逻辑决定何时入场和出场。这是EA的“决策引擎”——通常在`OnTick()`函数(旧版MQL4中为`start()`)中实现,该函数在每个新的报价Tick上执行。

入场条件的结构:

明确定义的入场条件必须不含糊。以均线交叉策略为例:

```
买入条件:快线上穿慢线(黄金交叉)
卖出条件:快线下穿慢线(死亡交叉)
```

MQL4中计算移动平均线:
```mql4
// 计算当前和前一根K线的均线值
double fastMA_current = iMA(NULL, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
double slowMA_current = iMA(NULL, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
double fastMA_previous = iMA(NULL, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double slowMA_previous = iMA(NULL, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);

// 用布尔变量定义交叉条件
bool isGoldenCross = (fastMA_previous <= slowMA_previous && fastMA_current > slowMA_current);
bool isDeathCross = (fastMA_previous >= slowMA_previous && fastMA_current < slowMA_current);
```

为什么布尔变量能提高代码质量: 它们使逻辑可读且自文档化。任何程序员(包括未来的你自己)都能立即理解`isGoldenCross`的含义,而无需解读嵌套的条件语句。

模块三:订单管理与执行(双手)

一旦策略逻辑产生信号,EA必须执行交易。这包括检查现有持仓、发送订单和处理错误。

持仓检查模式:

在入场新交易之前,EA必须验证不存在冲突的持仓。通常通过遍历所有未平仓订单并检查其MagicNumber来实现。

MQL4订单发送示例:
```mql4
// 检查是否存在此MagicNumber的持仓
if(CountOrdersByMagic(MagicNumber) == 0)
{
if(isGoldenCross)
{
int ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage,
Ask - StopLoss * Point,
Ask + TakeProfit * Point,
"EA Trade", MagicNumber, 0, clrGreen);
}
else if(isDeathCross)
{
int ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage,
Bid + StopLoss * Point,
Bid - TakeProfit * Point,
"EA Trade", MagicNumber, 0, clrRed);
}
}
```

错误处理: 专业EA在每次`OrderSend()`调用后都包含错误检查。常见错误包括:
  • `ERR_NO_ERROR` (0):成功

  • `ERR_NO_CONNECTION` (136):券商连接断开

  • `ERR_PRICE_CHANGED` (139):执行期间价格变动

  • `ERR_BROKER_BUSY` (142):券商服务器过载


  • 模块四:风险管理(安全卫士)

    风险管理是任何EA中最关键的模块。没有它,一次黑天鹅事件就可能摧毁账户。专业EA实施多层风险控制。

    第一层:单笔风险上限

    基于账户净值和止损距离动态计算仓位大小:

    ```mql4
    double CalculateLotSize(double riskPercent, double stopPips)
    {
    double accountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
    double riskAmount = accountEquity * (riskPercent / 100.0);
    double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
    double lotSize = riskAmount / (stopPips * pipValue);

    // 应用最小/最大手数限制
    double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
    double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    lotSize = MathMax(minLot, MathMin(lotSize, maxLot));

    // 按步长取整
    double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    lotSize = MathFloor(lotSize / step) * step;

    return lotSize;
    }
    ```

    第二层:日亏损上限

    当日亏损达到预设阈值后,阻止EA继续交易。这能阻止连续亏损后的“报复性交易”效应。

    ```mql4
    double dailyLossLimit = 6.0; // 日初净值的6%
    if(CalculateDailyLoss() > dailyLossLimit)
    {
    Print("日亏损上限已达到,暂停交易24小时。");
    return; // 退出OnTick(),不执行任何交易
    }
    ```

    第三层:最大回撤保护

    如果从净值峰值的累计亏损超过阈值(如15%),EA应完全关闭并通知用户。

    关于马丁格尔的警告:

    部分EA实施马丁格尔策略——每次亏损后加倍仓位。虽然在回测中可以快速回本,但在实盘中会导致灾难性回撤。在50%胜率系统中,连续10次亏损的概率只有0.1%,但当它发生时,账户几乎必然爆仓。不要在任何意图长期存活的EA中使用马丁格尔。

    回测:上实盘前的关键步骤

    回测是在历史数据上运行EA以评估其表现的过程。根据交易研究,回测应至少覆盖50-100笔交易才能提供统计学上有意义的结果。

    需要评估的关键回测指标:

    | 指标 | 含义 | 可接受范围 |
    |------|------|------------|
    | 胜率 | 盈利交易的比例 | 40-60%(因策略而异)|
    | 利润因子 | 总盈利 / 总亏损 | >1.5(稳健),>2.0(优秀)|
    | 最大回撤 | 峰值到谷底的最大跌幅 | <25% |
    | 夏普比率 | 风险调整后的回报 | >1.0 |

    过度拟合陷阱:

    一个常见的错误是不断优化参数直到回测看起来完美。这被称为“曲线拟合”,会导致实盘表现灾难性失效。学术研究表明,每优化1个参数,回测样本中至少需要100笔交易才能避免过度拟合。

    实操回测流程:

    1. 使用Tick数据提高精度: 日线OHLC数据对日内策略是不够的。对于在H1或更低时间框架上交易的EA,需要购买Tick数据(或使用提供高质量历史数据的券商)。

    2. 跨多种市场状态测试: 不要只在趋势市场上测试。包括震荡期、高波动事件(非农、CPI)和低波动的假日期间。

    3. 前进测试: 在前70%的数据上优化参数,然后在剩余30%上测试而不重新优化。这模拟了实盘条件。

    常见的EA陷阱

    陷阱一:没有建模滑点

    假设完美执行的回测是不现实的。真实市场存在滑点——尤其是在新闻事件期间。始终建模1-3点的正常条件滑点和5-10点的高影响力新闻滑点。

    陷阱二:忽视券商限制

    许多券商禁止对冲(同一品种同时持有多空单)、限制最大手数或适用FIFO规则。你的EA必须尊重这些限制。

    陷阱三:缺乏错误恢复

    网络断连会发生。价格跳空会出现。专业EA包含重连逻辑和持仓恢复机制。

    陷阱四:新闻期间交易

    除非专门设计用于新闻交易,否则EA应在重大经济数据发布(非农、FOMC、CPI)前后暂停15-30分钟。这些期间点差急剧扩大,会摧毁盈利能力。

    混合模式:EA+人工监督

    即使是最好的EA也能从人工监督中受益。混合模式结合了自动化与人工判断:

  • 让EA处理: 技术性入场/出场、仓位大小、止损设置

  • 人工覆盖: 重大新闻事件、极端波动飙升、市场状态变化(趋势vs震荡)


  • 示例每周工作流:
    1. 周日:回顾上周EA表现
    2. 周一早上:查看本周安排的高影响力新闻
    3. 新闻期间:禁用EA或切换到手动模式
    4. 周五下午:在周末跳空风险前平仓(视策略而定)

    整合:最小可行EA检查清单

    在投入真实资金部署任何EA之前,验证以下项目:

  • [ ] 所有参数都已外部化(无硬编码值)

  • [ ] 持仓检查逻辑防止重复入场

  • [ ] 止损和止盈始终附加

  • [ ] 日亏损上限已实现

  • [ ] 最大回撤停机已实现

  • [ ] 回测覆盖至少100笔交易,跨多种市场状态

  • [ ] 滑点已建模(未假设为零)

  • [ ] EA已在模拟盘上前测1-3个月


  • 参考来源:
    MetaQuotes Ltd. MQL4文档。ATFX策略回测科普材料(2021)。FM Studio EA开发研究(2025)。Van K. Tharp,《交易之道:通向财务自由之路》(2006)中的风险管理框架。回测方法改编自避免曲线拟合的学术研究。
    ```