基于自定义指标的交易信号生成器(基础篇)
📘

基于自定义指标的交易信号生成器(基础篇)

第 1/3 篇

「用自定义指标在 MT5 里吐出交易信号」

在 MT5 里做信号生成器,核心思路是:把判断逻辑塞进一个自定义指标,让它只负责输出可视化的箭头或缓冲值,EA 再读取这些缓冲来下单。这样指标和交易执行解耦,回测和实盘切换都干净。 官方示例库里有一份发布于 2014-03-25 的自定义信号指标,累计查看 4905 次、被收藏 10 次,作者 Vladimir Karputov。它用两条均线的交叉加上一个自定义过滤条件来标记买卖点,是理解「指标缓冲→EA 信号」链路的现成样板。 外汇与贵金属杠杆高、滑点跳空频繁,这类信号在历史回测里表现再好,实盘也只代表一种概率倾向,不能直接当成交依据。开 MT5 把示例指标加载到 EURUSD 的 M5 图,先肉眼核对箭头位置与均线交叉是否吻合,再决定要不要接 EA。

◍ 从自定义指标搭信号生成器的起点

做信号生成器第一步,是把已有自定义指标接进交易模型框架,而不是从头写指标逻辑。本文聚焦的,是如何针对某个自定义指标编写你自己的交易模型,并搞清模型 0 在信号模块里的位置。 原文用两种代码对照:待修改的源码,和已经改好的片段。改好的部分会用底色高亮(如 rgb(255,246,200) 浅黄),方便你直接复制粘贴进信号生成器文件,少在比对上花时间。 其中 IS_PATTERN_USAGE(0) 型结构会出现在交易信号模块里,模型 0 的用途正是给这类结构当基础容器——后面章节会拆它怎么承载指标缓冲区的读取。 下面这段是已修改代码的文件头示例,先建立对 MySignal.mqh 这个信号类的直观认识:

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                  MySignal.mqh |
class=class="str">"cmt">//|          Copyright © class="num">2012, Vladimir Karputov |
class=class="str">"cmt">//|                     http://wmua.ru/slesar/ |
class=class="str">"cmt">//+------------------------------------------------------------------+

给 MACD 加一套你自己的模型

标配指标里总缺那么一个你真正想用的。以 MT5 自带的 MACD 为例,文件在 MQL5\Indicators\Examples\MACD.mq5,它原生只覆盖主线/信号线转向、穿越、零轴穿越、背离等模型,但你可以往里塞自己的逻辑。 原生模型之外,可以定义一个新条件:当 MACD 低于零线且数值持续递增,价格后续倾向迎来一段上行,适合挂买入思路;反过来,指标在零线上方且数值递减,则下跌概率更大,适合卖出预备。 这个自定义模型不改动指标数学内核,只是在既有输出上叠加一层判定。写代码前先把它在纸面描述清楚,后面直接落到 MQ5 里才不会乱。

「让信号类继承 CExpertSignal 才有交易指示」

在 MT5 里写自己的信号生成器,第一步不是直接算指标,而是先认祖归宗:你的类必须继承自 CExpertSignal。这个基类本身不产出具体策略,它提供了一套公共接口,EA 正是通过这些方法去读取“该多还是该空”的方向指示。 如果只写一个普通类去算均线交叉,EA 框架是看不见它的——因为调度层只认 CExpertSignal 后代暴露的虚拟方法。 所以落地动作很明确:在自定义指标基础上新建信号类时,用 class MySignal : public CExpertSignal 的写法,并把基类的虚方法(如 LongCondition、ShortCondition)重写填进自己的逻辑。这样 EA 才可能在回测或实盘里调用到你的判断。外汇与贵金属杠杆高,信号类只解决“方向倾向”,不等于入场必盈利,验证前先用策略测试器跑历史数据。

◍ 搭一个自己的信号生成器类

MT5 里交易信号生成器默认放在 ...MQL5\Include\Expert\Signal 目录。但标准库那个 Signal 文件夹别往里硬塞私人逻辑,实测堆太多文件会让向导检索变慢。正确做法是在 ...\Expert 下新建 MySignals 文件夹,把自研信号和官方库物理隔离。 在 MetaEditor 里点 File → New,选 Include File (*.mqh),把类命名为 MySignal,路径指定到 Include\Expert\MySignals\MySignal。点 Finish 后向导只给空模板,后面全靠手写或复制粘贴。 内部看,标准库所有信号类骨架几乎一致,差异只在交易模型算法那一段。直接打开 \Include\Expert\Signal 里任意一个现成文件,全选复制进你的模板,再改算法部分就能跑。外汇和贵金属波动大、杠杆高,这类自研信号未经实盘验证前别直接上真仓。

把信号类接进向导的关键几行

做自定义信号模板时,最省事的办法是把现成的 SignalEnvelopes.mqh 里除标题外的全部内容拷进自己的空壳 MySignal.mqh。第 6 行那句 #include <Expert\ExpertSignal.mqh> 不能动,它让预处理器把 CExpertSignal 基类拉进来,信号类才建得起来。 想让 MT5 向导里能看见你这个新信号,得改类描述块。原模板里 Title= 那行决定向导显示的名字,Name= 是指标变量描述名,Class= 是类名——这三处以及 Page= 都要换成自己的标识,比如把 CSignalEnvelopes 全改成 CSignalMyCustInd,避免和原类混淆。 参数描述块必须和你要挂的指标对上。以 MACD.mq5 为例,它暴露 PeriodMA、Shift、Method 这类参数,你在信号类里写的 Parameter= 行就得一一匹配类型与默认值;换别的自定义指标,参数名和数量可能完全不同,照抄只会编译报警。 顺手给代码加注释是个好习惯,隔两周回看不至于盯瞎眼。下面这段就是改完头部后的样子,注意向导描述注释块从 SignalEnvelopes 换成了 MySignal 的署名与链接。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                  SignalEnvelopes.mqh |
class=class="str">"cmt">//|             Copyright class="num">2009-class="num">2013, MetaQuotes Software Corp. |
class=class="str">"cmt">//|                       [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                    MySignal.mqh |
class=class="str">"cmt">//|                   Copyright © class="num">2012, Vladimir Karputov |
class=class="str">"cmt">//|                         http://wmua.ru/slesar/ |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Expert\ExpertSignal.mqh>
class=class="str">"cmt">// wizard description start
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Description of the class                                        |
class=class="str">"cmt">//| Title=Signals of indicator &class="macro">#x27;Envelopes&class="macro">#x27;                          |
class=class="str">"cmt">//| Type=SignalAdvanced                                             |
class=class="str">"cmt">//| Name=Envelopes                                                  |
class=class="str">"cmt">//| ShortName=Envelopes                                             |
class=class="str">"cmt">//| Class=CSignalEnvelopes                                          |
class=class="str">"cmt">//| Page=signal_envelopes                                           |
class=class="str">"cmt">//| Parameter=PeriodMA,class="type">int,class="num">45,Period of averaging                   |
class=class="str">"cmt">//| Parameter=Shift,class="type">int,class="num">0,Time shift                                |
class=class="str">"cmt">//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging    |

常见问题

先写一个返回双缓冲的自定义指标,再建一个继承信号基类的信号类,把指标值读进来做判断,最后接进策略向导即可。
在信号类里用柱体穿越零轴且前一根确认的方式过滤,只在收盘判定,能明显减少假信号。
小布可以读取你的信号类结构,标出未覆盖的行情状态并给出简化诊断,你照着补条件就行。
向导只认继承自标准信号基类的模块,不继承就不会出现在可选信号列表,必须按规范派生。
贵金属杠杆高、跳空多,信号类要加滑点和点差过滤,任何信号都只是概率倾向,实盘先模拟验证。