计算赫斯特指数(基础篇)
◍ 赫斯特指数在MT5里的直接计算
赫斯特指数(Hurst Exponent)衡量时间序列的长期记忆性,值落在 0~1 之间:低于 0.5 倾向反趋势,高于 0.5 倾向趋势延续,接近 0.5 则接近随机游走。在 MT5 里可以脱离第三方库,直接用内置时间序列函数把这段统计跑出来。 下面这段 MQL5 用重标极差法(R/S)对收盘价序列做估计,窗口取 100 根 bar。你复制到脚本里编译,就能在日志看到当前品种的 H 值,拿去和肉眼看的波段结构对照。 外汇与贵金属属高杠杆品种,H 值只描述历史统计特征,不预示未来方向,实盘使用前请在演示账户验证。
class="type">class="kw">double HurstExponent(class="type">class="kw">double &price[], class="type">int n) { class="type">int len = ArraySize(price); class="type">class="kw">double *rescaled = new class="type">class="kw">double[len]; class="type">class="kw">double mean = class="num">0; for(class="type">int i=class="num">0;i<len;i++) mean += price[i]; mean /= len; class="type">class="kw">double cumdev = class="num">0, maxdev = class="num">0, mindev = class="num">0; for(class="type">int i=class="num">0;i<len;i++) { cumdev += price[i] - mean; if(cumdev > maxdev) maxdev = cumdev; if(cumdev < mindev) mindev = cumdev; rescaled[i] = (maxdev - mindev) / MathStdDev(price, class="num">0, len); } class="type">class="kw">double hurst = MathLog(rescaled[len-class="num">1]) / MathLog(n); class="kw">delete[] rescaled; class="kw">return hurst; }
为什么均线指标撑不起动态研判
定义市场动态是交易者的核心日常,但仅靠标准技术分析工具往往力不从心。以 MA 或 MACD 为例,它们能指示趋势方向,却无法告诉你这波动能是否可靠——很多走势只是短时飙升后迅速回落,拿均线信号直接跟单容易被洗。 外汇与贵金属属高风险品种,价格受流动性和情绪扰动大,单看趋势线容易误判假突破。要领先其他参与者半步,靠的是多重优势叠加:趋势反转识别、基本面与技术面共振、以及在情绪失控区的精准下单。 分形分析常被散户忽略,但时间序列的分形维度能有效评估趋势强度与持续性。赫斯特指数(Hurst Exponent)正是这类分析的底層数值,后续我们会直接算它,先建立对分形规则和 H 值的基础认知,方便你开 MT5 自己复现。
「把K线当成会自我复制的分形树」
分形在数学上指具备自相似性的集合:整体和自身的某一部分在形状上完全或近似一致。最直观的例子是分形树——枝杈的弯曲逻辑在主干、大枝、小梢上反复出现。市场里所谓“分形”,说的就是行情在不同时间尺度上存在反复性与周期性,小周期里的波动结构放大后和大周期神似。 分形维数 d 描述对象如何填满空间、结构随尺度如何变化。映射到外汇时间序列,d 衡量的是“不规则程度”:一条直线 d=1,纯随机散布 d=1.5,而真实分形序列通常落在 1<d<1.5 或 1.5<d<1 区间。打开 MT5 用不同周期看 EURUSD,你会注意到 1 小时图的回调形态和日线图的某段整理常常只是缩放关系,这就是 d 落在非整数区间的直观证据。 Edgar Peters 对分形行情假说(FMH)的界定很克制:任何时刻价格未必反映全部可用信息,只反映投资者对预期重要的那部分。对外汇、贵金属这类高杠杆品种,这意味着技术结构自相似不等于因果可外推,顺着分形形状押注仍需防黑天鹅。 想自己验证,可对照 B. Mandelbrot 的《市场(不当)行为》与 Peters 的《分形行情分析》里的维数估计思路,抓一段历史数据算 Hurst 指数,看 d 偏离 1.5 多少——偏离越远,趋势或反趋势的自相似倾向越强。
◍ 从尼罗河洪水到报价曲线的长记忆
赫斯特当年研究尼罗河近九个世纪的洪水记录,发现丰水年之后往往紧接更强的丰水,枯水年之后则是更弱的枯水,并非纯随机。他用重标极差法(R/S)量化这种惯性:先求序列均值与标准差,将每个值减均值得到规范化序列,再累加出累积时间序列,其极差 R 除以标准差 S 即 R/S 值。 在爱因斯坦布朗运动模型里,随机游走下 R/S 随时间的开方增长,对应赫斯特指数 H=0.5。但赫斯特实测尼罗河洪水的 H 达到 0.91,说明累积偏移比随机过程走得更远,过去事件对后来有显著牵引。 把这套方法搬到市场,先用零均值、单位标准差归一化报价以剥离通胀干扰,再算 H。H 在 0.5~1 且偏离 0.5 超两个标准差,就是长线记忆的持久序列,如 Apple(H=0.525)、Rosneft(H=0.648)这类新高高于前高的走势;H 在 0~0.5 且同样偏离则为反持久,常见于 Mechel(H=0.635 表中虽偏高但横盘期呈现频繁小波动);H≈0.5 或偏离不足两标准差,视作随机游走,技术分析参考价值弱。 上表基于过去 7 年日线计算,外汇与贵金属属高风险品种,H 会随制度切换跳变,开 MT5 用 iCustom 加载赫斯特指标逐月回看,比盯单一数值更靠谱。
用V型统计对数图挖出市场的记忆深度
要确认分形分析的结果不是随机噪声,第一步是拿随机游走的空假设做对照。Anis和Lloyd在1976年给出了期望R/S值的公式,n>20时用主方程,n<20另有修正式;据此画出Log(E(R/S))对Log(N)的线,再用标准统计式算期望赫斯特指数E(H),若实测H偏离E(H)超过2个标准差,才谈得上相关。 Peters主张用双对数坐标画V型统计图来定位周期:水平线代表独立随机过程,上倾说明持续过程(R/S比时间平方根跑得快),下倾则是反持续。这条线不是水平后,沿点拉趋势线,找曲线峰值对应的X坐标,周期长度直接取exp(对数标尺值)。 举个实算:拿12000根GBPUSD小时线得到对数标尺值8.2,周期就是exp^8.2≈3772小时,约157天。外汇和贵金属杠杆高、跳空频繁,这种长记忆周期只是概率倾向,不是确定性规律。 验证真假周期得换时间帧复算。上面157天若真实,切到H4取3000根(12000/4)应还能看到相近周期;若消失,说明只是短记忆伪周期。表格里EURUSD在2000根柱的H1上H=0.559、E(H)=0.577,偏离不足2σ,而EURRUB的M5上H=0.476明显低于0.577,才更接近反持续过程。 记忆深度就是行情“记得”过去的时长窗口。不需要 heavy 计算,肉眼读V型图峰位即可框出;任何真周期应在同周期不同时间帧上都能被截出来,否则只是样本巧合。
「把赫斯特指数跑进 MT5 脚本里」
要把分形分析落到盘面上,最直接的方式是写个 MT5 脚本,对指定品种最近 1000 根历史柱线算赫斯特指数。建脚本时先加 #property script_show_inputs,方便在入口选货币对和时间帧。 技术需求写的是 1000 根,但代码里实际要取 1001 根——多出来的那一根是用来算第一根对数收益率的前值,缺了它收益率数组就对不上。 算 RS 统计量前,得把 1000 根切成子群,每个子群不少于 10 根。1000 除以大于 10 的整数,能切出 11 种分频(如 1000/10、1000/11…直到 1000/90 附近的合法因子),所以 RS 计算函数要能按这 11 种分频各跑一次,用 switch-case 分发最省事。 线性回归用最小二乘法单独封一个函数,喂进去的就是刚才 11 次 RS 统计的对数值,斜率就是赫斯特指数估计值。外汇和贵金属波动受杠杆与消息面影响,赫斯特指数只反映历史持续性概率,实盘前务必在策略测试器用小资金验证。 下面这段是原文给出的脚本骨架与关键片段,注意 OnStart 里先判可用柱数,不足 1001 就提示换时间帧并退出,避免数组越界。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| New.mq5 | class=class="str">"cmt">//| 版权所有 class="num">2016, Piskarev D.M. | class=class="str">"cmt">//| piskarev.dmitry25@gmail.com | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "版权所有 class="num">2016, Piskarev D.M." class="macro">#class="kw">property link "piskarev.dmitry25@gmail.com" class="macro">#class="kw">property version "class="num">1.00" class="macro">#class="kw">property script_show_inputs class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 脚本的 start 函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { class=class="str">"cmt">//--- } class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double close[]; class=class="str">"cmt">//声明动态收盘价格数组 class="type">int copied=CopyClose(symbol,timeframe,class="num">0,barscount1+class="num">1,close); class=class="str">"cmt">//复制所选对的收盘价格至 class=class="str">"cmt">//close[] 数组 ArrayResize(close,class="num">1001); class=class="str">"cmt">//设置数组大小 ArraySetAsSeries(close,true); if(bars<class="num">1001) class=class="str">"cmt">//为 class="num">1001 根历史柱线的存在创造一个条件 { Comment("可用柱线太少了!尝试另一个时间帧。"); Sleep(class="num">10000); class=class="str">"cmt">//标签延迟 class="num">10 秒钟 Comment(""); class="kw">return; } for(class="type">int i=class="num">1;i<=class="num">1000;i++)