同步多个相同交易品种而时段不同的图表(基础篇)
📘

同步多个相同交易品种而时段不同的图表(基础篇)

第 1/3 篇

同品种多周期图表如何保持联动

在 MT5 里经常遇到一个场景:同一个交易品种,你开了 M5、H1、D1 三张图,想看价格在不同周期上的同步反应,但默认情况下这几张图各看各的,切换品种时也不会一起跳。 手动逐个改符号效率低,且容易漏掉某张图,导致分析时周期视角错位。Dmitriy Gizlyk 在 2018-06-12 发布的该示例帖获得 8962 次查看、30 条讨论,说明多图同步是实盘中的高频痛点。 解决思路是用一段 MQL5 脚本监听当前激活图表的品种,再把符号名广播给同品种的其他周期图表,让它们自动跟随。下面这段代码演示了基础实现逻辑。

MQL5 / C++
class="type">int OnInit()
{
   EventSetSymbol(GetSymbolName());
   class="kw">return(INIT_SUCCEEDED);
}

class="type">void OnSymbolChange(class="kw">const class="type">class="kw">string symbol)
{
   class="type">long chartIDs[];
   class="type">int total=ChartGetInteger(class="num">0,CHART_WINDOWS_TOTAL);
   for(class="type">int i=class="num">0;i<total;i++)
   {
      class="type">long id=ChartId();
      if(ChartSymbol(id)==symbol)
         ChartSetSymbolPeriod(id,symbol,ChartPeriod(id));
   }
}

◍ 跨周期盯盘的对象同步痛点

老手都习惯先看高周期定方向,再切低周期找入场,但手动切周期时,画好的趋势线、框选区域常常跟着变或丢失。MT5 本身支持单图表内改周期保留对象,可一旦要同时盯多个品种或多个周期,麻烦就来了。 最原始的办法是用模板:改一根线,得重新存模板,再挨个图表应用一遍。这种重复操作在盯盘黄金和欧美的联动时尤其耗神,且外汇和贵金属波动快,手动同步容易漏掉关键位。 本文的思路是把同步逻辑塞进一个指标里,让多图表的对象改动自动广播,而不是人肉搬模板。这类自动化对跨周期价格行为分析有直接帮助,但外汇贵金属属高风险品类,任何工具都不消除方向误判的概率。

「用事件驱动避开指标同步的两个坑」

要让 MT5 里多图表共享同一套图形对象,核心任务很直接:指定一个交易品种,把它的对象变化实时搬到其他同品种图表上。但跟踪方式选错,指标就会变成终端负担。 第一种思路是定时轮询,按固定周期扫一遍所有图的对象再同步。优点是每个图表只需一个实例,但有两个硬伤:轮询间隔天然带来同步延迟;你没法干净地判断哪个图表里的对象才是最新真相。对象一多,每次循环耗时和存储量都线性膨胀,而指标跑在 MT5 总流程里,过重会拖垮同终端其他指标的整体效率。 第二种走终端事件,在 OnChartEvent 里当场处理创建和修改。对象一动就立刻反应,延迟压到最低,也不用存全量状态、不用定时全扫,负载明显更轻。代价是 OnChartEvent 只在指标所在图表触发——想自由在任何图表改对象,就得每图都挂实例,人工或靠 ChartIndicatorAdd 自动都行。 我选了事件驱动来实现。指标启动后先按交易品种归类已开图表,查重并把当前图对象克隆进目标图;之后只处理图表事件,把改动对象的数据推给已建好的图表列表。运行时图表会开关,所以用定时器隔一阵重跑一次初始化过程来维持列表准确。外汇与贵金属图表多开时终端负载波动大,实盘前请在模拟环境验证定时器间隔。

把指标克隆到多图表上跑

做跨周期或多品种联动时,最麻烦的是把同一个指标手动挂到一堆图表上。写个 CCloneIndy 类,把品种、指标名、调用路径存进私有变量,初始化时顺手用 MQL_PROGRAM_PATH 截出 Indicators 之后的相对路径,并给指标设个短名,后面靠这个短名去目标图表抓参数。 SearchCharts 是公有的入口:传入源图表 ID,返回选中图表的 ID 数组。ID 为 -1 直接 false;为 0 就取当前 ChartID();若保存的品种和源图表不一致,就重写 s_Symbol 对齐。接着用 ChartFirst/ChartNext 遍历所有打开图表,跳过自身 ID 和品种不匹配的,命中后看指标在不在,不在就调 AddIndicator 挂上,成功才把 ID 写进数组。 AddIndicator 不能直接拿主图表句柄去贴,因为主图和接收图的品种或时段可能不同——我们任务里时段本来就是故意错开的。所以要先取主图指标句柄,拿到参数后,在接收图 ID 和对应时段上重新 iCustom 调用,失败就返回 false,成功再把对象克隆过去。 下面这段是类的骨架和 SearchCharts 前半部分的真实代码,注意 case -1 的提前返回和 s_Symbol 的重写逻辑,都是为了防止后面遍历时错位。外汇与贵金属图表切换频繁,这类自动克隆在实盘前务必在 MT5 策略测试器外先手测一遍,品种不匹配可能导致指标静默失败。

MQL5 / C++
class CCloneIndy
  {
class="kw">private:
  class="type">class="kw">string            s_Symbol;
  class="type">class="kw">string            s_IndyName;
  class="type">class="kw">string            s_IndyPath;
class="kw">public:
                 CCloneIndy();
                ~CCloneIndy();
  class="type">bool            SearchCharts(class="type">long chart,class="type">long &charts[]);
class="kw">protected:
  class="type">bool            AddChartToArray(class="kw">const class="type">long chart,class="type">long &charts[]);
  class="type">bool            AddIndicator(class="kw">const class="type">long master_chart,class="kw">const class="type">long slave_chart);
  };
CCloneIndy::CCloneIndy()
  {
  s_Symbol=_Symbol;
  s_IndyName=MQLInfoString(MQL_PROGRAM_NAME);
  s_IndyPath=MQLInfoString(MQL_PROGRAM_PATH);
  class="type">int pos=StringFind(s_IndyPath,"\\Indicators\\",class="num">0);
  if(pos>=class="num">0)
    {
    pos+=class="num">12;
    s_IndyPath=StringSubstr(s_IndyPath,pos);
    }
  IndicatorSetString(INDICATOR_SHORTNAME,s_IndyName);
  }
class="type">bool CCloneIndy::SearchCharts(class="type">long chart,class="type">long &charts[])
  {
  class="kw">switch((class="type">int)chart)
    {
    case -class="num">1:
      class="kw">return class="kw">false;
      class="kw">break;
    case class="num">0:
      chart=ChartID();
      class="kw">break;
    class="kw">default:
      if(s_Symbol!=ChartSymbol(chart))
        s_Symbol=ChartSymbol(chart);
      class="kw">break;
    }
  class="type">long check_chart=ChartFirst();
  class="kw">while(check_chart!=-class="num">1)
    {
    if(check_chart==chart)
      {
      check_chart=ChartNext(check_chart);
      class="kw">continue;
      }
    if(ChartSymbol(check_chart)!=s_Symbol)
      {
      check_chart=ChartNext(check_chart);
      class="kw">continue;
      }

常见问题

用事件驱动方式监听品种与周期变化,在主图触发后把对象克隆到其余同品种图表,避免手动逐个复制。
多半是指标或对象按各自图表时间轴计算导致偏移,应统一以主图坐标为基准做对象同步而非各自重算。
可以,小布能按你设定的主图把画线、指标克隆到同品种其他周期窗口,省去手动同步的重复劳动。
常见坑是每图都独立跑完整指标逻辑,应改为主图计算、其余图只接收结果,减少冗余开销。
优先保留1个主判断周期+1个确认周期,其余交给同步机制托管,贵金属波动高风险需聚焦关键信号。