3. 时间序列分解:趋势、季节性与残差

时间序列分解,说白了就是把一串乱糟糟的数据拆成几块有规律的东西。我刚开始做量化的时候,面对一堆价格数据,第一反应就是直接建模。结果呢?模型跑出来一塌糊涂。后来才明白,不先把数据拆开看看,就像医生不拍片子直接开药,太莽撞了。

今天咱们就聊聊怎么拆。核心就三个成分:趋势季节性残差。再加上两种拆法:加法模型乘法模型

3.1 三个成分,各是什么?

先给个直观理解:

  • 趋势(Trend):长期来看,数据是往上走还是往下走。比如A股过去十年,整体是震荡向上的。注意,是“长期”,不是短期波动。
  • 季节性(Seasonality):固定周期内的重复模式。比如电商销售额,每年双十一前后都会冲一波。周期可以是年、季度、月,甚至一周。
  • 残差(Residual):去掉趋势和季节性之后,剩下的随机波动。说白了就是“噪音”。如果残差里还有规律,说明你分解得不够干净。

我个人的习惯是,拿到数据先画个图。看一眼趋势,再找找有没有周期性波动。如果连图都不看就上模型,那跟闭着眼开车差不多。

3.2 加法模型 vs 乘法模型

这两种模型,区别在于成分之间怎么组合。

模型 公式 适用场景
加法模型 Y = T + S + R 季节性波动幅度不随趋势变化
乘法模型 Y = T × S × R 季节性波动幅度随趋势放大或缩小

举个例子。你想想看,一家小公司的月销售额,季节性波动可能是±10万。如果公司做大了,销售额翻倍,季节性波动可能变成±20万。这时候用乘法模型更合适。如果波动幅度一直不变,那就用加法模型。

核心判断标准:看季节性波动的幅度是否与趋势水平成正比。

我在项目中遇到过一件事。有一次分析某商品的日销量数据,趋势是缓慢上升的,但季节性波动看起来越来越大。我一开始用了加法模型,结果残差里还残留着明显的季节性模式。后来换成乘法模型,残差才变得干净。嗯,这里要注意:选错模型,残差会“说谎”

3.3 怎么分解?经典方法

最常用的方法是移动平均分解。步骤很简单:

  1. 用移动平均估计趋势 T。
  2. 从原序列中减去趋势,得到“去趋势序列”。
  3. 对去趋势序列按周期平均,得到季节性成分 S。
  4. 从原序列中减去 T 和 S,得到残差 R。

如果是乘法模型,步骤类似,只是把减法换成除法。

下面给一段Python代码,用statsmodels库实现加法分解。我个人习惯用这个库,因为它稳定,坑少。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose

# 生成模拟数据:趋势 + 季节性 + 噪音
np.random.seed(42)
dates = pd.date_range('2020-01-01', periods=365, freq='D')
trend = np.linspace(100, 200, 365)
seasonality = 10 * np.sin(2 * np.pi * np.arange(365) / 30)
noise = np.random.normal(0, 2, 365)
data = trend + seasonality + noise

# 分解
result = seasonal_decompose(data, model='additive', period=30)

# 画图
result.plot()
plt.show()

这段代码跑完之后,你会看到四张图:原始数据、趋势、季节性、残差。一眼就能看出分解得干不干净。

小技巧:如果数据是日频,周期参数 period 要设对。比如周周期设7,月周期设30。设错了,分解出来的季节性就是错的。我曾经因为把月周期设成365,结果季节性完全看不出规律,折腾了半天才发现是参数问题。

3.4 避坑指南:残差里还有规律怎么办?

分解完之后,一定要看一眼残差图。如果残差里还有明显的周期性或趋势,说明分解不彻底。常见原因有两个:

  • 周期选错了:比如数据有双周期(周周期和月周期),你只分解了一个。
  • 模型选错了:加法模型和乘法模型搞反了。

我曾经遇到一个案例,某金融时间序列的残差里总是有“尖峰”。后来发现,是因为数据里有一个异常值,把移动平均拉偏了。处理办法是:先做异常值检测,再分解。顺序很重要。

警告:不要盲目相信分解结果。尤其是金融数据,经常有结构性突变(比如政策变化、黑天鹅事件)。这些突变会被分解到残差里,但其实是“信号”而不是“噪音”。

3.5 知识体系总览

下面这张图,是我自己总结的时间序列分解核心逻辑。你看一眼,基本就能把今天的内容串起来。

时间序列分解核心逻辑 原始时间序列 Y 波动幅度是否 随趋势变化? 加法模型 Y=T+S+R 乘法模型 Y=T×S×R 趋势 T | 季节性 S | 残差 R 趋势 T | 季节性 S | 残差 R

这张图的核心就一句话:先判断波动幅度是否随趋势变化,再选模型,最后拆出三个成分。别搞反了顺序。

3.6 实战中的一点感悟

时间序列分解这件事,看起来简单,但做起来容易翻车。我个人的经验是:

  • 先画图,再分解。图能告诉你很多信息,比如有没有缺失值、有没有异常点。
  • 分解之后,一定要检查残差。残差如果还有规律,说明你漏掉了什么。
  • 不要迷信自动分解。有些库的默认参数不一定适合你的数据。

说白了,分解不是目的,目的是理解数据背后的生成机制。你拆得越干净,后续建模就越有底气。


公众号:蓝海资料掘金营,微信deep3321