一张图表上多个指标(第 04 部分):晋升为一款智能交易系统(基础篇)
📘

一张图表上多个指标(第 04 部分):晋升为一款智能交易系统(基础篇)

第 1/2 篇

◍ 把多指标图表升级成 EA 的起点

在 MT5 里,把一张叠了多个指标的图表直接转成智能交易系统(EA),是很多手动交易员跨进自动化的第一步。原文作者 Daniel Jose 在 2022 年 5 月 17 日发布的这一思路,截至发布页统计获得了 2351 次查看与 5 条互动,说明这类「图表即策略」的改造需求并不小众。 做法上,核心是把你已经在图表上肉眼确认过的指标组合(例如均线 + MACD + 波动率带)用 MQL5 的 iCustom 或内置 iMA / iMACD 接口重写进 OnTick 逻辑,让 EA 代替你盯盘并下单。外汇与贵金属品种波动受杠杆与消息面影响大,这类自动化改造只是降低人工遗漏,不消除爆仓风险,回测与模拟盘验证必须做在前面。 一个容易踩的坑:图表上多个指标的周期如果混用(比如 M5 均线配 H1 MACD),EA 里要用不同句柄分别拉数据,别图省事全用 CurrentPeriod,否则信号会错位。打开 MT5 的 MetaEditor,新建 EA 模板后先把指标句柄建出来,是验证这条路径最快的办法。

EA 里挂子窗口为什么比指标难

在自定义指标里加多个子窗口只是改改属性、拖拖绘图缓冲区的事,MQL5 给了现成接口,照着做就行。但把同样的多窗口逻辑搬进 EA,情况立刻变复杂——EA 没有指标那种内建的子窗口绘制通道,你得自己用代码去驱动终端创建并绑定窗口。 难点不在代码量,而在你得真正理解 MQL5 的图表对象与指标句柄机制。会写几行不代表能跑通:很多交易者复制指标代码进 EA 直接编译报错,就是因为 EA 上下文里 ChartIndicatorAdd、iCustom 的调用时序和指标自身生命周期完全不同。 好消息是,EA 里设置子窗口并不需要你写几百行底层绘图,核心就是搞清 MQL5 怎么通过指标句柄把计算输出推到独立窗口。外汇与贵金属杠杆高、滑点大,任何多窗口 EA 在实盘前都应在 MT5 策略测试器里先验证窗口创建是否稳定。

「EA 里塞指标为何总糊主图」

自定义指标类写好了,功能也齐,但直接丢进 EA 用会出岔子:EA 环境没有子窗口机制,类里的绘图逻辑无处落地。有人想走捷径,用 iCustom 调已编译的指标,代码能加载,可图表会被指标模板直接盖在主窗口上,根本没法看。 真问题不是「怎么调指标」,而是「EA 怎么拥有子窗口」。为后续启动的指标单独造子窗口没意义,更顺的路子是先把指标能力揉进 EA,再自己克服子窗口限制。 落地拆成四件实事:造一个不污染主图的通用指标以支持 iCustom;把该指标含进 EA 转成完整交易系统;写个通用对象类负责生成子窗口;用绑定 window 的 C_TemplateChart 管理子窗内容且不动原指标代码。听起来多,逐个点掉就通了。 下面这段 OnInit 片段演示了坑位:iCustom 指向子窗口指标编译件,若句柄无效直接 INIT_FAILED;ChartIndicatorAdd 的 subwindow 参数写 0 表示主图,真要子窗得换对应编号,否则依旧糊主图。外汇与贵金属杠杆高,EA 加载逻辑错一处就可能误绘,上线前务必在 MT5 策略测试器单步核对句柄。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
input class="type">class="kw">string user01 = "";                    class=class="str">"cmt">//Used indicators
input class="type">class="kw">string user02 = "";                    class=class="str">"cmt">//Assets to follow
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
{
    class="type">int m_handleSub;
class=class="str">"cmt">//... Expert Advisor code ...
    if ((m_handleSub = iCustom(NULL, class="num">0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) class="kw">return INIT_FAILED;
    if (!ChartIndicatorAdd(ChartID(), class="num">0, m_handleSub)) class="kw">return INIT_FAILED;
class=class="str">"cmt">//... Expert Advisor code ...
    ChartRedraw();
    
    class="kw">return(INIT_SUCCEEDED);
}
class=class="str">"cmt">//...The rest of the Expert Advisor code ...

◍ 把空壳指标塞进 RESOURCE 目录

要支撑子窗口里挂指标,最干净的做法是写一个啥都不画、只完成初始化的自定义指标。下面这段 SubSupport.mq5 就是全部内容,没有多余逻辑。 代码里 indicator_plots 设为 0,意味着它不在图表上输出任何线或图形;OnInit 直接返回 INIT_SUCCEEDED,OnCalculate 原样吐回 rates_total。它存在的意义不是计算,而是被 EA 以资源方式引用。 保存时别丢进普通 Indicators 文件夹。它的落点应该是智能交易系统的 RESOURCE 目录,文件结构因此和常规指标不同。这么摆位有实际用处,但这一节先不展开,留到后面任务再说。 你打开 MT5 的 MQL5/Experts/RESOURCE 路径,把这份文件丢进去,就能在 EA 里通过资源机制调用它,验证子窗口指标支撑是否生效。外汇与贵金属品种波动剧烈,这类底层挂载出错可能让 EA 静默失效,上真仓前先在策略测试器跑一遍。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property description "This file only enables support of indicators in SubWin."
class="macro">#class="kw">property indicator_chart_window
class="macro">#class="kw">property indicator_plots class="num">0
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
{
      class="kw">return INIT_SUCCEEDED;
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnCalculate(class="kw">const class="type">int rates_total, class="kw">const class="type">int prev_calculated, class="kw">const class="type">int begin, class="kw">const class="type">class="kw">double &price[])
{
      class="kw">return rates_total;
}
class=class="str">"cmt">//+------------------------------------------------------------------+

常见问题

先确认指标都输出明确信号值而非仅绘图,再把指标句柄在EA的OnInit里统一创建,最后用信号组合写交易逻辑。
EA没有图表窗口上下文,子窗口句柄和绘图对象需手动绑定坐标系,遗漏就会导致画不出或错位。
小布可读取你的指标清单并生成EA骨架代码,标出需手动补的信号判断与资源管理项,省去重复敲框架。
检查指标是否默认画在主图窗口,给每个指标显式指定子窗口索引,并确认颜色线宽没被覆盖。
把编译后的空壳指标放入EA所在RESCOURCES或MQL5/Indicators对应子目录,并在EA里用资源引用路径加载。