SSA就是奇异谱分析。
奇异谱分析是近年来兴起的一种研究非线性时间序列数据的强大的方法。它根据所观测到的时间序列构造出轨迹矩阵,并对轨迹矩阵进行分解、重构,从而提取出代表原时间序列不同成分的信号,如长期趋势信号、周期信号、噪声信号等,从而对时间序列的结构进行分析,并可进一步预测。
说的通俗点,我们平时用均线,但是有一个问题,均线虽然算法本质上有平滑噪音的含义,但是有时候,也把重要的信息给平滑掉了。所以,我们是不是除了平滑这样的方法之外,要开拓新的方法来分离噪音和有用信息呢。
图像的压缩给我们一个很重要的启示,就是谱分解,如果不知道什么是谱分解的话,只要知道,这是一种先分解,然后获取重要信息的一种方法即可。
奇异谱分解的基本思想很简单,分成如下几个步骤:
2.1将时间序列转化为轨迹矩阵
假设有一个时间序列,当然,对于我们而言,就是股价:Y(T)=(y(1),⋯,y(T))
X=(y1,y2,y3,⋯ym;
y2,y3,y4,⋯ym+1;
…
…
yn,yn+1,yn+2,⋯,yT)
就变成了这样一个n*m的矩阵。
其中,m为选取的窗口长度,可以当做MA中的窗口长度一样理解。n=T-m+1。
2.2 SVD分解与矩阵重构
计算X.T*X并对其进行奇异值分解(SVD),从而得到其m个特征值
λ1≥λ2≥⋯≥λm≥0
然后按照从大到小的原则进行矩阵重构。笔者建议大家看一下SVD分解的相关内容,可以更好的理解这一部分。
假设重构后的矩阵为
X=(x1,1 x1,2 x1,3 ⋯ x1,m;
x2,1
x2,2 x2,3 ⋯ x2,m+1
…
…
xn,1
xn,2 xn,3 ⋯ xn,n+m−1)
2.3序列重构
可是我们要的是像MA一样的线呀,现在这个显然不是,所以我们要再把矩阵变成时间序列。方法还是有很多的,比如最常用的有对角相加:
y1=x1,1 y2=(x1,2 + x2,1)/2 y3=(x1,3 + x2,2 + x3,1)/3
…
2.4 接下来,我们就用代码实现上面的这些步骤。
def get_window_matrix(self, input_array, t, m): # 将时间序列变成矩阵 temp = [] n = t - m + 1 for i in range(n): temp.append(input_array[i:i +
m]) window_matrix =
np.array(temp) return
window_matrix def svd_reduce(self,
window_matrix): # svd分解 u, s, v =
np.linalg.svd(window_matrix) m1,
n1 = u.shape m2, n2 = v.shape index = s.argmax() # get the biggest index u1 = u[:, index] v1 = v[index] u1 = u1.reshape((m1, 1)) v1 = v1.reshape((1, n2)) value = s.max() new_matrix = value * (np.dot(u1, v1)) return new_matrix def recreate_array(self, new_matrix, t,
m): # 时间序列重构 ret = [] n = t - m + 1 for p in range(1, t + 1): if p < m: alpha = p elif p > t - m + 1: alpha = t - p + 1 else: alpha = m sigma = 0 for j in range(1, m + 1): i = p - j + 1 if i > 0 and i < n + 1: sigma += new_matrix[i -
1][j - 1] ret.append(sigma /
alpha) return ret def SSA(self, input_array, t, m): window_matrix =
self.get_window_matrix(input_array, t, m)
new_matrix = self.svd_reduce(window_matrix) new_array =
self.recreate_array(new_matrix, t, m)
return new_array
这里,我们调用SSA函数就可以获得重构后的时间序列。
那么按照逻辑,重构后的时间序列我们选取最后一个,就是我们要的当天的SSA了,然后就可以像趋势线一样使用。