MQL5 向导:无需编程即可创建 EA 交易程序·进阶篇
🧩

MQL5 向导:无需编程即可创建 EA 交易程序·进阶篇

(2/3)· 不写一行代码就能拼出交易机器人,但模块怎么选、交互架构怎么搭才不埋坑?

含代码示例偏理论 第 2/3 篇
很多人以为向导点几下就完事,其实模块组合背后的类继承关系才是 EA 稳定性的关键。选错信号与资金管理的对接方式,回测看着顺、实盘就乱报手数。先把架构看明白,再让向导替你写代码。

EA 输入参数的实盘含义

下面这段 MQL5 声明定义了策略 EA 的核心开关与信号参数。MagicNumber 取 23689 只是订单标识,EveryTick 设 false 意味着只在新柱成型时计算,避免逐 tick 重算拖慢回测。 信号层里 ThresholdOpen 与 ThresholdClose 都给 10,代表多空强度超过 10 分才触发建/平仓;StopLevel 与 TakeLevel 同设 50.0 点,是初始止损止盈距离。Signal_Expiration=4 表示挂单若 4 根 K 线内不成交就自动撤掉。 均线部分用了周期 85、偏移 0、SMA 方法、收盘价序列,权重 1.0 说明它作为主信号不被稀释。追踪模块里固定 30 点启动 trailing、盈利满 50 点才跟,资金块则按账户净值 10% 折算固定手数。 外汇与贵金属波动剧烈,上述点数在 XAUUSD 上可能瞬间被打掉,上 MT5 把这批 input 原样贴进 EA 头文件,改 ThresholdOpen 到 20 对比一下成交频率,比看任何说明都直观。

MQL5 / C++
class="type">class="kw">ulong                Expert_MagicNumber            =class="num">23689;      class=class="str">"cmt">// 
class="type">bool                Expert_EveryTick              =class="kw">false;      class=class="str">"cmt">// 
class=class="str">"cmt">//--- 主要信号的参数
class="kw">input class="type">int           Signal_ThresholdOpen          =class="num">10;         class=class="str">"cmt">// 建仓信号阈值 [class="num">0...class="num">100]
class="kw">input class="type">int           Signal_ThresholdClose         =class="num">10;         class=class="str">"cmt">// 平仓信号阈值 [class="num">0...class="num">100]
class="kw">input class="type">class="kw">double        Signal_PriceLevel             =class="num">0.0;        class=class="str">"cmt">// 执行交易的价格水平
class="kw">input class="type">class="kw">double        Signal_StopLevel              =class="num">50.0;       class=class="str">"cmt">// 止损水平 (点数)
class="kw">input class="type">class="kw">double        Signal_TakeLevel              =class="num">50.0;       class=class="str">"cmt">// 获利水平 (点数)
class="kw">input class="type">int           Signal_Expiration             =class="num">4;          class=class="str">"cmt">// 挂单过期时间 (柱数)
class="kw">input class="type">int           Signal_MA_PeriodMA            =class="num">85;         class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 平均周期数
class="kw">input class="type">int           Signal_MA_Shift               =class="num">0;          class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 时间转换
class="kw">input ENUM_MA_METHOD Signal_MA_Method             =MODE_SMA;   class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 平均方法
class="kw">input ENUM_APPLIED_PRICE Signal_MA_Applied        =PRICE_CLOSE;class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 价格序列
class="kw">input class="type">class="kw">double        Signal_MA_Weight              =class="num">1.0;        class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 权重 [class="num">0...class="num">1.0]
class=class="str">"cmt">//--- 追踪输入参数
class="kw">input class="type">int           Trailing_FixedPips_StopLevel  =class="num">30;         class=class="str">"cmt">// 追踪止损水平 (点数)
class="kw">input class="type">int           Trailing_FixedPips_ProfitLevel=class="num">50;         class=class="str">"cmt">// 追踪获利水平 (点数)
class=class="str">"cmt">//--- 资金输入参数
class="kw">input class="type">class="kw">double        Money_FixLot_Percent          =class="num">10.0;       class=class="str">"cmt">// 百分比

「EA初始化里把信号、均线和追踪串起来」

MT5 的标准 EA 框架里,OnInit 不是随便写几行下单逻辑,而是把「信号—过滤器—追踪—资金」四个模块挂到 CExpert 实例上。这段代码用 ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber) 做底层绑定,失败就 printf 报错并返回 -1,MagicNumber 错了订单会乱套。 信号层先 new 一个 CExpertSignal,再设 ThresholdOpen、PriceLevel、StopLevel 等 7 个参数;任何一步 new 出来是 NULL 就直接 Deinit 并返错误码(-2、-3 这类),你能从日志里的数字快速定位断在哪。 均线过滤用 CSignalMA 做 filter0,挂进 signal.AddFilter;PeriodMA、Method、Applied 这些决定它到底是看收盘价还是典型价的哪条均线。追踪模块用的是 CTrailingFixedPips,StopLevel 和 ProfitLevel 设完才算给 EA 装上了硬止损移动能力。 固定手数从顶部 input double Money_FixLot_Lots = 0.1 来,外汇和贵金属都是高杠杆品种,0.1 手在 XAUUSD 上波动一点约 1 美元,实盘前建议在策略测试器里先跑历史数据验证这套挂载是否如预期触发。

MQL5 / C++
class="kw">input class="type">class="kw">double      Money_FixLot_Lots       =class="num">0.1;      class=class="str">"cmt">// 固定交易量
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 全局EA交易对象                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
CExpert ExtExpert;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EA交易初始化函数                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- 初始化EA
   if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
     {
      class=class="str">"cmt">//--- 失败
      printf(__FUNCTION__+": 初始化EA交易失败");
      ExtExpert.Deinit();
      class="kw">return(-class="num">1);
     }
class=class="str">"cmt">//--- 创建信号
   CExpertSignal *signal=new CExpertSignal;
   if(signal==NULL)
     {
      class=class="str">"cmt">//--- 失败
      printf(__FUNCTION__+": 创建信号错误");
      ExtExpert.Deinit();
      class="kw">return(-class="num">2);
     }
class=class="str">"cmt">//---
   ExtExpert.InitSignal(signal);
   signal.ThresholdOpen(Signal_ThresholdOpen);
   signal.ThresholdClose(Signal_ThresholdClose);
   signal.PriceLevel(Signal_PriceLevel);
   signal.StopLevel(Signal_StopLevel);
   signal.TakeLevel(Signal_TakeLevel);
   signal.Expiration(Signal_Expiration);
class=class="str">"cmt">//--- 创建 CSignalMA 过滤器
   CSignalMA *filter0=new CSignalMA;
   if(filter0==NULL)
     {
      class=class="str">"cmt">//--- 失败
      printf(__FUNCTION__+": 创建过滤器 filter0 失败");
      ExtExpert.Deinit();
      class="kw">return(-class="num">3);
     }
   signal.AddFilter(filter0);
class=class="str">"cmt">//--- 设置参数过滤器
   filter0.PeriodMA(Signal_MA_PeriodMA);
   filter0.Shift(Signal_MA_Shift);
   filter0.Method(Signal_MA_Method);
   filter0.Applied(Signal_MA_Applied);
   filter0.Weight(Signal_MA_Weight);
class=class="str">"cmt">//--- 创建追踪对象
   CTrailingFixedPips *trailing=new CTrailingFixedPips;
   if(trailing==NULL)
     {
      class=class="str">"cmt">//--- 失败
      printf(__FUNCTION__+": 创建追踪错误");
      ExtExpert.Deinit();
      class="kw">return(-class="num">4);
     }
class=class="str">"cmt">//--- 给EA增加追踪功能 (将会自动删除))
   if(!ExtExpert.InitTrailing(trailing))
     {
      class=class="str">"cmt">//--- 失败
      printf(__FUNCTION__+": 初始化追踪错误");
      ExtExpert.Deinit();
      class="kw">return(-class="num">5);
     }
class=class="str">"cmt">//--- 设置追踪参数
   trailing.StopLevel(Trailing_FixedPips_StopLevel);
   trailing.ProfitLevel(Trailing_FixedPips_ProfitLevel);
class=class="str">"cmt">//--- 创建资金对象
   CMoneyFixedLot *money=new CMoneyFixedLot;
   if(money==NULL)
     {
      class=class="str">"cmt">//--- 失败
      printf(__FUNCTION__+": 创建资金对象错误");
      ExtExpert.Deinit();

◍ 资金对象挂不上就直接退码

这段初始化尾部逻辑只做一件事:把资金管理对象接进 EA,接不上立刻拆台走人。 if(!ExtExpert.InitMoney(money)) 失败时打印「初始化资金对象错误」并调用 Deinit(),返回码是 -7;若校验设置不过返回 -8,指标初始化失败返回 -9,正常则返回 0。 money.Percent() 和 money.Lots() 两个调用把外部输入的仓位百分比与固定手数写进资金模块,之后才允许进入 ValidationSettings() 与 InitIndicators()。 OnDeinit / OnTick / OnTrade / OnTimer 全是薄壳,直接转交 ExtExpert 对应方法,说明事件分发集中在 Expert 类里。 头部的 include 路径暴露了结构:SignalMA 管信号、TrailingFixedPips 管固定点数的追踪止损、MoneyFixedLot 管资金,想换模块直接改这三行就能换策略内核。外汇与贵金属杠杆高,改完请在策略测试器用历史数据回测,别直接上实盘。

MQL5 / C++
  if(!ExtExpert.InitMoney(money))
  {
    class=class="str">"cmt">//--- 失败
    printf(__FUNCTION__+": 初始化资金对象错误");
    ExtExpert.Deinit();
    class="kw">return(-class="num">7);
  }
class=class="str">"cmt">//--- 设置资金参数
  money.Percent(Money_FixLot_Percent);
  money.Lots(Money_FixLot_Lots);
class=class="str">"cmt">//--- 检查所有的交易对象
  if(!ExtExpert.ValidationSettings())
  {
    class=class="str">"cmt">//--- 失败
    ExtExpert.Deinit();
    class="kw">return(-class="num">8);
  }
class=class="str">"cmt">//--- 调整所有所需的指标
  if(!ExtExpert.InitIndicators())
  {
    class=class="str">"cmt">//--- 失败
    printf(__FUNCTION__+": 初始化指标错误");
    ExtExpert.Deinit();
    class="kw">return(-class="num">9);
  }
class=class="str">"cmt">//--- ok
  class="kw">return(class="num">0);
  }
class="type">void OnDeinit(class="kw">const class="type">int reason)
  {
  ExtExpert.Deinit();
  }
class="type">void OnTick()
  {
  ExtExpert.OnTick();
  }
class="type">void OnTrade()
  {
  ExtExpert.OnTrade();
  }
class="type">void OnTimer()
  {
  ExtExpert.OnTimer();
  }
class="macro">#class="kw">property copyright "Copyright class="num">2012, MetaQuotes Software Corp."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#include <Expert\Expert.mqh>
class=class="str">"cmt">//--- 可用信号
class="macro">#include <Expert\Signal\SignalMA.mqh>
class=class="str">"cmt">//--- 可用追踪止损
class="macro">#include <Expert\Trailing\TrailingFixedPips.mqh>
class=class="str">"cmt">//--- 可用资金管理
class="macro">#include <Expert\Money\MoneyFixedLot.mqh>
class=class="str">"cmt">//--- EA交易的输入参数
class="kw">input class="type">class="kw">string        Expert_Title            ="TestExpert"; class=class="str">"cmt">// EA交易名称

EA 参数组的实盘落点

这段声明直接决定了一个基于均线信号的 EA 在 MT5 里怎么下单、怎么退场。MagicNumber 写死 23689,是为了在同一品种上把本 EA 的挂单和手工单区分开,避免被其他脚本误平。 Expert_EveryTick 设为 false,意味着只在新柱生成时计算信号,而不是每跳都刷,回测里能明显少算很多冗余成交。 信号层的核心是那条 85 周期的 SMA:Signal_MA_PeriodMA=85、Signal_MA_Method=MODE_SMA、Signal_MA_Applied=PRICE_CLOSE,阈值开平都是 10(0~100 区间)。止损止盈对称放在 50 点(Signal_StopLevel / TakeLevel=50.0),挂单 4 根柱不过就废(Signal_Expiration=4)。 追踪部分给了固定点数的尾随:盈利过 50 点后启动,止损跟到 30 点之外(Trailing_FixedPips_ProfitLevel=50、StopLevel=30)。仓位用权益百分比法,Money_FixLot_Percent=10.0 表示按账户 10% 权益换算手数。 外汇和贵金属杠杆高,这类固定点数止损在跳空时可能滑到 50 点以外,开 MT5 把上面参数原样贴进 input 区,先跑 EURUSD 的 M15 复盘看成交密度再上真仓。

MQL5 / C++
class="type">class="kw">ulong                Expert_MagicNumber            =class="num">23689;       class=class="str">"cmt">//
class="type">bool                 Expert_EveryTick              =class="kw">false;       class=class="str">"cmt">//
class=class="str">"cmt">//--- 主要信号的参数
class="kw">input class="type">int            Signal_ThresholdOpen         =class="num">10;           class=class="str">"cmt">// 建仓信号阈值 [class="num">0...class="num">100]
class="kw">input class="type">int            Signal_ThresholdClose        =class="num">10;           class=class="str">"cmt">// 平仓信号阈值 [class="num">0...class="num">100]
class="kw">input class="type">class="kw">double         Signal_PriceLevel            =class="num">0.0;          class=class="str">"cmt">// 执行交易的价格水平
class="kw">input class="type">class="kw">double         Signal_StopLevel             =class="num">50.0;         class=class="str">"cmt">// 止损水平 (点数)
class="kw">input class="type">class="kw">double         Signal_TakeLevel             =class="num">50.0;         class=class="str">"cmt">// 获利水平 (点数)
class="kw">input class="type">int            Signal_Expiration            =class="num">4;            class=class="str">"cmt">// 挂单过期时间 (柱数)
class="kw">input class="type">int            Signal_MA_PeriodMA           =class="num">85;           class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 平均周期数
class="kw">input class="type">int            Signal_MA_Shift              =class="num">0;            class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 时间转换
class="kw">input ENUM_MA_METHOD Signal_MA_Method             =MODE_SMA;     class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 平均方法
class="kw">input ENUM_APPLIED_PRICE Signal_MA_Applied        =PRICE_CLOSE;  class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 价格序列
class="kw">input class="type">class="kw">double         Signal_MA_Weight             =class="num">1.0;          class=class="str">"cmt">// 移动平均(class="num">85,class="num">0,...) 权重 [class="num">0...class="num">1.0]
class=class="str">"cmt">//--- 追踪输入参数
class="kw">input class="type">int            Trailing_FixedPips_StopLevel =class="num">30;           class=class="str">"cmt">// 追踪止损水平 (点数)
class="kw">input class="type">int            Trailing_FixedPips_ProfitLevel=class="num">50;          class=class="str">"cmt">// 追踪获利水平 (点数)
class=class="str">"cmt">//--- 资金输入参数
class="kw">input class="type">class="kw">double         Money_FixLot_Percent         =class="num">10.0;         class=class="str">"cmt">// 百分比
把模块组合诊断交给小布
小布盯盘已内置常见 MQL5 向导模块组合的风险标注,打开对应品种页就能看到某 EA 用的是哪类信号与追踪逻辑,你只管判断适不适合当前行情。

常见问题

Signal 存放交易信号类算法,Trailing 是未平仓位追踪类,Money 为资金与风险管理类;向导解析这些目录自动拼出 EA 源码。
若初期没用面向对象方式隔离模块交互,耦合过紧就会导致局部修改牵动全局,架构不良时调试成本陡增。
可以,小布盯盘的品种页会解析 EA 公开属性与模块特征,标出它归属的 Money 类变体,省去你翻 include 目录。
能,向导允许用自定义类替换或搭配官方信号、追踪与资金模块,也可通过任务服务订购现成实现。