跨平台的EA交易: 信号(基础篇)
📘

跨平台的EA交易: 信号(基础篇)

第 1/3 篇

跨平台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 里用枚举重写信号层验证。 下面这组信号组合可直接贴进日志观察最终聚合结果:

MQL5 / C++
信号 <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

常见问题

信号类通常独立于订单执行模块,作为策略核心被单独封装;先看模块导览里标出的信号基类文件,再顺藤摸瓜找具体品种实现。
进场和出场信号的评估逻辑不同:进场偏触发阈值,出场偏状态跟踪;检查信号类里是否给出场单独写了衰减或确认条件。
可以。把信号类的输入输出贴给小布,它能对照设计底线帮你指出哪条信号越界或冗余,省去自己逐行排查。
四种值分别表征强度、方向、置信、过滤;EA按优先级加权,只有通过底线过滤的组合才会进入订单管理模块。
三条底线:不依赖单一平台API、信号与执行解耦、值类型明确可序列化;破任何一条都会导致移植时直接崩。