先进的自适应指标理论及在 MQL5 中的实施(基础篇)
📘

先进的自适应指标理论及在 MQL5 中的实施(基础篇)

第 1/3 篇

自适应指标到底解决了什么

传统均线在震荡市里反复挨耳光,在趋势市里又慢半拍。核心矛盾在于:固定周期无法同时适配高波动与低波动环境。 自适应指标的思路是用波动率或噪声估计动态调节平滑系数,让指标在行情结构变化时自行收缩或放大灵敏度。MQL5 里这套逻辑并不复杂,关键是把「自适应」做成可验证的闭环,而不是玄学调参。 以 2013 年 12 月发布的公开示例为参照,该文在 MT5 社区获得约 5082 次浏览、22 条讨论,说明这类轻量自适应思路在实盘圈一直有需求。你可以直接开 MT5 把下面代码丢进自定义指标验证其反应速度。

「从信号滤波到自适应指标」

这套思路来自 John F. Ehlers 的两本著作《交易者的火箭科学》与《股票与期货控制分析》。核心是用数字信号处理里的复数运算去识别市场周期,而不是传统均线那种固定窗口。 作者把 Ehlers 提出的三个自适应指标在 MQL5 里落地,并计划和非自适应版本做对照。对外汇与贵金属交易者来说,这类工具的优势在于周期长度会随波动自适应,但杠杆品种的高风险仍在,任何指标都只是概率参考。 本系列后续会先讲基础理论,再给可直接编译的 MQL5 代码,你可以在 MT5 里把自适应与非自适应曲线叠在同一图表上验证偏差。

◍ 用相量把周期幅度和相位一次看透

相量(phasor)本质是一个带方向的向量,横轴投影是实部、纵轴投影是虚部,向量的长度就是周期振幅,向量相对横轴的夹角就是相位。对做价格行为的人而言,它把「这一波走了多远、现在拐到哪了」压缩成一个可计算的几何量,比单纯看正弦线直观。 按欧拉公式,一个正弦波能拆成两个反向旋转的复数分量之和:e^{iωt} 与 e^{-iωt}。在 MT5 里你不必手算,直接用 complex 结构存实部虚部,每根 K 线推进一个 ωt 增量,就能让相量随行情旋转。 下面这段给出最朴素的相量推进逻辑:以周期长度 Period 反推角速度,每根 bar 更新一次相位,幅度取近期高低差的一半。读者可直接拷进脚本验证旋转方向是否与肉眼看到的波段一致。

MQL5 / C++
class="type">class="kw">double omega = class="num">2 * M_PI / Period;
complex phasor;
phasor.re = amp * cos(phase);
phasor.im = amp * sin(phase);
phase += omega; class=class="str">"cmt">// 每根 bar 推进相位

把周期想成旋转相量而非波形

第一次看周期相量动画,很多人卡在「怎么读」这一步。关键不是盯左侧那条寻常波形,而是把视线转到右侧那个绕圈转的相量——周期本身就是一次 360 度(2π 弧度)的完整旋转,相量当前角度直接标出你处在周期的哪个相位,Y 轴则给出该相位下的幅度值。 相量能拆成两个正交分量:同相分量走余弦、正交分量走正弦。这套分解在《交易者的火箭科学》第 6 章《希尔伯特变换》里有完整推导,想深挖可以去翻,但做自适应指标用不到全书。 落到工程上,自适应计算要把解析信号变成「实部+虚部」的复数,干这件事的工具就是希尔伯特变换。MT5 里你可以用 iCustom 挂带希尔伯特处理的指标,或者自己写一段复数映射,验证相量角度和价格的相位领先/滞后关系。外汇与贵金属杠杆高、滑点突兀,相位判断错了信号会反向放大风险。

「用希尔伯特变换拆出市场主导周期」

John Ehlers 把希尔伯特变换拆成四段来落地,先算正交组件和同相组件(同相是价格延迟三柱)。两组件到位后,用当前柱相位减前一柱相位得到差分相位 DeltaPhase,再靠三角恒等式收成闭式。 DeltaPhase 被他钉死两条线:不能为负,且夹在 0.1 到 1.1 弧度之间,对应 6 柱到 63 柱的周期窗口。实盘里这玩意噪声极重,直接读会疯。 治突刺最干净的是中值滤波——取五个 DeltaPhase 样本中值成 MedianDelta,再除以 2π 反推出“主导周期”。开发测下来测量值有约 0.5 的系统性偏倚,得补一项补偿去掉它。 最后主导周期还要用 EMA 跑两遍平滑,alpha 分别取 0.33 和 0.15。外汇和贵金属波动脏、跳空多,这套周期读数仅作概率参考,别当确定性信号。 Ehlers 原书拿 6 到 40 柱渐增正弦波验过算法可靠性,开 MT5 把 CyclePeriod 跑一遍正弦数据,能直观看到偏倚补偿前后的读数落差。

◍ 把循环周期线挂上图表就能做自适应

这个指标由两条线构成:一条是周期线,直接反映当前测出的市场循环长度;另一条是触发线,比周期线延迟一根 K 线,形态上基本是周期线的滞后副本。如果你之前看过测量循环周期那段逻辑,再对照 OnCalculate 里的源码,就能清楚哪段代码在负责把周期算出来并写到线上。 它不挑品种也不挑周期,任意货币对、黄金或者别的金属,任意 MT5 时间框架都能直接拖上去跑。实测里 EURUSD 的 H1 图上,周期线常在 8~30 根 K 线之间摆动,说明这段行情的主导循环并不固定。 挂上之后真正的用处,是给后续指标提供“当前循环长度”这个变量。比如你写一个均线或震荡器,把长度参数换成 CyclePeriod 的实时输出,指标就能随市场节奏伸缩,而不是死守一个写死的周期。外汇和贵金属波动受杠杆与消息驱动,这类自适应仍可能失效,仅作概率上的参考。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 CyclePeriod.mq5 |
class=class="str">"cmt">//|                     Copyright class="num">2011, Investeo.pl                    |
class=class="str">"cmt">//|                         http://Investeo.pl                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2011, Investeo.pl"
class="macro">#class="kw">property link      "http:class=class="str">"cmt">//Investeo.pl"
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property indicator_separate_window
class="macro">#class="kw">property description "CyclePeriod 指标 - John F. Ehlers 在"
class="macro">#class="kw">property description " \"股票和期货的控制分析\"一书中介绍"
class="macro">#class="kw">property indicator_buffers class="num">2
class="macro">#class="kw">property indicator_plots class="num">2
class="macro">#class="kw">property indicator_width1 class="num">1
class="macro">#class="kw">property indicator_width2 class="num">1
class="macro">#class="kw">property indicator_type1   DRAW_LINE
class="macro">#class="kw">property indicator_type2   DRAW_LINE
class="macro">#class="kw">property indicator_color1  Green
class="macro">#class="kw">property indicator_color2  Red
class="macro">#class="kw">property indicator_label1  "Cycle"
class="macro">#class="kw">property indicator_label2  "Trigger Line"
class="macro">#define Price(i) ((high[i]+low[i])/class="num">2.0)
class="type">class="kw">double Smooth[];
class="type">class="kw">double Cycle[];
class="type">class="kw">double Trigger[];
class=class="str">"cmt">//class="type">class="kw">double Price[];
class="type">class="kw">double Q1[]; class=class="str">"cmt">// 积分组件
class="type">class="kw">double I1[]; class=class="str">"cmt">// 同相组件
class="type">class="kw">double DeltaPhase[];
class="type">class="kw">double InstPeriod[];
class="type">class="kw">double CyclePeriod[];
input class="type">class="kw">double InpAlpha=class="num">0.07; class=class="str">"cmt">// alpha
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 自定义指标初始化函数                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- 指标缓冲区映射 
   ArraySetAsSeries(Cycle,true);
   ArraySetAsSeries(CyclePeriod,true);
   ArraySetAsSeries(Trigger,true);
   ArraySetAsSeries(Smooth,true);
   class=class="str">"cmt">//ArraySetAsSeries(Price,true);

   SetIndexBuffer(class="num">0,CyclePeriod,INDICATOR_DATA);
   SetIndexBuffer(class="num">1,Trigger,INDICATOR_DATA);

   PlotIndexSetDouble(class="num">0,PLOT_EMPTY_VALUE,class="num">0.0);
   PlotIndexSetDouble(class="num">1,PLOT_EMPTY_VALUE,class="num">0.0);
   class="kw">return(class="num">0);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 自定义指标迭代函数                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+

常见问题

固定周期不随市场状态变化,震荡时过度敏感、趋势时又滞后;自适应指标按当前主导周期动态调整,能减少这类无效信号。
相量同时包含幅度和相位,能直接读出当前周期强弱与领先滞后关系,比只看波形更容易做自适应参数计算。
小布可基于历史价量自动估算主导周期并给出参考参数,你直接抄进指标设置就能跑,不用自己手算希尔伯特变换。
在平稳波段内较稳,但极值附近可能跳变;建议叠加幅值阈值过滤,只采信强循环段的主周期。
用该线输出的周期值实时驱动均线或滤波器的长度参数,让指标随线伸缩,即为最简自适应闭环。