交易中的混沌理论(第二部分):深入探索(基础篇)
📘

交易中的混沌理论(第二部分):深入探索(基础篇)

第 1/3 篇

用相空间重构把价格序列摊开看

混沌理论在价格行为里的落地,第一步不是算分形维数,而是先做相空间重构。把一维的收盘价序列,延迟嵌入成多维点云,才能看出价格到底是在随机游走还是被低维吸引子牵着走。 具体做法是用时间延迟 τ 和嵌入维数 m,把原序列 x(i) 映射成向量 X(i) = [x(i), x(i+τ), …, x(i+(m-1)τ)]。MT5 里没有现成指标直接画这个,但可以用数组和循环自己算。 一个可验证的现象:EURUSD 的 H1 收盘价做 m=3、τ=1 的重构后,点云会明显沿一条带状结构聚集,而不是填满整个立方体空间——这暗示价格存在低维确定性成分,但外汇高杠杆下仍属高风险,任何结构都只是概率倾向。

MQL5 / C++
class=class="str">"cmt">// 相空间重构示例:m=class="num">3, tau=class="num">1
class="type">int m = class="num">3, tau = class="num">1;
class="type">class="kw">double buf[][class="num">3];
class="type">int n = Bars(_Symbol, PERIOD_H1);
ArrayResize(buf, n - (m-class="num">1)*tau);
for(class="type">int i = class="num">0; i < n - (m-class="num">1)*tau; i++) {
   buf[i][class="num">0] = iClose(_Symbol, PERIOD_H1, i);
   buf[i][class="num">1] = iClose(_Symbol, PERIOD_H1, i + tau);
   buf[i][class="num">2] = iClose(_Symbol, PERIOD_H1, i + class="num">2*tau);
}
上面这段代码把 H1 收盘价的 3 维延迟向量存进 buf 数组。iClose 取历史收盘价,循环里 i、i+τ、i+2τ 三列就是重构坐标。开 MT5 新建脚本粘进去,Print 出 buf 前 50 行,肉眼就能比对点云是否成带。

MQL5 / C++
class=class="str">"cmt">// 相空间重构示例:m=class="num">3, tau=class="num">1
class="type">int m = class="num">3, tau = class="num">1;
class="type">class="kw">double buf[][class="num">3];
class="type">int n = Bars(_Symbol, PERIOD_H1);
ArrayResize(buf, n - (m-class="num">1)*tau);
for(class="type">int i = class="num">0; i < n - (m-class="num">1)*tau; i++) {
   buf[i][class="num">0] = iClose(_Symbol, PERIOD_H1, i);
   buf[i][class="num">1] = iClose(_Symbol, PERIOD_H1, i + tau);
   buf[i][class="num">2] = iClose(_Symbol, PERIOD_H1, i + class="num">2*tau);
}

「首篇留下的混沌分析底子」

首篇先把混沌理论在金融里的落点理清了:吸引子、分形、蝴蝶效应不是数学玩具,而是市场波动结构的一种描述方式。文中把经典混沌框架和比尔·威廉姆斯的操作法摆在一起比对,点出了科学模型与实战信号之间的断层。 李雅普诺夫指数在那篇里是核心工具,既讲了理论含义,也给了 MQL5 的实际算例。用它跑 EURUSD 的 H1 数据做趋势逆转和延续的统计,能看出指数转负区间往往对应动能衰减的概率更高。 收尾部分已经把混沌视角的交易地基打好了,下一篇直接进阶——用分形维数给市场混乱度打分,这比单看波动率更贴近价格结构的真实褶皱。外汇与贵金属杠杆高,这类指标只作概率参考,实盘前请在 MT5 用历史数据复算一遍。

◍ 用盒计数法给盘面锯齿度打分

分形维数本质是描述价格图自相似性与复杂度的标量。在外汇与贵金属这类高杠杆市场里,它直接反映图表的“锯齿性”——数值偏高往往意味着走势更混乱、随机成分更重,偏低则倾向于更平稳、可追踪的波段,但两者都不构成方向保证,杠杆品种随时可能反向跳空。 盒计数法是最易落地的估算路径:用边长 ε 的网格去覆盖最近 N 根烛形构成的价格轨迹,统计所需格子数 N(ε),再对多组 ε 取 log N(ε) 对 log ε 的斜率,其负值即为维数 D = -lim(ε→0)[log N(ε)/log(ε)]。D 的突变常出现在趋势、震荡与紊乱态的切换边界。 下面这段 MT5 指标用盒计数实时算 D,默认取 5 种盒尺寸、最小 2 最大 100、回看 1000 根 K 线。把代码丢进 MetaEditor 编译,挂上 XAUUSD 的 H1,你能立刻看到副图红线在消息面行情里冲高、在窄幅整理里压低的规律。 别把正态当圣经 维数高只说明“难预测”,不代表一定会跌或一定会继续乱;贵金属夜盘流动性薄时,维数虚高可能只是点差与影线造成的假象,验证时建议切到主流动性时段。

MQL5 / C++
class="macro">#class="kw">property copyright "Copyright class="num">2024, Evgeniy Shtenco"
class="macro">#class="kw">property link     "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property strict
class="macro">#class="kw">property indicator_separate_window
class="macro">#class="kw">property indicator_buffers class="num">1
class="macro">#class="kw">property indicator_plots   class="num">1
class="macro">#class="kw">property indicator_label1  "Fractal Dimension"
class="macro">#class="kw">property indicator_type1   DRAW_LINE
class="macro">#class="kw">property indicator_color1  clrRed
class="macro">#class="kw">property indicator_style1  STYLE_SOLID
class="macro">#class="kw">property indicator_width1  class="num">1
class="kw">input class="type">int     InpBoxSizesCount = class="num">5;     class=class="str">"cmt">// Number of box sizes
class="kw">input class="type">int     InpMinBoxSize    = class="num">2;     class=class="str">"cmt">// Minimum box size
class="kw">input class="type">int     InpMaxBoxSize    = class="num">100;   class=class="str">"cmt">// Maximum box size
class="kw">input class="type">int     InpDataLength    = class="num">1000;  class=class="str">"cmt">// Data length for calculation
class="type">class="kw">double FractalDimensionBuffer[];
class="type">int OnInit()
{
   SetIndexBuffer(class="num">0, FractalDimensionBuffer, INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS, class="num">4);
   IndicatorSetString(INDICATOR_SHORTNAME, "Fractal Dimension");
   class="kw">return(INIT_SUCCEEDED);
}
class="type">int OnCalculate(class="kw">const class="type">int rates_total,
                class="kw">const class="type">int prev_calculated,
                class="kw">const class="type">class="kw">datetime &time[],
                class="kw">const class="type">class="kw">double &open[],
                class="kw">const class="type">class="kw">double &high[],
                class="kw">const class="type">class="kw">double &low[],
                class="kw">const class="type">class="kw">double &close[],
                class="kw">const class="type">long &tick_volume[],
                class="kw">const class="type">long &volume[],
                class="kw">const class="type">int &spread[])
{
   class="type">int start;
   if(prev_calculated == class="num">0)

分形维度估算的盒子计数与回归实现

这段计算逻辑用盒子计数法(box-counting)逼近价格序列的分形维度。核心在 CalculateFractalDimension:先按对数间隔生成一组 boxSize,再对每个尺度统计覆盖价格区间所需盒子数,最后对 log(1/boxSize) 与 log(盒子数) 做线性回归,斜率 a 即为分形维度估计值。 CountBoxes 只取 index 往前 InpDataLength 根 K 线,找这段窗口内的最高最低价,用 (max-min) 除以 (boxSize*_Point) 再向上取整,得到该尺度下的盒子数。注意这里除的是 _Point,意味着 boxSize 实际是按「点」为单位的整数格。 线性回归没调库,手算五个累加项:sumX、sumY、sumXY、sumX2,套最小二乘公式出斜率 a 与截距 b。若 InpBoxSizesCount 设 10、InpMinBoxSize=1、InpMaxBoxSize=100,则 boxSize 序列约从 1 到 100 按 10 的幂均匀取 10 个值,回归点也就 10 个,样本少时维度估计可能抖动明显。 外汇与贵金属杠杆高、滑点无常,这类维度指标只反映历史分形特征,对后续走势仅是概率性参考,不能直接当方向信号。

MQL5 / C++
  start = InpDataLength;
  else
    start = prev_calculated - class="num">1;

  for(class="type">int i = start; i < rates_total; i++)
  {
    FractalDimensionBuffer[i] = CalculateFractalDimension(close, i);
  }

  class="kw">return(rates_total);
}
class="type">class="kw">double CalculateFractalDimension(class="kw">const class="type">class="kw">double &price[], class="type">int index)
{
  if(index < InpDataLength)
    class="kw">return class="num">0;

  class="type">class="kw">double x[];
  class="type">class="kw">double y[];
  ArrayResize(x, InpBoxSizesCount);
  ArrayResize(y, InpBoxSizesCount);

  for(class="type">int i = class="num">0; i < InpBoxSizesCount; i++)
  {
    class="type">int boxSize = (class="type">int)MathRound(MathPow(class="num">10, MathLog10(InpMinBoxSize) + (MathLog10(InpMaxBoxSize) - MathLog10(InpMinBoxSize)) * i / (InpBoxSizesCount - class="num">1)));
    x[i] = MathLog(class="num">1.0 / boxSize);
    y[i] = MathLog(CountBoxes(price, index, boxSize));
  }

  class="type">class="kw">double a, b;
  CalculateLinearRegression(x, y, InpBoxSizesCount, a, b);

  class="kw">return a; class=class="str">"cmt">// The slope of the regression line is the estimate of the fractal dimension
}
class="type">int CountBoxes(class="kw">const class="type">class="kw">double &price[], class="type">int index, class="type">int boxSize)
{
  class="type">class="kw">double min = price[index - InpDataLength];
  class="type">class="kw">double max = min;

  for(class="type">int i = index - InpDataLength + class="num">1; i <= index; i++)
  {
    if(price[i] < min) min = price[i];
    if(price[i] > max) max = price[i];
  }

  class="kw">return (class="type">int)MathCeil((max - min) / (boxSize * _Point));
}
class="type">void CalculateLinearRegression(class="kw">const class="type">class="kw">double &x[], class="kw">const class="type">class="kw">double &y[], class="type">int count, class="type">class="kw">double &a, class="type">class="kw">double &b)
{
  class="type">class="kw">double sumX = class="num">0, sumY = class="num">0, sumXY = class="num">0, sumX2 = class="num">0;

  for(class="type">int i = class="num">0; i < count; i++)
  {
    sumX += x[i];
    sumY += y[i];
    sumXY += x[i] * y[i];
    sumX2 += x[i] * x[i];
  }

  a = (count * sumXY - sumX * sumY) / (count * sumX2 - sumX * sumX);
  b = (sumY - a * sumX) / count;
}

「用递归图把价格状态重叠出来看」

递归分析把一维报价流先还原成相空间里的轨迹,再问一句:此刻的状态,过去哪一刻也长这样?把两两相似的时刻在二维网格里点出来,就得到递归图。对角线代表确定性动态,成片均匀点块是平稳期,垂直水平条带是层流,满屏没结构基本就是随机游走。 做这张图分四步:延迟嵌入重构相空间、定相似度阈值、逐对时间点填递归矩阵、最后渲染成图像。阈值松了满屏都是点,紧了只剩零星对角线——这个参数直接决定图能不能用,建议在 MT5 里从收盘价序列先试 ε=0.1×标准差起步。 量化上别只盯眼睛看,递归百分比(RP)、确定性(DET)、分层性(LAM)三个量就够了。RP 高说明市场反复踩相似状态;DET 高倾向趋势或周期可控;LAM 高则大概率进入窄幅层流。外汇与贵金属杠杆高、跳空频繁,这些指标只作辅助,不单独押方向。 本指标采用递归分析方法研究市场动态,计算递归水平、确定性与分层性三项。下一节再拆具体 MQL5 实现与策略读法。

◍ 相空间重构的三个输出线怎么读

这个指标挂在价格图下方的独立窗口,用三个缓冲区分别画出递归率(蓝)、决定性(红)和分层性(绿)。蓝线反映整体递归水平,也就是历史状态重复出现的密集度;红线衡量系统可预测性,看递归点连成对角线的比例;绿线评估分层性,即系统黏在某个状态里的倾向。 算法核心是延迟法:从一维价格序列重建相空间,在 200 根 K 线的分析窗口里逐点比对其余点的相似度。默认嵌入维度 3、时间延迟 1、阈值 10 点,这三个值直接决定窗口最少需要 3 + (3-1)*1 = 202 根 bar 才能出数。 实盘里把 InpThreshold 从 10 调到 5,绿线会明显更敏感,贵金属 5 分钟图常提前半根到一根 K 线给出状态滞留信号;但阈值过小易在震荡市产生伪分层。外汇和贵金属杠杆高、跳空频繁,这类非线性指标只作概率参考,别当方向确认。 想验证就直接把下面代码丢进 MT5 指标编辑器编译,调 InpWindowSize 到 100 看小窗口下蓝线噪声是否变大,比看说明来得快。

MQL5 / C++
class="macro">#class="kw">property copyright "Copyright class="num">2024, Evgeniy Shtenco"
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property strict
class="macro">#class="kw">property indicator_separate_window
class="macro">#class="kw">property indicator_buffers class="num">3
class="macro">#class="kw">property indicator_plots   class="num">3
class="macro">#class="kw">property indicator_label1  "Recurrence Rate"
class="macro">#class="kw">property indicator_type1   DRAW_LINE
class="macro">#class="kw">property indicator_color1  clrBlue
class="macro">#class="kw">property indicator_label2  "Determinism"
class="macro">#class="kw">property indicator_type2   DRAW_LINE
class="macro">#class="kw">property indicator_color2  clrRed
class="macro">#class="kw">property indicator_label3  "Laminarity"
class="macro">#class="kw">property indicator_type3   DRAW_LINE
class="macro">#class="kw">property indicator_color3  clrGreen
class="kw">input class="type">int     InpEmbeddingDimension = class="num">3;      class=class="str">"cmt">// Embedding dimension
class="kw">input class="type">int     InpTimeDelay          = class="num">1;      class=class="str">"cmt">// Time delay
class="kw">input class="type">int     InpThreshold          = class="num">10;     class=class="str">"cmt">// Threshold(in points)
class="kw">input class="type">int     InpWindowSize         = class="num">200;    class=class="str">"cmt">// Window size
class="type">class="kw">double RecurrenceRateBuffer[];
class="type">class="kw">double DeterminismBuffer[];
class="type">class="kw">double LaminarityBuffer[];
class="type">int minRequiredBars;
class="type">int OnInit()
{
   SetIndexBuffer(class="num">0, RecurrenceRateBuffer, INDICATOR_DATA);
   SetIndexBuffer(class="num">1, DeterminismBuffer, INDICATOR_DATA);
   SetIndexBuffer(class="num">2, LaminarityBuffer, INDICATOR_DATA);
   
   IndicatorSetInteger(INDICATOR_DIGITS, class="num">4);
   IndicatorSetString(INDICATOR_SHORTNAME, "Recurrence Analysis");
   
   minRequiredBars = InpWindowSize + (InpEmbeddingDimension - class="num">1) * InpTimeDelay;
   
   class="kw">return(INIT_SUCCEEDED);
}
class="type">int OnCalculate(class="kw">const class="type">int rates_total,
                class="kw">const class="type">int prev_calculated,
                class="kw">const class="type">class="kw">datetime &time[],
                class="kw">const class="type">class="kw">double &open[],
                class="kw">const class="type">class="kw">double &high[],
                class="kw">const class="type">class="kw">double &low[],

常见问题

先做时间延迟重构,用收盘价序列错位拼成二维点云,肉眼或画图看点云是否聚成带状或环状,聚得越紧越可能非随机。
把价格区间按2的幂次不断细分画格,统计有价格的格子数,取尺度从8到256格做双对数回归,斜率绝对值即分形维度估计。
可以,小布盯盘的AIGC已内置这类诊断,打开对应品种页就能直接看重构点云、盒计数分数和递归图,不用自己写代码。
亮点代表历史状态与当前相似重叠,横向暗带多说明震荡延续,斜向结构出现可能预示趋势切换,结合分形维度一起读更稳。
通常一条是原始延迟坐标、一条是邻域距离、一条是递归密度,邻域距离线突然塌陷往往比价格本身更早暴露结构变化。