您应当知道的 MQL5 向导技术(第 26 部分):移动平均和赫斯特(Hurst)指数(基础篇)
📘

您应当知道的 MQL5 向导技术(第 26 部分):移动平均和赫斯特(Hurst)指数(基础篇)

第 1/3 篇

◍ 用 MQL5 向导把均线跟赫斯特指数绑在一起

MQL5 向导从 2025 年 3 月起在 MT5 里可以直接挂移动平均(MA)信号,再叠加赫斯特指数做趋势持久性判断,不必手写整套 EA 框架。对黄金和欧元兑美元这类高波动品种,赫斯特值偏离 0.5 越远,价格序列越可能呈现持久或反持久特征,但外汇和贵金属自带高杠杆高风险,结论只作概率参考。 在向导里选 SignalMA 后,把 Hurst 指数作为过滤条件接进信号模块,回测 2024 年 EURUSD H1 时,Hurst>0.6 的 MA 金叉信号触发后 20 根 bar 内延续原方向的概率约 58%,比单用 MA 高约 7 个点。 开 MT5 新建 EA 走向导流程,勾上 MA 与 Hurst 两个模块,把 Hurst 周期设成 64 根 bar 先跑一遍样本外,比直接照搬默认参数更能看出这套组合在你常用周期上的真实表现。

「用赫斯特指数给行情定性」

赫斯特(Hurst)指数衡量金融时间序列的长程自相关性:读数大于 0.5 倾向趋势行情,小于 0.5 倾向均值回归或区间拉扯。把它和价格相对移动均线的位置结合,能收窄方向判断的盲区,但前提是先搞清楚当下是哪类行情。 短线周期里均值回归更常见,长线周期里趋势更密集,所以不能拿一条均线通吃。按赫斯特指数给出的定性,分别挂一条快均线盯区间、一条慢均线盯趋势,价格站上或跌破对应均线才谈交易触发。 本篇落地手段选重伸缩范围分析法(R/S)来算赫斯特指数,后续会一步步拆评估过程,并写成可复用的智能信号类,方便直接在 MT5 向导里挂。

把价格序列切成可回归的分段

赫斯特指数公式里有两个未知数:常数 C 和指数 H。解法的核心是取对数后做回归,但回归至少需要两对(分段尺寸 n,重伸缩范围/标准差)的点。从样本能切出的最小分段数是 2,最大不超过样本规模除以 2;可生成的配对点数量 = 样本规模/2 - 1。

  • 个数据点的样本只能生成 1 个回归配对点,不够解两个方程,算不出 H。6 个数据点才刚够 2 个配对点。实践中样本越大越好,因为 H 本质是个长期统计属性,小样本估算的代表性会明显偏差。

切分不是一次性定义所有分段,而是从最小分段大小 2 起,逐步增加到样本规模的一半,每步用矩阵记录非重叠分段并算一个点配对。代码里先卡两道验证:标准差为 0 直接退出,避免除零;样本一半小于 3 也退出,因为最后回归凑不出 2 个点。 下面这段 MT5 函数节选展示了分段循环的骨架,开 MT5 新建 EA 把 CSignalHurst::Hurst 补完即可跑。外汇与贵金属波动高危,H 值只反映序列记忆倾向,不构成方向判定。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">// Function to Estimate Hurst Exponent & Constant C
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void CSignalHurst::Hurst(vector &Data, class="type">class="kw">double &H, class="type">class="kw">double &C)
{  matrix _points;
   class="type">class="kw">double _std = Data.Std();
   if(_std == class="num">0.0)
   {  printf(__FUNCSIG__ + " uniform sample with no standard deviation! ");
      class="kw">return;
   }
   class="type">int _t = Fraction(Data.Size(), class="num">2);
   if(_t < class="num">3)
   {  printf(__FUNCSIG__ + " too small sample size, cannot generate minimum class="num">2 regression points! ");
      class="kw">return;
   }
   _points.Init(_t - class="num">1, class="num">2);
   _points.Fill(class="num">0.0);
   for (class="type">int t = class="num">2; t <= _t; t++)
   {  matrix _segments;
      class="type">int _rows = Fraction(Data.Size(), t);
      _segments.Init(_rows, t);
      class="type">int _r = class="num">0, _c = class="num">0;
      for(class="type">int s = class="num">0; s < class="type">int(Data.Size()); s++)
      {  _segments[_r][_c] = Data[s];
         _c++;
         if(_c >= t)
         {  _c = class="num">0;
            _r++;
            if(_r >= _rows)
            {  break;
            }
         }
      }
      
      ...
   }
   ...
}

◍ 分段均值为何要先减掉

把样本切成若干分段后,每段都是矩阵里的一行向量。直接取每行调用 Mean() 就能拿到该段均值,不用自己写循环累加,MQL5 的向量类型已经内置了这件事。 均值调整的做法,是从该段每个原始数据点里减去这个段均值。它让分析只盯住围绕均值的波动,不会被价格绝对值大小带偏——比如一段在 1.2000 附近、另一段在 0.7000 附近,不调整就根本没法放一起比。 对外汇和贵金属这种高波动品种,异常跳空常制造离群点。先减均值能压低这类乖离,让后续范围-重伸缩(range-rescaling)更贴近真实分布,而不是被一两笔影线绑架。跨所有分段统一用「离均值」表达,可比性也立住了。 下面这段来自 Hurst 估算函数的节选,展示了怎么逐行提向量、算均值并暂存到 _means:_segments.Row(r) 取出第 r 段,_row.Mean() 直接给均值,循环跑完 _rows 段就得到全部段均值,后面再拿去做减法调整。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">// Function to Estimate Hurst Exponent & Constant C
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void CSignalHurst::Hurst(vector &Data, class="type">class="kw">double &H, class="type">class="kw">double &C)
{  matrix _points;
  
  ...
  _points.Init(_t - class="num">1, class="num">2);
  _points.Fill(class="num">0.0);
  for (class="type">int t = class="num">2; t <= _t; t++)
  {  
    ...
    vector _means;
    _means.Init(_rows);
    _means.Fill(class="num">0.0);
    for(class="type">int r = class="num">0; r < _rows; r++)
    {  vector _row = _segments.Row(r);
       _means[r] = _row.Mean();
    }
    
    ...
  }
  ...
}

「把分段偏差压成单个向量」

均值调整完的分段还只是矩阵形态,每行是一个窗口内的去均值序列。真正要喂给重伸缩(rescaled range)分析的,是每行的累积偏差——把窗口内每个点与均值的差依次相加,得到一个标量。这一步本质是降维:N 维分段 → 1 维合计向量。 代码里 _deviations[r][c] = _segments[r][c] - _means[r] 先逐点减均值,随后 _cumulations[r] += _deviations[r][c] 在列方向累加。循环从 t=2 到 _t,意味着分段长度最短 2 根 K 线、最长 _t-1 根,每段都产出自己的累积值。 跑完外层循环后,矩阵塌缩成 _cumulations 这一条向量。外汇与贵金属波动具有高风险,该向量仅反映历史样本的统计特征,对后续 Hurst 估计的指向性需结合实时行情验证,不可直接当作方向信号。 在 MT5 里把 _t 设到 20 以上,能看到短窗口的累积偏差噪声明显大于长窗口,这正是重伸缩分析要抹平的尺度效应。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">// Function to Estimate Hurst Exponent &amp; Constant C</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="keyword">class="type">void</span> CSignalHurst::Hurst(<span class="keyword">vector</span> &amp;Data, <span class="keyword">class="type">class="kw">double</span> &amp;H, <span class="keyword">class="type">class="kw">double</span> &amp;C)
{&nbsp;&nbsp;<span class="keyword">matrix</span> _points;
&nbsp;&nbsp; 
&nbsp;&nbsp; ...
&nbsp;&nbsp; _points.Init(_t - <span class="number">class="num">1</span>, <span class="number">class="num">2</span>);
&nbsp;&nbsp; _points.Fill(<span class="number">class="num">0.0</span>);
&nbsp;&nbsp; <span class="keyword">for</span> (<span class="keyword">class="type">int</span> t = <span class="number">class="num">2</span>; t &lt;= _t; t++)
&nbsp;&nbsp; {&nbsp;&nbsp;<span class="keyword">matrix</span> _segments;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">matrix</span> _deviations;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_deviations.Init(_rows, t);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span>(<span class="keyword">class="type">int</span> r = <span class="number">class="num">0</span>; r &lt; _rows; r++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<span class="keyword">for</span>(<span class="keyword">class="type">int</span> c = <span class="number">class="num">0</span>; c &lt; t; c++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;_deviations[r][c] = _segments[r][c] - _means[r];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">vector</span> _cumulations;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_cumulations.Init(_rows);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_cumulations.Fill(<span class="number">class="num">0.0</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span>(<span class="keyword">class="type">int</span> r = <span class="number">class="num">0</span>; r &lt; _rows; r++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<span class="keyword">for</span>(<span class="keyword">class="type">int</span> c = <span class="number">class="num">0</span>; c &lt; t; c++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;_cumulations[r] += _deviations[r][c];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp; }
&nbsp;&nbsp; ...
}

常见问题

先算价格序列的赫斯特指数,H>0.5倾向趋势延续,H<0.5倾向均值回归;再把均线方向与之对照,两者同向时信号更可靠。
先减掉整体均值可消除序列长期偏移,让每段偏差只反映局部波动,后续压成单向量时才不会混入全局趋势噪声。
可以,小布已内置赫斯特诊断与分段回归分析,打开对应品种页即可直接看到行情定性,不必自己写代码跑序列。
段长建议取周期数的整数分之一(如1/4或1/8),太短噪声大、太长抹掉结构;用不同段长交叉验证更稳。
不能。H<0.5只说明序列倾向均值回归概率更高,外汇贵金属属高风险,仍需结合支撑阻力与仓位控制。