价格行为分析工具包开发(第19部分):ZigZag分析器·进阶篇
📐

价格行为分析工具包开发(第19部分):ZigZag分析器·进阶篇

(2/3)·手动连高低点漏掉隐性波段?ZigZag算法把趋势线绘制交给代码实时跑

进阶 第 2/3 篇
接上篇,我们继续深挖工具包的核心模块。很多交易者画趋势线靠目测连点,遇到盘整杂波就容易漏掉真正定义方向的波段顶点。用ZigZag阈值过滤反转,能让趋势线只锚定有效摆动,少画一堆自欺欺人的线。

「高低点分别做线性回归画线」

把前 N 个摆动高点与低点的时间、价格分别套进一元线性回归,得到两条通道边界的斜率与截距。代码里对高点、低点各跑一遍相同的累加逻辑:先排除最近一个摆动点(highCount/lowCount 够 4 才减 1),再用 usedHighCount、usedLowCount 参与拟合,样本少于 3 直接跳过。 回归核心就是那几句:sumT 累加时间、sumP 累加价格、sumTP 累加时间×价格、sumT2 累加时间平方;分母 denominator = N*sumT2 - sumT*sumT,不为零时斜率 m = (N*sumTP - sumT*sumP)/denominator,截距 b = (sumP - m*sumT)/N。若分母为零(所有时间点重合的极端情况)则只取价格均值当水平线。

MQL5 / C++
class=class="str">"cmt">// 排除最近一个摆动点(若样本够4)
class="type">int usedHighCount = (highCount >= class="num">4) ? highCount - class="num">1 : highCount;
class="type">int usedLowCount  = (lowCount  >= class="num">4) ? lowCount  - class="num">1 : lowCount;
class="type">class="kw">double mHigh = class="num">0, bHigh = class="num">0, mLow = class="num">0, bLow = class="num">0;
class="type">bool validHigh = false, validLow = false;

class=class="str">"cmt">// 高点回归
if(usedHighCount >= class="num">3)
  {
  class="type">class="kw">double sumT = class="num">0, sumP = class="num">0, sumTP = class="num">0, sumT2 = class="num">0;
  for(class="type">int i = class="num">0; i < usedHighCount; i++)
    {
    class="type">class="kw">double t = (class="type">class="kw">double)highTimes[i];
    class="type">class="kw">double p = highPrices[i];
    sumT += t;
    sumP += p;
    sumTP += t * p;
    sumT2 += t * t;
    }
  class="type">int N = usedHighCount;
  class="type">class="kw">double denominator = N * sumT2 - sumT * sumT;
  if(denominator != class="num">0)
    {
    mHigh = (N * sumTP - sumT * sumP) / denominator;
    bHigh = (sumP - mHigh * sumT) / N;
    }
  else
    bHigh = sumP / N;
  validHigh = true;
  }
class=class="str">"cmt">// 低点回归(结构同上)
if(usedLowCount >= class="num">3)
  {
  class="type">class="kw">double sumT = class="num">0, sumP = class="num">0, sumTP = class="num">0, sumT2 = class="num">0;
  for(class="type">int i = class="num">0; i < usedLowCount; i++)
    {
    class="type">class="kw">double t = (class="type">class="kw">double)lowTimes[i];
    class="type">class="kw">double p = lowPrices[i];
    sumT += t;
    sumP += p;
    sumTP += t * p;
    sumT2 += t * t;
    }
  class="type">int N = usedLowCount;
  class="type">class="kw">double denominator = N * sumT2 - sumT * sumT;
  if(denominator != class="num">0)
    {
    mLow = (N * sumTP - sumT * sumP) / denominator;
    bLow = (sumP - mLow * sumT) / N;
    }
  else
    bLow = sumP / N;
  validLow = true;
  }

class=class="str">"cmt">// 时间边界
 class="type">class="kw">datetime pastTime   = iTime(_Symbol, InpTimeFrame, LookBackBars - class="num">1);
 class="type">class="kw">datetime futureTime = lastBarTime + ExtendFutureBars * PeriodSeconds();
class=class="str">"cmt">// 双回归有效才画线
 if(validHigh && validLow)
  {
开 MT5 把这段塞进 EA,LookBackBars 设 200、ExtendFutureBars 设 20,切 EURUSD 的 H1 跑一下,能直观看到通道随 K 线延伸而重算。外汇与贵金属杠杆高,回归通道只描述已发生摆动的概率倾向,不构成方向担保。

MQL5 / C++
class=class="str">"cmt">// 排除最近一个摆动点(若样本够4)
class="type">int usedHighCount = (highCount >= class="num">4) ? highCount - class="num">1 : highCount;
class="type">int usedLowCount  = (lowCount  >= class="num">4) ? lowCount  - class="num">1 : lowCount;
class="type">class="kw">double mHigh = class="num">0, bHigh = class="num">0, mLow = class="num">0, bLow = class="num">0;
class="type">bool validHigh = false, validLow = false;

class=class="str">"cmt">// 高点回归
if(usedHighCount >= class="num">3)
  {
  class="type">class="kw">double sumT = class="num">0, sumP = class="num">0, sumTP = class="num">0, sumT2 = class="num">0;
  for(class="type">int i = class="num">0; i < usedHighCount; i++)
    {
    class="type">class="kw">double t = (class="type">class="kw">double)highTimes[i];
    class="type">class="kw">double p = highPrices[i];
    sumT += t;
    sumP += p;
    sumTP += t * p;
    sumT2 += t * t;
    }
  class="type">int N = usedHighCount;
  class="type">class="kw">double denominator = N * sumT2 - sumT * sumT;
  if(denominator != class="num">0)
    {
    mHigh = (N * sumTP - sumT * sumP) / denominator;
    bHigh = (sumP - mHigh * sumT) / N;
    }
  else
    bHigh = sumP / N;
  validHigh = true;
  }
class=class="str">"cmt">// 低点回归(结构同上)
if(usedLowCount >= class="num">3)
  {
  class="type">class="kw">double sumT = class="num">0, sumP = class="num">0, sumTP = class="num">0, sumT2 = class="num">0;
  for(class="type">int i = class="num">0; i < usedLowCount; i++)
    {
    class="type">class="kw">double t = (class="type">class="kw">double)lowTimes[i];
    class="type">class="kw">double p = lowPrices[i];
    sumT += t;
    sumP += p;
    sumTP += t * p;
    sumT2 += t * t;
    }
  class="type">int N = usedLowCount;
  class="type">class="kw">double denominator = N * sumT2 - sumT * sumT;
  if(denominator != class="num">0)
    {
    mLow = (N * sumTP - sumT * sumP) / denominator;
    bLow = (sumP - mLow * sumT) / N;
    }
  else
    bLow = sumP / N;
  validLow = true;
  }

class=class="str">"cmt">// 时间边界
 class="type">class="kw">datetime pastTime   = iTime(_Symbol, InpTimeFrame, LookBackBars - class="num">1);
 class="type">class="kw">datetime futureTime = lastBarTime + ExtendFutureBars * PeriodSeconds();
class=class="str">"cmt">// 双回归有效才画线
 if(validHigh && validLow)
  {

同向斜率下的平行通道画法

当高低点回归斜率同号(mHigh*mLow>0)时,说明价格上下边界倾向朝同一方向运行,此时用两者均值 mParallel=(mHigh+mLow)/2.0 作为平行通道的统一斜率,比分别画两条不同斜率的线更贴近通道本意。 代码先以 highPrices[0] 和 lowPrices[0] 分别减去 mParallel 乘对应时间,得到上下轨截距 bHighParallel、bLowParallel,再按 pastTime 到 futureTime 拉出射线。两条线都开了 OBJPROP_RAY_LEFT 与 OBJPROP_RAY_RIGHT,意味着左右双向延伸,适合在 MT5 上直观看价格是否持续贴着通道走。 若斜率异号则走 else 分支,高低点各用自身斜率 mHigh、mLow 与截距 bHigh、bLow 画独立趋势线,不强行平行。外汇与贵金属波动受杠杆与消息面影响大,通道被刺穿的概率不低,实盘使用前建议在历史数据上验证命中率。

MQL5 / C++
  class=class="str">"cmt">// When slopes have the same sign, use average slope for parallel lines
  if(mHigh * mLow > class="num">0)
    {
     class="type">class="kw">double mParallel = (mHigh + mLow) / class="num">2.0;
     class="type">class="kw">double bHighParallel = highPrices[class="num">0] - mParallel * (class="type">class="kw">double)highTimes[class="num">0];
     class="type">class="kw">double bLowParallel  = lowPrices[class="num">0] - mParallel * (class="type">class="kw">double)lowTimes[class="num">0];
     class="type">class="kw">datetime highStartTime = pastTime;
     class="type">class="kw">double highStartPrice  = mParallel * (class="type">class="kw">double)highStartTime + bHighParallel;
     class="type">class="kw">double highEndPrice    = mParallel * (class="type">class="kw">double)futureTime + bHighParallel;
     if(!ObjectCreate(class="num">0, "Downtrend_HighLine", OBJ_TREND, class="num">0, highStartTime, highStartPrice, futureTime, highEndPrice))
        Print("Failed to create High Trendline");
     else
       {
       ObjectSetInteger(class="num">0, "Downtrend_HighLine", OBJPROP_COLOR, clrRed);
       ObjectSetInteger(class="num">0, "Downtrend_HighLine", OBJPROP_RAY_LEFT, true);
       ObjectSetInteger(class="num">0, "Downtrend_HighLine", OBJPROP_RAY_RIGHT, true);
       }
     class="type">class="kw">datetime lowStartTime = pastTime;
     class="type">class="kw">double lowStartPrice  = mParallel * (class="type">class="kw">double)lowStartTime + bLowParallel;
     class="type">class="kw">double lowEndPrice    = mParallel * (class="type">class="kw">double)futureTime + bLowParallel;
     if(!ObjectCreate(class="num">0, "Uptrend_LowLine", OBJ_TREND, class="num">0, lowStartTime, lowStartPrice, futureTime, lowEndPrice))
        Print("Failed to create Low Trendline");
     else
       {
       ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_COLOR, clrGreen);
       ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_RAY_LEFT, true);
       ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_RAY_RIGHT, true);
       }
    }
   else class=class="str">"cmt">// Draw separate trendlines if slopes differ
    {
     class="type">class="kw">datetime highStartTime = pastTime;
     class="type">class="kw">double highStartPrice  = mHigh * (class="type">class="kw">double)highStartTime + bHigh;
     class="type">class="kw">double highEndPrice    = mHigh * (class="type">class="kw">double)futureTime + bHigh;

◍ 用回归直线在图上拉出趋势射线

当高低点两组坐标都通过有效性校验时,代码会分别用线性回归斜率 mHigh/bHigh 与 mLow/bLow 算出过去与未来两个时间点的价格,再调用 ObjectCreate 画 OBJ_TREND 趋势线。高点线命名为 Downtrend_HighLine 并染红,低点线命名为 Uptrend_LowLine 并染绿,两条线都开启 OBJPROP_RAY_LEFT 与 OBJPROP_RAY_RIGHT,意味着向左右双向无限延伸。 若只有 validHigh 成立而低点回归无效,则只画红色高点射线,跳过绿色线,避免用残缺数据强行绘线误导判断。外汇与贵金属波动剧烈,射线仅表达历史回归倾向,实际触碰后的反转概率需结合实时成交量与周期确认。 下面这段是双线绘制的核心片段,逐行看逻辑:if 判断 ObjectCreate 是否返回 false,失败就 Print 报错;成功则进 else 设置颜色与双向射线属性。低点线对称处理,只是把变量换成 mLow/bLow 和绿色。

MQL5 / C++
if(!ObjectCreate(class="num">0, "Downtrend_HighLine", OBJ_TREND, class="num">0, highStartTime, highStartPrice, futureTime, highEndPrice))
      Print("Failed to create High Trendline");
   else
     {
     ObjectSetInteger(class="num">0, "Downtrend_HighLine", OBJPROP_COLOR, clrRed);
     ObjectSetInteger(class="num">0, "Downtrend_HighLine", OBJPROP_RAY_LEFT, true);
     ObjectSetInteger(class="num">0, "Downtrend_HighLine", OBJPROP_RAY_RIGHT, true);
     }
   class="type">class="kw">datetime lowStartTime = pastTime;
   class="type">class="kw">double lowStartPrice  = mLow * (class="type">class="kw">double)lowStartTime + bLow;
   class="type">class="kw">double lowEndPrice    = mLow * (class="type">class="kw">double)futureTime + bLow;
   if(!ObjectCreate(class="num">0, "Uptrend_LowLine", OBJ_TREND, class="num">0, lowStartTime, lowStartPrice, futureTime, lowEndPrice))
      Print("Failed to create Low Trendline");
   else
     {
     ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_COLOR, clrGreen);
     ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_RAY_LEFT, true);
     ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_RAY_RIGHT, true);
     }

「用枢轴点数组画双向射线趋势线」

这段逻辑在 validLow 成立时,把线性回归算出的下轨延成一条双向射线。lowStartTime 取回看起点 pastTime,lowStartPrice 用斜率 mLow 乘时间再加截距 bLow 得到;futureTime 对应的 lowEndPrice 同理推算,等于把拟合直线向右也铺开。 ObjectCreate 失败会 Print 报错,成功则用 ObjectSetInteger 把 Uptrend_LowLine 染成 clrGreen,并同时打开 OBJPROP_RAY_LEFT 与 OBJPROP_RAY_RIGHT。左右都射线化后,这条线在 MT5 主图会贯穿历史与未成交区,方便肉眼读支撑。 DrawSupportResistance 另开一个例程,用 confirmedHighs[10]、confirmedLows[10] 两个定长数组承接之字转向缓冲里的极值。循环里只收 iHigh/iLow 与 zzBuffer[i] 相等的点,且各自上限 10 个,超出直接丢弃。 usedHighCount 与 usedLowCount 有个细节:当确认点数 ≥4 时故意减 1,相当于留最后一个极值不进主统计。major/minor 阻力支撑初值分别设为 -1e9 与 1e9,后续遍历 usedHighCount 找最大正值填 majorResistance,这部分截断了,但思路是拿数组极值当价位锚。外汇与贵金属波动剧烈,射线支撑阻力仅作概率参考,实盘须自担高风险。

MQL5 / C++
      ObjectSetInteger(class="num">0, "Downtrend_HighLine", OBJPROP_RAY_RIGHT, true);
     }
   }
   if(validLow)
     {
      class="type">class="kw">datetime lowStartTime = pastTime;
      class="type">class="kw">double lowStartPrice  = mLow * (class="type">class="kw">double)lowStartTime + bLow;
      class="type">class="kw">double lowEndPrice    = mLow * (class="type">class="kw">double)futureTime + bLow;
      if(!ObjectCreate(class="num">0, "Uptrend_LowLine", OBJ_TREND, class="num">0, lowStartTime, lowStartPrice, futureTime, lowEndPrice))
         Print("Failed to create Low Trendline");
      else
        {
         ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_COLOR, clrGreen);
         ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_RAY_LEFT, true);
         ObjectSetInteger(class="num">0, "Uptrend_LowLine", OBJPROP_RAY_RIGHT, true);
        }
      }
   }
class="type">void DrawSupportResistance()
  {
   class="type">class="kw">double confirmedHighs[class="num">10], confirmedLows[class="num">10];
   class="type">int confHighCount = class="num">0, confLowCount = class="num">0;
   for(class="type">int i = class="num">0; i < LookBackBars - class="num">1; i++)
     {
      if(zzBuffer[i] != class="num">0)
        {
         if(iHigh(_Symbol, InpTimeFrame, i) == zzBuffer[i] && confHighCount < class="num">10)
           {
            confirmedHighs[confHighCount] = zzBuffer[i];
            confHighCount++;
           }
         else if(iLow(_Symbol, InpTimeFrame, i) == zzBuffer[i] && confLowCount < class="num">10)
            {
             confirmedLows[confLowCount] = zzBuffer[i];
             confLowCount++;
            }
        }
     }
   class="type">int usedHighCount = (confHighCount >= class="num">4) ? confHighCount - class="num">1 : confHighCount;
   class="type">int usedLowCount  = (confLowCount  >= class="num">4) ? confLowCount - class="num">1  : confLowCount;
   class="type">class="kw">double majorResistance = -class="num">1e9, majorSupport = class="num">1e9;
   class="type">class="kw">double minorResistance = -class="num">1e9, minorSupport = class="num">1e9;
   class="type">class="kw">double tempHigh = -class="num">1e9, tempLow = -class="num">1e9;
   for(class="type">int i = class="num">0; i < usedHighCount; i++)
     {
      if(confirmedHighs[i] > majorResistance)
        {

主次阻支水平的判定与画线落地

这段逻辑在已确认高低点数组中做二次筛选:主阻力取所有 confirmedHighs 里的最小值,次阻力取仅次于主阻力的那个高值;支撑方向完全对称,主支撑取 confirmedLows 最大值,次支撑取次低值。判定时用了 -1e9 / 1e9 作为未初始化哨兵值,tempHigh 大于该负哨兵才把结果写进 minorResistance,避免把空数据当真实价位画出来。 画线部分用 OBJ_HLINE 在图表挂水平线,主阻力品红(clrMagenta)、次阻力紫红(clrFuchsia)、主支撑浅青(clrAqua)、次支撑蓝(clrBlue)。注意次线有交叉保护:minorResistance 必须严格小于 majorResistance 才画,minorSupport 必须严格大于 majorSupport 才画,防止主次线重叠误导。 开 MT5 把下面代码塞进你的支撑阻力函数末尾,加载到 EURUSD 小时图,可能看到最多四条彩色水平线标出当前结构位。外汇与贵金属波动剧烈,这些线仅作结构参考,实际突破概率随会话背景变化。

MQL5 / C++
      tempHigh = majorResistance;
      majorResistance = confirmedHighs[i];
      }
      else if(confirmedHighs[i] > tempHigh)
        {
         tempHigh = confirmedHighs[i];
        }
     }
   if(tempHigh > -class="num">1e9)
      minorResistance = tempHigh;
   for(class="type">int i = class="num">0; i < usedLowCount; i++)
     {
      if(confirmedLows[i] < majorSupport)
        {
         tempLow = majorSupport;
         majorSupport = confirmedLows[i];
        }
      else if(confirmedLows[i] < tempLow)
          {
           tempLow = confirmedLows[i];
          }
     }
   if(tempLow < class="num">1e9)
      minorSupport = tempLow;
   if(usedHighCount > class="num">0)
     {
      if(!ObjectCreate(class="num">0, "Major_Resistance", OBJ_HLINE, class="num">0, class="num">0, majorResistance))
         Print("Failed to create Major Resistance");
      else
         ObjectSetInteger(class="num">0, "Major_Resistance", OBJPROP_COLOR, clrMagenta);
      if(minorResistance > -class="num">1e9 && minorResistance < majorResistance)
        {
         if(!ObjectCreate(class="num">0, "Minor_Resistance", OBJ_HLINE, class="num">0, class="num">0, minorResistance))
            Print("Failed to create Minor Resistance");
         else
            ObjectSetInteger(class="num">0, "Minor_Resistance", OBJPROP_COLOR, clrFuchsia);
        }
     }
   if(usedLowCount > class="num">0)
     {
      if(!ObjectCreate(class="num">0, "Major_Support", OBJ_HLINE, class="num">0, class="num">0, majorSupport))
         Print("Failed to create Major Support");
      else
         ObjectSetInteger(class="num">0, "Major_Support", OBJPROP_COLOR, clrAqua);
      if(minorSupport < class="num">1e9 && minorSupport > majorSupport)
        {
         if(!ObjectCreate(class="num">0, "Minor_Support", OBJ_HLINE, class="num">0, class="num">0, minorSupport))
            Print("Failed to create Minor Support");
         else
            ObjectSetInteger(class="num">0, "Minor_Support", OBJPROP_COLOR, clrBlue);
        }
     }
   }

◍ 把 ZigZag 折点画成可延伸的趋势线

下面这段 MT5 脚本把标准 ZigZag 指标加载进来,并在最近 200 根 K 线里抓转折折点,再把下降趋势的高点连线、上升趋势的低点连线向后延伸 100 根,方便肉眼读结构。外汇与贵金属波动剧烈,这类辅助画线仅描述已发生结构,不代表后续必然沿原方向运行。 代码用 iCustom 挂系统自带的 "ZigZag",三个参数 Depth=12、Deviation=5、Backstep=3,属于偏敏感的设置,折点出现频率高,适合抓短线波段。LookBackBars 与 ExtendFutureBars 分别控制回看与前瞻根数,你直接调这两个输入就能改变画线密度。 OnInit 里若句柄返回 INVALID_HANDLE 会打印错误并中断初始化;OnDeinit 则负责删掉名为 Downtrend_HighLine 与 Uptrend_LowLine 的两个对象,避免切换周期时残留旧线。复制进 MT5 新建的 mq5 文件即可编译,实盘前先在 EURUSD 的 M15 上验证折点识别是否符合你的肉眼判断。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 ZigZag Analyzer.mq5|
class=class="str">"cmt">//|                                                    Copyright class="num">2025, MetaQuotes Ltd.|
class=class="str">"cmt">//|                                         [MQL5官方文档]
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2025, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.0"
class="macro">#class="kw">property strict
class=class="str">"cmt">// Input parameters
input ENUM_TIMEFRAMES InpTimeFrame    = PERIOD_CURRENT; class=class="str">"cmt">// Timeframe to analyze
input class="type">int             ZZ_Depth        = class="num">12;   class=class="str">"cmt">// ZigZag depth
input class="type">int             ZZ_Deviation    = class="num">5;    class=class="str">"cmt">// ZigZag deviation
input class="type">int             ZZ_Backstep     = class="num">3;    class=class="str">"cmt">// ZigZag backstep
input class="type">int             LookBackBars    = class="num">200; class=class="str">"cmt">// Bars to search for pivots
input class="type">int             ExtendFutureBars = class="num">100; class=class="str">"cmt">// Bars to extend trendlines into the future
class=class="str">"cmt">// Global indicator handle for ZigZag
class="type">int zzHandle;
class=class="str">"cmt">// Arrays for ZigZag data and pivot storage
class="type">class="kw">double   zzBuffer[];
class="type">class="kw">datetime pivotTimes[];
class="type">class="kw">double   pivotPrices[];
class="type">bool     pivotIsPeak[];
class=class="str">"cmt">// Variable to detect new bars
class="type">class="kw">datetime lastBarTime = class="num">0;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Initialization function                                           |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
   zzHandle = iCustom(_Symbol, InpTimeFrame, "ZigZag", ZZ_Depth, ZZ_Deviation, ZZ_Backstep);
   if(zzHandle == INVALID_HANDLE)
     {
      Print("Error creating ZigZag handle");
      class="kw">return(INIT_FAILED);
     }
   class="kw">return(INIT_SUCCEEDED);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Deinitialization function                                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(const class="type">int reason)
  {
   ObjectDelete(class="num">0, "Downtrend_HighLine");
   ObjectDelete(class="num">0, "Uptrend_LowLine");
把波段识别交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到ZigZag自动标出的波段高低点,你专注判断线破还是不破。

常见问题

阈值偏低会保留更多杂波,偏高则滞后。日内贵金属常见用0.3%~0.8%,具体看品种波动率和周期,倾向在M5~H1上回测再定。
跨周期连线能分辨短中长期方向是否共振。若日线支撑与小时阻力同向,概率上信号更可靠,但仍属高风险市场行为。
ZigZag常被归于比尔·沃尔夫相关体系,用来凸显超过阈值的重大反转,沃尔夫波浪借它定位五浪供需均衡,但两者并非绑定使用。
可以,小布的品种页已内置AIGC诊断,自动标出波段顶点并绘制延伸线,不用自己写MQL5跑指标。
需在OnTick或定时器里重算最后一段未闭合ZigZag,避免历史段锁死导致线不跟价,外汇贵金属跳空时尤甚。