ZigZag (之字折线) 的力量(第二部分)。 接收、处理和显示数据的示例(基础篇)
📘

ZigZag (之字折线) 的力量(第二部分)。 接收、处理和显示数据的示例(基础篇)

第 1/3 篇

◍ 用 ZigZag 抓转折:MT5 里怎么接数据画出来

ZigZag 指标在 MT5 里不是直接给你买卖信号,而是把价格里的显著折返点连成线,帮你看清波段结构。想在 EA 或脚本里用它,第一步是拿到它的缓冲数据,再决定怎么处理、怎么画。 下面这段 MQL5 演示了如何获取 ZigZag 句柄、读取最近两个折点数值并打印。实际跑的时候,把代码贴进 MT5 脚本编辑器编译,挂到 EURUSD 的 H1 图表,就能在专家日志里看到输出——外汇和贵金属波动大,ZigZag 参数敏感,不同品种回看点数要自己调,高风险。 需要注意,ZigZag 是重绘指标,越靠近当前 K 线,折点越可能偏移。所以拿它做触发条件时,建议只用已经稳定的历史折点,别拿最新未确认点下单。

MQL5 / C++
class="type">int zigzag_handle = iCustom(_Symbol, PERIOD_H1, "Examples\\ZigZag", class="num">12, class="num">5, class="num">3);
if(zigzag_handle == INVALID_HANDLE) { Print("Failed to create ZigZag handle"); class="kw">return; }
class="type">class="kw">double zigzag_buffer[class="num">2];
if(CopyBuffer(zigzag_handle, class="num">0, class="num">0, class="num">2, zigzag_buffer) <= class="num">0) { Print("CopyBuffer failed"); class="kw">return; }
Print("ZigZag[class="num">0] = ", zigzag_buffer[class="num">0], " ZigZag[class="num">1] = ", zigzag_buffer[class="num">1]);

四类价格行为指标与统计EA的分工

要把价格行为量化,第一步是定义什么是「线段」。在 MT5 里,线段通常指 ZigZag 识别出的相邻拐点之间的波动段,其大小与持续时间是后续统计的底层变量。 FrequencyChangeZZ 负责记录拐点出现的频率变化,用来观察市场节奏是否加快或放缓;SumSegmentsZZ 汇总线段的总量,适合判断一段行情里波动密集程度。 PercentageSegmentsZZ 按涨跌幅百分比给线段分类,MultiPercentageSegmentsZZ 则在此基础上做多阈值切分,能同时输出不同幅度区间的线段占比。外汇与贵金属波动受杠杆与消息影响大,这类统计仅反映历史分布,不预示下一步方向。 真正落地要靠配套 EA:它收集上述指标数据,分别按「大小」和「持续时间」计数,并在图形界面呈现。EA 处理界面时注意控件重绘开销,避免在每 tick 刷新全部标签,否则高频行情下可能卡顿。

「从修订 ZigZag 到可交易 EA 的链路」

前面已经给出过修订版 ZigZag 指标和一套接收该类指标数据的 C++ 类封装。这一节要做的,是把这些底层工具真正接上交易逻辑:先基于它们写出指标,再写一个读取 ZigZag 形态信号下单的 EA,用历史数据跑通验证。 顺带会引入 EasyAndFast 图形界面函数库的新版本,省掉自己撸窗体事件的麻烦。MT5 里新建 EA 时直接#include 这套库,就能在参数面板外再挂一个可视化统计面板。 本篇主线分三块:定义价格行为的指标原型、带 GUI 的统计型 EA、以及专门数指定区间内 ZigZag 线段根数的 EA。外汇与贵金属波动大、滑点不可控,这类统计 EA 只用于概率观察,不预示单边走势。

◍ 四个刻画价格行为的派生指标

做价格行为量化,先要把走势拆成可统计的线段。基于 ZigZag 的派生指标里,有四个直接定义价格行为特征:FrequencyChangeZZ 统计反向 ZigZag 线段的形成频率,SumSegmentsZZ 从线段集合算总和与均值,PercentageSegmentsZZ 给出线段总和的占比及相互差值,MultiPercentageSegmentsZZ 则借用 PercentageSegmentsZZ 的数值,去判断更高时间帧中若干线段的形成性质。 这四个指标代码结构都和前文 ZigZag 一致,真正要盯的只有接收数据并填充缓冲区的 FillIndicatorBuffers 主函数。 在 MT5 里把这类指标挂到 EURUSD 的 M15,观察 FrequencyChangeZZ 连续 20 根 K 线的输出,能直接看到反向线段形成节奏的稀密变化——这是手动画线很难快速量化的。外汇与贵金属杠杆高、滑点随机,这类统计只描述历史行为,后续转折仍是概率事件。

FrequencyChangeZZ 怎么把 ZigZag 线段数搬进缓冲区

FrequencyChangeZZ 的核心思路,是把 ZigZag 的线段结构换算成「每段包含多少根柱线」,再写进自己的指标缓冲区。主图挂一个普通 ZigZag 只是为了肉眼对照,真正的计算全在子窗口完成。 外部参数只有三项,且本文所有指标共用同一套:按全部可用历史计算、ZigZag 新线段的最小偏差阈值、以及取最终数据用的极值数量。调参时若改了最小偏差,子窗口里「价格放缓」的显现密度会明显变化。 函数入口先接收柱线索引 i 和时间数组 time[],随后从当前柱线时间起,尝试拷贝 1000 根柱的 ZigZag 高低缓冲与对应时间。拷贝成功才往下走,失败就重试最多 10 次——这是为了防止 MT5 在品种刚加载时返回不全。 拿到源数据后调用 GetZigZagData 重组线段,再用 SegmentsTotalBars 取出线段集合里的柱线总数,落进 segments_bars_total_buffer[i]。图表上柱状越低,往往意味着该段 ZigZag 收敛快、价格在选择方向前出现了放缓。外汇与贵金属波动剧烈,这类放缓信号仅作概率参考,实盘须自担高风险。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 填充指标缓冲区                                                                       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void FillIndicatorBuffers(class="kw">const class="type">int i,class="kw">const class="type">class="kw">datetime &time[])
  {
   class="type">int copy_total=class="num">1000;
   for(class="type">int t=class="num">0;t<class="num">10;t++)
     {
      if(::CopyBuffer(zz_handle,class="num">2,time[i],copy_total,h_zz_buffer_temp)==copy_total &&
          ::CopyBuffer(zz_handle,class="num">3,time[i],copy_total,l_zz_buffer_temp)==copy_total &&
          ::CopyTime(_Symbol,_Period,time[i],copy_total,t_zz_buffer_temp)==copy_total)
        {
         class=class="str">"cmt">//--- 获取 ZZ 数据
         zz.GetZigZagData(h_zz_buffer_temp,l_zz_buffer_temp,t_zz_buffer_temp);
         class=class="str">"cmt">//--- 将线段集合中的柱线数量保存到指标缓冲区
         segments_bars_total_buffer[i]=zz.SegmentsTotalBars();
         class="kw">break;
        }
     }
  }

「用三条缓冲区看线段总和的强弱倾斜」

SumSegmentsZZ 在底层复用了前一示例的取数逻辑,差异只发生在缓冲区填充阶段:它分别向三个缓冲区写数据,两个对应向上与向下线段的总和,第三个存二者均值,方便直接在图表上比对多空线段的累积能量。 加载到 MT5 图表后,蓝线代表向上线段总和、红线代表向下线段总和。实测可见,当蓝线持续位于红线上方,说明向上线段总和大于向下线段总和;红线反超则情形逆转。 单向线段总和压过反向的时间越长,后续发生逆转的概率倾向升高,但这只是图表现象,能否作为价格方向的前瞻信号,仍需在策略测试器里跑实验验证,外汇与贵金属品种本身波动剧烈、风险较高。 下面这段是缓冲区填充核心:每次尝试从 ZZ 句柄拷贝 1000 根 K 线的高低点与时间,成功后调用 SumSegmentsUp / Down 算总和并写缓冲,最多重试 10 次。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 填充指标缓冲区                                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void FillIndicatorBuffers(class="kw">const class="type">int i,class="kw">const class="type">class="kw">datetime &time[])
  {
   class="type">int copy_total=class="num">1000;
   for(class="type">int t=class="num">0; t<class="num">10; t++)
     {
      if(CopyBuffer(zz_handle,class="num">2,time[i],copy_total,h_zz_buffer_temp)==copy_total &&
         CopyBuffer(zz_handle,class="num">3,time[i],copy_total,l_zz_buffer_temp)==copy_total &&
         CopyTime(_Symbol,_Period,time[i],copy_total,t_zz_buffer_temp)==copy_total)
        {
         class=class="str">"cmt">//--- 获取 ZZ 数据
         zz.GetZigZagData(h_zz_buffer_temp,l_zz_buffer_temp,t_zz_buffer_temp);
         class=class="str">"cmt">//--- 获取线段数据
         segments_up_total_buffer[i] =zz.SumSegmentsUp();
         segments_dw_total_buffer[i] =zz.SumSegmentsDown();
         segments_average_buffer[i]  =(segments_up_total_buffer[i]+segments_dw_total_buffer[i])/class="num">2;
         class="kw">break;
        }
     }
  }

常见问题

通过iCustom调用修订版ZigZag获取拐点和线段方向,用PlotIndexSetInteger设置画线样式,把高点到低点存进缓冲区即可在图表显示转折。
主要看线段总数、上涨线段占比、下跌线段占比和平均线段长度,用这三个缓冲区能判断当前多空倾斜强弱。
可以,小布盯盘已内置这类AIGC诊断,打开对应品种页就能直接看到线段总和的偏向,不用手动跑EA。
它在每根K线统计该刻生效的zigzag线段数量,按上涨或下跌分类写入两条缓冲区,第三条写总和,便于后续读值。
需加信号过滤、仓位计算和订单执行模块,并把线段倾斜结论转成开平仓条件,外汇贵金属波动大须先回测验证。