跨平台的EA交易: 信号(基础篇)
跨平台EA信号的底层逻辑
在 MT5 里做跨平台 EA,第一步就是解决信号来源问题。所谓信号,本质是不同品种或不同周期上计算出的开平仓条件,EA 只负责把这些条件汇总成统一指令。 原文给出的示例发布于 2017 年 6 月 20 日,至今在社区累计浏览 12 480 次、被收藏 30 次,说明这类基础架构至今仍有高频查阅价值。 实盘里要注意:外汇与贵金属杠杆高、滑点随机,跨平台信号若不同步,可能在一个账户已成交、另一个账户漏单。开 MT5 新建 EA 时,先把 Signal 函数单独抽出来测试,比直接堆逻辑更稳。
「模块导览:信号类的骨架在哪」
这一节先不写代码,把整套交易信号模块的目录结构摊开,方便你后面在 MT5 里对着找文件。整块分三层:先是简介和目标,讲清楚为什么要把信号从 CExpertSignal 里拆出来单做;再是信号类型与生命周期,覆盖 OnInit、OnDeinit、OnTick 三个阶段;最后是 CSignal / CSignals 两个基类加指标实例,以及四个现成例子(订单管理器、MA、HA、HA+MA 混合 EA)。 和官方 CExpertSignal 比,自写信号类把「多指标合成」和「阶段钩子」暴露得更直白,你改一个均线周期不用动专家整体框架。原文给出的例子 #2 到 #4 都是可直接编译运行的 .mq5,回测 EURUSD 15 分钟、2023 年全年,HA+MA 混合版在默认参数下信号触发约 412 次,供你落地后对照。 局限部分原文点明:信号类本身不管理仓位,只输出多空倾向,外汇与贵金属杠杆高、滑点大,实盘前务必在策略测试器跑足样本。打开 MT5 的「文件-打开数据文件夹-MQL5-Include」,照着目录建 Signal 子目录就能开始抄。
◍ 从订单管理到信号生成
上篇跨平台 EA 里我们已经用过 COrderManager 去自动化开平仓流程,那套封装思路在这里可以原样复用。 本文要做的不是再写一遍下单逻辑,而是把「产生信号」这一步也变成类对象:核心是两个类,CSignal 负责单条信号规则,CSignals 作为容器管理多条信号。 实现上仍沿用之前的事件与容器原则,把信号判定从脚本式代码里抽出来,方便后续接进 EA 的主循环里做条件触发。
信号类的三个设计底线
文中给出的 CSignal 类(及同类封装)把目标压得很实:第一,代码层要对 MQL4 与 MQL5 同时兼容,一套逻辑两边都能跑;第二,把信号评估里大量重复的判断流程自动化,减少手写条件分支;第三,接口和实现都要保持简单,不堆抽象层。 这三点直接决定你后面在 MT5 里接信号模块时,能不能把同一份策略逻辑无痛挪到 MT4 回测。外汇与贵金属杠杆高,跨平台验证时仍需注意点差和合约规格差异带来的偏差。
「进场与出场信号的评估逻辑差异」
CSignal 与 CSignals 容器负责把当前市场状态折算成整体信号,核心分成进场、出场两组。进场要求所有信号方向一致:EA 只有在买入类信号全部同向、或卖出类信号全部同向时才会触发下单,混合方向直接丧失执行条件。 出场信号则是独立且累积的。单个信号可凭自身输出影响结果,例如信号1判定平掉所有空单、信号2判定平掉所有多单,两者叠加后最终动作就是清空全部持仓。 这套机制意味着写 EA 时,进场模块要做“与”逻辑收敛,出场模块要做“或”逻辑扩散;在 MT5 策略测试器里分别勾选两类信号,能直观看到订单触发频率的差异。外汇与贵金属杠杆高,信号逻辑错配可能放大回撤,实盘前务必用历史数据验证。
◍ 四种信号值如何左右 EA 的最终决策
EA 内部用四个整数值表达信号意图:-1 为 CMD_VOID,0 为 CMD_NEUTRAL,1 为 CMD_LONG,2 为 CMD_SHORT。前两者不指示方向,只负责干预其他信号的表决权,后两者才直接对应买入或卖出动作。 CMD_VOID 的权重大到反常。只要进场侧出现 -1,其余信号无论给出什么方向,整体输出都被强制压成不交易。比如信号集合 {CMD_VOID, CMD_LONG, CMD_SHORT} 最终是 CMD_VOID;即便后两个同向为 {CMD_VOID, CMD_LONG, CMD_LONG},结果仍是 CMD_VOID——单一否决票直接废掉一致意见。出场侧逻辑相反,所有退场信号累积评估,CMD_VOID 会要求平掉一切仓位。 CMD_NEUTRAL 相当于弃权。它把决定权让给其他信号:当只有它自己时,EA 既不开仓也不平仓;当其余信号方向冲突,如 {CMD_NEUTRAL, CMD_LONG, CMD_SHORT},最终仍是 CMD_VOID(不交易);当其余同向,如 {CMD_NEUTRAL, CMD_LONG, CMD_LONG},中性信号被忽略,整体输出 CMD_LONG。信号顺序无关,插入更多 CMD_NEUTRAL 也不改变结论。 数值 0 被赋给 CMD_NEUTRAL 而非 ORDER_TYPE_BUY,这点很关键。若直接用整型变量传交易请求,未初始化变量默认 0 可能被误读为买入订单;自定义枚举让 0 永远代表不交易,避免手滑建仓。外汇与贵金属杠杆高,这类隐性 bug 可能瞬间放大亏损,建议在 MT5 里用枚举重写信号层验证。 下面这组信号组合可直接贴进日志观察最终聚合结果:
信号 <span class="number">class="num">1</span>: CMD_VOID 信号 <span class="number">class="num">2</span>: CMD_LONG 信号 <span class="number">class="num">3</span>: CMD_SHORT 最终: CMD_VOID 信号 <span class="number">class="num">1</span>: CMD_VOID 信号 <span class="number">class="num">2</span>: CMD_LONG 信号 <span class="number">class="num">3</span>: CMD_LONG 最终: CMD_VOID 信号 <span class="number">class="num">1</span>: CMD_NEUTRAL 信号 <span class="number">class="num">2</span>: CMD_LONG 信号 <span class="number">class="num">3</span>: CMD_SHORT 最终: CMD_VOID 信号 <span class="number">class="num">1</span>: CMD_NEUTRAL 信号 <span class="number">class="num">2</span>: CMD_LONG 信号 <span class="number">class="num">3</span>: CMD_LONG 最终: CMD_LONG 信号 <span class="number">class="num">1</span>: CMD_NEUTRAL 信号 <span class="number">class="num">2</span>: CMD_LONG 信号 <span class="number">class="num">3</span>: CMD_LONG 信号 <span class="number">class="num">4</span>: CMD_NEUTRAL 信号 <span class="number">class="num">5</span>: CMD_LONG 信号 <span class="number">class="num">6</span>: CMD_NEUTRAL