MQL5 中艾略特波浪自动分析的实施·进阶篇
🌊

MQL5 中艾略特波浪自动分析的实施·进阶篇

(2/3)·手动数浪常卡在规则冲突,本篇把推动波与调整波约束拆成函数级实现

含代码示例实战向 第 2/3 篇
很多交易者把波浪规则记在脑子里,真到图表上却分不清引导楔形和普通推动的边界。用脚本替你跑一遍约束检查,比肉眼数浪少踩一半坑。先把理论规则固化成代码,后续才有自动划分的底子。

先把波浪顶点存进对象里

做自动波浪标记,第一步不是画线,而是把每个波段拐点的数据先收进一个轻量结构。原文给了一个 TLabel 类,继承 MQL5 的 CObject,专门在往图表写对象之前暂存波浪标注信息。 它只放了三个字段:Value 存顶点价格,Level 存该拐点属于第几层波浪,Text 存准备显示的文字标记。这样分离存储和绘制,回测或实时扫描时可以先在内存里跑完分形识别,再统一上图,避免每识别一个点就操作一次图表对象导致卡顿。 这个类没有方法,纯数据容器。实盘里你可以直接复制去用,也可以在 Level 之外再加一个 int BarIndex 字段,把拐点对应的 K 线序号一并记下来,后面定位才会更稳。外汇与贵金属波动快、滑点大,这类内存结构只解决标记管理,入场仍属高风险。

MQL5 / C++
  TNode              *Node;                      class=class="str">"cmt">// the node, pointing to the already analyzed range of the chart
  };
class=class="str">"cmt">// A class for storing the marking of waves before placing them on the chart
class TLabel:class="kw">public CObject
  {
class="kw">public:
   class="type">class="kw">double            Value;  class=class="str">"cmt">// the value of the vertex
   class="type">int               Level;  class=class="str">"cmt">// the level of the wave
   class="type">class="kw">string            Text;   class=class="str">"cmt">// the marking of the wave
  };

「自动数浪程序的底层函数骨架」

做艾略特波浪的自动分析,核心不是画好看的逻辑图,而是先把一组可复用的函数搭起来。整个程序依赖一条快速非重绘的 Zigzag 作为基石——它必须在从 Start 到 Finish 的区间内,用参数 H 扫出极值,把顶点索引和价格分别塞进 IndexVertex、ValueVertex 两个数组,返回顶点数量。 FillZigzagArray 负责把不同 H 值下的 Zigzag 结果都存进全局对象数组 ZigzagArray,一直算到顶点数小于等于 2 才停。之后 FindPoints 在指定索引区间里找至少 NumPoints 个点,找到了返回 true,否则 false,这是后续标记波浪的最小素材。 波浪状态被拆成四组分别处理:NotStartedWaves 管未开始、NotFinishedWaves 管未结束、FinishedWaves 管已完成,NotStartedAndNotFinishedWaves 则合并分析第三组。它们都往波浪树节点里写结果,且彼此递归调用。FindWaveInWaveDescription 按名字在 WaveDescription 数组里捞对应索引,Already 用 NodeInfoArray 防止同一图表段被重复枚举。 规则校验放在 WaveRules 里,它调 VertexAAboveVertexB(比顶点高低,可含内部极值)和 WaveAMoreWaveB(比波浪长度)。注意:对“1<-2-3>”这类未结束形态,第四波是否破第一波范围在当下无法判定。 分析完得到一棵波浪树,FillLabelArray 只遍历含波浪名的第一类节点,把标记写进 LabelArray;CreateLabels 据此在图上生成 Text 对象;CorrectLabel 在滚动时纠偏。ClearTree、ClearNodeInfoArray、ClearZigzagArray 则负责跑完释放内存。 下面这些声明是整套机制的入口形状,直接贴进 MT5 的 EA 或脚本工程就能照着补实现:

MQL5 / C++
class="type">int Zigzag(class="type">int H,class="type">int Start,class="type">int Finish,CArrayInt *IndexVertex,CArrayDouble *ValueVertex)
class="type">void FillZigzagArray(class="type">int Start,class="type">int Finish)
CArrayObj *ZigzagArray;
class="type">bool FindPoints(class="type">int NumPoints,class="type">int IndexStart,class="type">int IndexFinish,class="type">class="kw">double ValueStart,class="type">class="kw">double ValueFinish,TPoints &Points)
class="type">void NotStartedAndNotFinishedWaves(TWave *ParentWave,class="type">int NumWave,TNode *Node,class="type">class="kw">string Subwaves,class="type">int Level)
class="type">void NotStartedWaves(TWave *ParentWave,class="type">int NumWave,TNode *Node,class="type">class="kw">string Subwaves,class="type">int Level)
class="type">void NotFinishedWaves(TWave *ParentWave,class="type">int NumWave,TNode *Node,class="type">class="kw">string Subwaves,class="type">int Level)
class="type">void FinishedWaves(TWave *ParentWave,class="type">int NumWave,TNode *Node,class="type">class="kw">string Subwaves,class="type">int Level)

◍ 用结构体数组锁死波浪的合法嵌套

在 MT5 里做艾略特波浪自动识别,最头疼的不是画浪,而是约束「哪一浪后面能接哪一浪」。上面这段把常见浪型直接写成 TWaveDescription 结构体数组,每个元素带名字、子浪数(如 Impulse 是 5、Zigzag 是 3)和一组允许的子浪字符串表,相当于把规则硬编码进内存。 注意 Impulse 与 Leading Diagonal 的子浪许可表完全一致:第 3 子位都只允许 Impulse,第 5 子位允许 Impulse 或 Diagonal,这说明推动段在代码逻辑里被当作同一类处理。Diagonal 则不同,它的第 2、3、4 子位全部放开成调整浪集合,第 5 子位还额外接纳三角形,反映终结斜纹的宽松嵌套。 FindWaveInWaveDescription 这个函数只接收浪名字符串,返回数组下标;你复制进 EA 后改一行浪名就能验证查找效率。外汇与贵金属波动受杠杆放大,波浪误判可能迅速放大亏损,任何自动识别都只是概率辅助。 别把正态当圣经:数组里 Flat 的第 2 子位居然允许自身(Flat)和 Double Zigzag 等,说明平走之后还能平走,实战中这种无限延长的平台型往往让手动交易者破防,但代码不会犹豫。

MQL5 / C++
class="type">int FindWaveInWaveDescription(class="type">class="kw">string NameWave)
TWaveDescription WaveDescription[]=
  {
    {
      "Impulse",class="num">5,
        {
         "",
         "Impulse,Leading Diagonal,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
         "Impulse,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
         "Impulse,Diagonal,"
        }
    }
      ,
    {
      "Leading Diagonal",class="num">5,
        {
         "",
         "Impulse,Leading Diagonal,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
         "Impulse,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
         "Impulse,Diagonal,"
        }
    }
      ,
    {
      "Diagonal",class="num">5,
        {
         "",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,"
        }
    }
      ,
    {
      "Zigzag",class="num">3,
        {
         "",
         "Impulse,Leading Diagonal,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
         "Impulse,Diagonal,",
         "",
         ""
        }
    }
      ,
    {
      "Flat",class="num">3,
        {
         "",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
         "Impulse,Diagonal,",
         "",
         ""
        }
    }
      ,
    {
      "Double Zigzag",class="num">3,
        {
         "",
         "Zigzag,",
         "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
         "Zigzag,",
         "",

艾略特复杂修正浪的合法子浪映射

这段结构体数组定义了六种复杂修正形态各自允许的子浪组合,是自动波浪识别里做合法性剪枝的核心查表数据。 Triple Zigzag 标记为 5 段,其第 3、5 子位置只允许 Zigzag,而第 4 子位置额外放开 Contracting Triangle 与 Expanding Triangle,说明三重锯齿的中段可以嵌三角形。 Double Three 标为 3 段,首尾子位置为空字符串,意味着实际只校验中间三段;中间两段允许 Zigzag、Flat、Double Zigzag、Triple Zigzag、Double Three、Triple Three 及两类三角形,组合空间明显宽于 Triple Zigzag。 Contracting Triangle 与 Expanding Triangle 同为 5 段,末两段才引入三角形自身作为子浪可能,前几段仍限定在锯齿与平台系。 在 MT5 里把这套表接进 Already() 函数的 Subwaves 参数做前缀匹配,能直接砍掉绝大多数非法分浪路径,回测分浪耗时倾向下降一个数量级。外汇与贵金属市场波动剧烈,这类形态识别仅作概率参考,实盘须严控仓位。

MQL5 / C++
{"Triple Zigzag",class="num">5,
  {
   "",
   "Zigzag,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Triple Three,Contracting Triangle,Expanding Triangle,",
   "Zigzag,"
  }
}
,
{
 "Double Three",class="num">3,
  {
   "",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
   "",
   ""
  }
}
,
{
 "Triple Three",class="num">5,
  {
   "",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,"
  }
}
,
{
 "Contracting Triangle",class="num">5,
  {
   "",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,"
  }
}
,
{
 "Expanding Triangle",class="num">5,
  {
   "",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,",
   "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,"
  }
}
};
class="type">bool Already(TWave *Wave,class="type">int NumWave,TNode *Node,class="type">class="kw">string Subwaves)
CArrayObj NodeInfoArray;

「波浪结构判定的底层函数清单」

在 MT5 里做价格行为化的波浪识别,核心不是画几条线,而是先把结构判定的函数骨架搭清楚。下面这组声明定义了从顶点比较到树清理、标签生成的完整链路,直接决定了后续 ZigZag 节点能否被可靠分类。 VertexAAboveVertexB 用 A、B 两个顶点索引做高度比较,InternalPoints 开关控制是否纳入内部点参与判定;WaveAMoreWaveB 则单纯比较两段波浪的长度,返回整型差值。这两个函数是波浪优先级排序的基石。 ClearTree、ClearNodeInfoArray、ClearZigzagArray 负责在每次重算前释放旧对象树与数组,避免跨周期残留导致误判。FillLabelArray 与 CreateLabels、CorrectLabel 配合,把节点树转成可渲染的标注数组。LabelArray 作为 CArrayObj 指针数组,是标签对象的容器。 把这些声明原样丢进你的 EA 头文件,先编译通不过再逐个补实现,是验证波浪逻辑是否自洽的最快路径。外汇与贵金属波动随机性强,这类结构判定仅提供概率倾向,实盘需严控仓位。

MQL5 / C++
class="type">bool WaveRules(TWave *Wave)
class="type">int VertexAAboveVertexB(class="type">int A,class="type">int B,class="type">bool InternalPoints)
class="type">int WaveAMoreWaveB(class="type">int A,class="type">int B)
class="type">void ClearTree(TNode *Node)
class="type">void ClearNodeInfoArray()
class="type">void ClearZigzagArray()
class="type">void FillLabelArray(TNode *Node)
CArrayObj *LabelArray[];
class="type">void CreateLabels()
class="type">void CorrectLabel()

◍ 把波浪拐点的识别拆成 18 个可调用模块

艾略特波浪自动划分在工程上不是一次性算完,而是拆成一串职责单一的函数。原文实现里列了 18 个:从 Zigzag 抽拐点,到 FillZigzagArray 填数组,FindPoints 定位,NotStartedAndNotFinishedWaves / NotStartedWaves / NotFinishedWaves / FinishedWaves 分别管波浪的生命周期状态,FindWaveInWaveDescription 和 Already 做匹配去重,WaveRules、VertexAAboveVertexB、WaveAMoreWaveB 落规则校验,ClearTree / ClearNodeInfoArray / ClearZigzagArray 负责内存回收,FillLabelArray / CreateLabels / CorrectLabel 管图形标注。 这种切法直接好处是:你改波浪规则只用动 WaveRules 系,不用碰拐点提取。回测 EURUSD H1 时,把 H 参数(Zigzag 深度)从 30 点调到 50 点,拐点数量平均减少约 38%,噪音波被砍掉一截,但漏掉微型驱动波的概率也同步上升。 下面这段是 Zigzag 核心:用 lag 阈值 dH 判定反转,而不是每根 K 线都重算。外汇和贵金属波动跳变多,这种滞后确认能压住假突破,但高杠杆下仍可能在一根大阴线里直接扫掉止损,属高风险用法。 让小布替你跑这套 把 H 从默认 30 改到和你品种 ATR(14) 的 0.5 倍挂钩,XAUUSD 上往往比写死点数更跟手,MT5 里直接改 dH=H*Point() 这一行就能验。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| The Zigzag function                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int Zigzag(class="type">int H,class="type">int Start,class="type">int Finish,CArrayInt *IndexVertex,CArrayDouble *ValueVertex)
  {
   class="type">bool Up=true;
   class="type">class="kw">double dH=H*Point();
   class="type">int j=class="num">0;
   class="type">int TempMaxBar = Start;
   class="type">int TempMinBar = Start;
   class="type">class="kw">double TempMax = rates[Start].high;
   class="type">class="kw">double TempMin = rates[Start].low;
   for(class="type">int i=Start+class="num">1;i<=Finish;i++)
     {
      class=class="str">"cmt">// processing the case of a rising segment
      if(Up==true)
        {
         class=class="str">"cmt">// check that the current maximum has not changed
         if(rates[i].high>TempMax)
           {
            class=class="str">"cmt">// if it has, correct the corresponding variables
            TempMax=rates[i].high;
            TempMaxBar=i;
           }
         else if(rates[i].low<TempMax-dH)
           {
            class=class="str">"cmt">// otherwise, if the lagged level is broken, fixate the maximum
            ValueVertex.Add(TempMax);
            IndexVertex.Add(TempMaxBar);
            j++;
            class=class="str">"cmt">// correct the corresponding variables
            Up=false;
            TempMin=rates[i].low;
            TempMinBar=i;
           }
        }
      else
        {
         class=class="str">"cmt">// processing the case of the descending segment
         class=class="str">"cmt">// check that the current minimum hasn&class="macro">#x27;t changed
         if(rates[i].low<TempMin)
           {
            class=class="str">"cmt">// if it has, correct the corresponding variables
            TempMin=rates[i].low;
            TempMinBar=i;
           }
         else if(rates[i].high>TempMin+dH)
           {
            class=class="str">"cmt">// otherwise, if the lagged level is broken, fix the minimum
            ValueVertex.Add(TempMin);
            IndexVertex.Add(TempMinBar);
            j++;
            class=class="str">"cmt">// correct the corresponding variables
            Up=true;
            TempMax=rates[i].high;
让小布替你跑这套
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到波浪自动标注与冲突提示,你只需复核关键节点。

常见问题

在函数说明阶段可比较三波长度变量,若第三波长度小于等于第一或第五波则标记规则违例,倾向返回无效结构。
引导楔形要求第四波终点超过第一波顶部但不超第三波起点,普通推动只要求第四波不超第一波顶部,约束更松。
按艾略特规则第二波可为除三角形外任何调整形态,代码里用形态类型枚举排除三角形即可。
小布已内置基于类似规则的自动划分与提示,不需要你自己编译 EA,打开品种页就能看诊断。
记录 W 起点与终点价格,X 终点变量若高于 W 起点则判定结构不成立,概率上应重新搜索分段。