English Русский Deutsch 日本語
preview
MQL5 中的奇异谱分析(SSA)

MQL5 中的奇异谱分析(SSA)

MetaTrader 5示例 |
22 1
Francis Dube
Francis Dube

什么是 SSA?

MetaTrader 5(MT5)最新版本已将 OpenBLAS 运算库初步集成到核心向量与矩阵数据类型中。其中,奇异谱分析(SSA)相关的一系列方法尤为值得关注。本文将深入讲解 MQL5 中全新的 SSA 工具,拆解其在行情分析与预测中的使用方法。本指南旨在为希望充分发挥 SSA 分析潜力的交易者提供参考。我们将深入剖析 SSA 的核心方法,拆解其两步式分解与重构流程。更重要的是,我们会讲解新增的 SSA 向量方法各自的作用,并演示如何解读、最优组合其输出结果,以获取可执行的交易决策依据。

奇异谱分析是一种非参数化技术,专门用于时间序列数据的分析与预测。其核心目标是将时间序列分解为若干个可加分量,通常包含:缓慢变化的趋势项、各类周期项、以及残差噪声项。SSA 的显著特点是:对底层数据生成过程几乎不做预设假设。SSA 的理论基础融合了统计学与信号处理理论。本质上,SSA 基于谱分解原理,通过在重构嵌入空间中分析主成分,揭示时间序列的频率特征。你可以将其理解为专门适配时间序列数据的主成分分析(PCA):借助降维原理,挖掘被噪声或复杂交互关系掩盖的隐藏结构与规律。



MQL5 中的 SSA

在 MQL5 中,SSA 计算已原生集成为向量数据类型的方法,同时也在 Alglib 数学库中提供了实现。Alglib 版 SSA 的优势主要在于实时行情处理,而直接通过向量调用的全新 SSA 功能更适合探索性数据分析。注意:本文主要讲解实数运算相关用法,MQL5 也提供了等效的复数运算方法,使用逻辑一致,仅解读方式需适配复数域。

所有新增的向量 SSA 方法,第一个必填参数都是窗口长度。该参数决定了时间序列如何转换为更高维度的结构 ——轨迹矩阵。你可能会问:为什么需要构建高维结构? 答案就藏在 SSA 与 PCA 的关联中。要知道,PCA 是应用于多变量数据集的降维技术。而 SSA 会将单变量时间序列重构为类似多变量数据集的结构。实现方式是:将时间序列按等长片段排列为矩阵行。其中,每一行的长度由窗口长度参数定义。

举个例子:时间序列Y=[y1​,y2​,y3​,y4​,y5​,y6​],总长度 N=6。 如果设置窗口长度 L=3,就会生成如下轨迹矩阵。

轨迹矩阵

矩阵的行数 R 计算公式:R=N−L+1。本例中:R=6−3+1=4。最终生成一个 R×L 维度的矩阵(本例为 4×3),这就是轨迹矩阵。该矩阵的反对角线上呈现出典型的汉克尔矩阵(Hankel Matrix)特征。构建轨迹矩阵是 SSA 方法的第一步。因此,窗口长度是 SSA 的核心参数:它直接决定轨迹矩阵的维度,进而显著影响谱分解的分辨率与分量分离效果。

为了清晰讲解 SSA 的原理,我们将用一个确定性序列演示其应用,序列样式如下。

示例序列

该序列由预设的可叠加分量构成:趋势项 + 两组周期项 + 随机噪声。将这些分量叠加后,会得到一段看似无规律的序列。SSA 的目标就是挖掘出这些隐藏的底层分量。实现方式是:对轨迹矩阵或其协方差矩阵进行分解,得到特征模态—— 和 PCA 原理一致,这些模态会揭示序列的主成分。



分量相对贡献度与累计贡献度

MQL5 向量方法SingularSpectrumAnalysisSpectrum() 会输出一个向量,代表序列各分量的相对贡献度。该向量内的实数总和为 1,数值按降序排列,表示每个分量的占比权重。这些贡献度对应矩阵分解计算出的特征值相对大小。

//---
   vector relative_contributions;
   if(!full_process.SingularSpectrumAnalysisSpectrum(WindowLen,relative_contributions))
     {
      Print(" error ", GetLastError());
      return;
     }
//---
   relative_contributions*=100.0;
   vector cumulative_contributions = relative_contributions.CumSum();

计算相对贡献度的累加和,即可得到累计贡献度。通过这些数值,我们能快速确定:最少需要选取多少个分量,才能实现对原始序列的高精度拟合。相对贡献度的图表通常会呈现出明显的近似平台期,这表明部分分量的贡献度数值相近。这种数值相近性,通常意味着这些分量共同代表了同一个周期要素。

下图是我们示例序列的相对贡献度与累计贡献度图表。

示例序列的相对贡献度

图表显示:前两个分量分别贡献了序列总方差的约 68% 和 12%。

示例序列的累计贡献度

仅前五个分量,就占据了总方差的 98% 以上。相对贡献度图表呈现出独特的形态,清晰体现出前 5 个分量的主导地位。将主导分量与其余分量区分开的临界点,通常被称为拐点(肘点);低于该水平的分量被称为噪声基底。该临界点可粗略估算信号与噪声的分离边界。相对贡献度图表的另一个显著特征是:第二、第三个分量紧密聚集,与第四、第五个分量明显区分开。这表明这些成组的分量彼此相关,可能分别代表序列中独有的特征。



序列分量提取

完成对示例序列的分析后,我们已经明确了决定序列整体走势的主要分量。若要评估这些分量的规律性,将其可视化会是很有效的方式。此时,向量方法SingularSpectrumAnalysisReconstructComponents()就能发挥作用。该方法最核心的输出是分量序列矩阵。但需要注意:尽管 MQL5 官方文档说明矩阵的列代表估算的分量序列,但该方法实际是将每个分量序列存储为矩阵的行。此外,该方法的向量输出结果中,还包含序列表征矩阵分解后的原始特征值。

//---
   matrix components;
   vector eigvalues;
   if(!full_process.SingularSpectrumAnalysisReconstructComponents(WindowLen,components,eigvalues))
     {
      Print(" error ", GetLastError());
      return;
     }
//---

分量序列矩阵的行按照相对贡献度从大到小排列。因此,第一行对应的是最大特征值的分量,同时也是相对贡献度最高的分量。下图展示了示例序列的所有分解分量。

示例序列的分解分量

如果将其与原始分量的图表对比,你可能会发现一些偏差。这恰恰说明:SSA 分解并非绝对精确。该方法无法精准识别出序列的真实周期分量,只能对这些分量进行最优拟合与估算。不过,将所有独立的分量序列相加,最终可以还原出原始序列。



滤波处理

得到分量序列集合后,我们可以结合 SSA 分析结果,区分哪些分量代表底层有效信号,哪些代表非确定性噪声。如果我们的核心目标是提取主导周期,可以直接剔除相对贡献度较低的分量,从而生成滤波后的序列。这种操作的前提假设是:贡献度较低的分量均为掩盖主信号的噪声。

用户可以直接通过SingularSpectrumAnalysisReconstructSeries()方法对序列执行滤波操作。只需指定需要纳入滤波序列的主导分量数量即可。

//---
   vector filtered;
   if(!full_process.SingularSpectrumAnalysisReconstructSeries(WindowLen,FilterComponents,filtered))
     {
      Print(" error ", GetLastError());
      return;
     }

SSA 方法通常擅长分离噪声,但其效果取决于数据中噪声的类型。仅通过剔除低贡献度分量,往往无法彻底分离噪声。这也会直接影响有效信号、趋势或特定周期分量的提取效果。对这些分量的解读,通常需要通过显著性统计检验进行验证。影响特定分量分离的另一个因素是强趋势:趋势的主导性可能会掩盖数据中其他低频震荡信号。

示例序列的滤波结果



预测

SSA 方法最实用的功能之一就是时间序列预测。该功能由SingularSpectrumAnalysisForecast()方法实现。时间序列完成分解与重构后,预测步骤通常采用递归预测算法。该算法基于重构分量普遍满足的线性递推关系(LRR)实现。其核心假设是:这些重构分量遵循可预测的规律模式。算法会根据奇异向量和重构序列计算出一组系数。这些系数代表了重构信号中历史数据与未来数据的线性关系。预测新数据点时,算法会对重构序列前窗口长度个数值进行线性加权组合(权重为计算出的系数)。该过程会迭代执行,从而生成连续的多步预测值。

//---
   vector forecast;
   if(!full_process.SingularSpectrumAnalysisForecast(WindowLen,FilterComponents,ForecastLen,forecast))
     {
      Print(" error ", GetLastError());
      return;
     }
//---

显而易见,这类预测假设历史模式会在未来完全重现。当然,在现实世界的时间序列中,这种情况几乎不可能成立。尽管如此,SSA 依然具备实用价值 —— 通过聚焦具有规则波形的特定分量,能让复杂行情过程更具可预测性。



参数选择与预处理

我们已经明确,SSA 对序列的分解无法提取出时间序列的真实周期分量。它仅能提取分量的估算值。这是该方法的一个明显局限性,而SSA 对窗口长度的高度敏感性,会进一步加剧这一局限。窗口长度的选择可根据分解目标确定。如果核心目标是分离趋势,窗口长度越大越好。如果更关注震荡分量,则需要匹配震荡周期;例如:寻找周期为 20 的周期分量时,可将窗口长度设为 20。

学术文献中的实证研究表明:窗口长度 L 决定了震荡信号的解析范围,可识别的周期区间为 L/5 至 L。问题在于,目标分量的周期通常无法提前预知,因此需要大量试错调整。通用经验法则:将窗口长度设置为目标序列长度的 1/2 到 2 倍之间。更长的窗口长度用于放大慢变分量(趋势),而更短的窗口长度用于捕捉更精细的细节。

除了对窗口长度敏感,使用者还需注意:时间序列中的强趋势会影响分解结果。强趋势会掩盖序列中的其他低频分量。解决该问题的核心方法:在执行 SSA 之前,对原始序列进行去趋势处理。可采用的预处理方式包括中心化或移除线性趋势,代码示例如下:

//---
   if(m_detrend)
     {
      vector reg = m_buffer.LinearRegression();
      m_buffer -= reg;
     }
//---

在滤波或预测时,确定需要选择多少个分量,可以借助相对贡献度与累计贡献度图表。在相对贡献度图表中,核心是找到肘点—— 用于区分信号与噪声。图表中,信号对应的点会与逐步趋近于零的噪声点形成明显分界。观察分解过程中原始特征值的衰减曲线,也能看到同样的分界特征。另一种可行方案:设定一个目标方差占比(通常为 85%~95%),然后在累计贡献度序列中,找到满足该占比所需的分量数量。



分量分组

我们知道,SSA 分解无法完美还原序列的真实底层分量 —— 这一点在简单示例中已经得到验证。我们得到的是一组近似真实分量的估算序列。我们只需要确定如何组合这些估算分量,就能更清晰地识别出定义数据规律的真实要素。这可以通过构建分量序列的加权相关矩阵实现。加权相关矩阵用于衡量每一对分量序列偏离正交状态的程度。如果一对分量序列完全正交,则它们大概率是相互独立的分量。

相关性越高,说明这一对分量越应该合并。下方代码片段展示了一个通用方法:输入分量序列矩阵与 SSA 分解的窗口长度参数,计算加权相关矩阵。该函数声明在文章附带的 ssa.mqh 头文件中。 

//+------------------------------------------------------------------+
//| component correlations                                           |
//+------------------------------------------------------------------+
matrix component_corr(ulong windowlen,matrix &components)
  {
   double w[];
   ulong fsize = components.Cols();
   ulong r = fsize - windowlen + 1;
  
   for(ulong i = 0; i<fsize; i++)
     {
      if(i>=0 && i<=windowlen-1)
         w.Push(i+1);
      else
         if(i>=windowlen && i<=r-1)
            w.Push(windowlen);
         else
            if(i>=r && i<=fsize-1)
               w.Push(fsize-i);
     }

   vector weights;
   weights.Assign(w);
   ulong d = windowlen;

   vector norms(d);
   matrix out = matrix::Identity(d,d);

   for(ulong i = 0; i<d; i++)
     {
      norms[i] = weights.Dot(pow(components.Row(i),2.0));
      norms[i] = pow(norms[i],-0.5);
     }

   for(ulong i = 0; i<d; i++)
     {
      for(ulong j = i+1; j<d; j++)
        {
         out[i][j] = MathAbs(weights.Dot(components.Row(i)*components.Row(j))*norms[i]*norms[j]);
         out[j][i] = out[i][j];
        }
     }

   return out;
  }

下方展示了示例序列前六大分量的分量相关系数矩阵局部片段。

分量相关系数矩阵(局部)

图表中可以看到,索引 (1:2) 对应的两个分量高度相关,印证了第 2、3 号分量存在关联性,而索引 (3:4) 则反映第 4、5 号分量之间的关联关系。该分析结论与前文相对贡献度图表的目视观察结果完全吻合。据此可以推断:这两组关联分量,对应示例序列中的周期性成分。而排名首位的独立分量特征明显,大概率代表趋势项。结合前文累计贡献度可知,这五个分量合计贡献占比超过 98%,其余分量则基本可判定为噪声。



价格序列分解实操演示

本节展示一款以EA 智能交易系统实现的应用案例,可对任意一段价格样本进行分量分解与可视化查看。该工具搭载图形交互界面,支持自定义交易品种、时间周期与价格序列长度,一键完成序列展示与 SSA 分解。同时提供分解前去趋势可选功能,也可按需查看相对贡献度、累计贡献度图表。下图为该工具运行截图:以欧美货币对(EURUSD)收盘价为例,底部图表展示其中一组分解后的独立分量。

价格分解工具演示


结论

本文系统介绍了 MQL5 中全新的奇异谱分析(SSA)工具,重点讲解了向量数据类型基于 OpenBLAS 的新增底层能力。文中对 SSA 分析方法进行了通俗完整的概述,刻意弱化复杂数学推导,侧重实操应用。总而言之,奇异谱分析是量化交易者与数据分析人员的实用工具,但想要充分发挥其效用,必须合理选择参数,并理解其运行特性与局限性。本文提及的所有完整代码,均附于文末可供下载使用。 

文件名  文件描述 
MQL5/include/ssa.mqh
该头文件包含了分量分组章节中所描述的、用于计算分量相关系数的函数定义。
MQL5/scripts/SSA_Filtered_Demo.mq5
该脚本用于演示基于 SSA 的滤波功能。
MQL5/scripts/SSA_Decomposition_Demo.mq5
该脚本用于演示基于 SSA 的序列分解功能。
MQL5/scripts/SSA_ComponentContributions_Demo.mq5
该脚本用于演示分量相对贡献度的可视化展示。
MQL5/scripts/SeriesPlot.mq5
该脚本用于绘制本文所述示例序列的各分解分量图表。
MQL5/experts/SSA_PriceDecomposition.ex5
该 EA 程序可用于展示任意价格序列的分解结果。
MQL5/experts/SSA_PriceDecomposition.mq5
上述 EA 的源代码文件。

本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/18777

附加的文件 |
MQL5.zip (37 KB)
最近评论 | 前往讨论 (1)
Stanislav Korotky
Stanislav Korotky | 10 7月 2025 在 16:18

在很短的时间内看到关于同一主题的如此密切相关的文章(即使其中一篇文章最初是用俄语写的),真是奇怪。

文章

一维奇异谱分析

Evgeny Chernish, 04/23/2025 11:23

这是一种分析时间序列的有效方法,可将序列的复杂结构分解为趋势、季节(周期)波动和噪声等简单成分。

MQL5自优化智能交易系统(第八部分):多策略分析(3)—— 加权投票机制 MQL5自优化智能交易系统(第八部分):多策略分析(3)—— 加权投票机制
本文将探讨如何确定集成策略中最优的策略数量 —— 这是一个复杂问题,而借助MetaTrader 5的遗传算法优化器可以轻松解决。同时,我们也会使用MQL5云端计算作为核心资源,加速回测与优化过程。具体而言,本篇内容将为后续开发统计评估模型奠定基础,用于基于初始集成结果评估并改进交易策略。
构建动态多品种EA(第三部分):均值回归与动量策略 构建动态多品种EA(第三部分):均值回归与动量策略
在本文中,我们将继续讲解构建动态多品种智能交易系统(EA)的第三部分内容,重点聚焦于均值回归策略与动量交易策略的融合。我们将详细拆解如何检测价格对均值的偏离(通过Z-分数)并据此执行交易,以及如何在多个外汇对上测算动量,以此确定交易方向。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
通过协整股票实现统计套利(第一部分):恩格尔 - 格兰杰检验与约翰森协整检验 通过协整股票实现统计套利(第一部分):恩格尔 - 格兰杰检验与约翰森协整检验
本文旨在以适合交易者且通俗易懂的方式,介绍最常用的协整检验方法,并附带一份解读检验结果的简易指南。恩格尔 - 格兰杰检验与约翰森协整检验,能够识别出具备长期联动关系、且在统计上显著的资产配对或资产组合。约翰森检验尤其适用于包含三种及以上资产的投资组合,因其可一次性测算出所有协整向量的强度。