第1章:滞后特征与差分——时序特征工程的基石
大家好,我是你们这趟旅程的向导。今天咱们聊聊时序特征工程里最基础、也最核心的两个操作:滞后特征和差分。说实话,这两个东西看着简单,但用好了,能让你的模型效果提升一大截。我在量化交易这行摸爬滚打这么多年,见过太多人一上来就上复杂模型,结果连最基本的滞后结构都没搞清楚,最后模型效果还不如一个简单的ARIMA。
好,咱们直接进入正题。
1.1 滞后算子(Lag Operator)——时间序列的“时间机器”
滞后算子,符号是 L,也叫延迟算子。它的作用很简单:把时间序列往回推。
定义上,L * y_t = y_{t-1}。你想想看,这就像给数据装了个“时间机器”,让当前时刻的数据回到过去。更一般地,L^k * y_t = y_{t-k},表示滞后k期。
我个人习惯把滞后算子看作一个“移位指令”。在代码里,它对应pandas的shift()函数。比如:
import pandas as pd
import numpy as np
# 生成示例数据
dates = pd.date_range('2024-01-01', periods=10, freq='D')
data = pd.Series(np.random.randn(10), index=dates, name='price')
# 滞后1期
data_lag1 = data.shift(1)
print(pd.concat([data, data_lag1], axis=1).head())
输出结果:
price price_lag1
2024-01-01 0.123456 NaN
2024-01-02 -0.789012 0.123456
2024-01-03 0.456789 -0.789012
2024-01-04 -0.234567 0.456789
2024-01-05 0.890123 -0.234567
嗯,这里要注意:滞后一期后,第一行会变成NaN。因为t=1时刻没有t=0的数据。这个NaN在建模时要么删掉,要么填充。我建议直接删掉,因为填充会引入偏差。
核心要点:滞后算子本质上是将时间序列的“记忆”显式地表达为特征。在金融时序中,过去的价格、成交量、波动率等信息,往往对当前时刻有预测能力。
1.2 差分运算——让非平稳序列“变乖”
差分,说白了就是计算相邻时刻的差值。一阶差分:Δy_t = y_t - y_{t-1}。季节性差分:Δ_s y_t = y_t - y_{t-s},s是季节周期。
为什么需要差分?因为很多金融时间序列是非平稳的,比如股票价格。非平稳序列的均值和方差会随时间变化,直接建模会出问题。差分之后,序列通常会变得平稳。我个人习惯在建模前,先用ADF检验看序列是否平稳,如果不平稳,就做一阶差分。
举个例子:
# 一阶差分
diff_1 = data.diff(1)
print(diff_1.head())
# 季节性差分(假设周期为7天)
diff_s = data.diff(7)
print(diff_s.head())
输出:
price_diff_1
2024-01-01 NaN
2024-01-02 -0.912468
2024-01-03 1.245801
2024-01-04 -0.691356
2024-01-05 1.124690
我在项目中遇到过一个问题:有些序列需要做二阶差分才能平稳。但要注意,差分阶数越高,信息损失越大。一般一阶差分就够了,最多二阶。千万别为了追求平稳性而过度差分,否则会丢失长期趋势信息。
避坑指南:我曾经在一个高频交易项目中,对价格序列做了三阶差分,结果模型预测效果极差。后来发现,过度差分把价格中的趋势和季节性信息全抹掉了,只剩下噪声。记住:差分是为了让序列平稳,不是为了“干净”。
1.3 收益率计算——金融时序的“通用语言”
在金融领域,我们很少直接对价格建模,而是对收益率建模。原因很简单:价格是非平稳的,收益率通常是平稳的。而且收益率具有可加性,方便跨资产比较。
两种最常见的收益率:
- 简单收益率:
R_t = (P_t - P_{t-1}) / P_{t-1} - 对数收益率:
r_t = ln(P_t / P_{t-1})
对数收益率有个好处:它近似等于简单收益率(当收益率很小时),而且具有时间可加性。比如,一周的对数收益率等于每天对数收益率之和。这在多期收益计算中非常方便。
代码实现:
# 简单收益率
simple_return = data.pct_change()
print(simple_return.head())
# 对数收益率
log_return = np.log(data / data.shift(1))
print(log_return.head())
输出:
simple_return log_return
2024-01-01 NaN NaN
2024-01-02 -7.392857 -7.692308
2024-01-03 1.578947 0.947368
2024-01-04 -0.513514 -0.720720
2024-01-05 1.944444 0.666667
你想想看,当收益率很小时,比如0.1%,简单收益率和对数收益率几乎相等。但当收益率很大时,比如10%,两者就有明显差异了。我个人习惯在回测和风险管理中用对数收益率,因为它更符合正态分布假设,而且计算多期收益时不会出现负价格的问题。
小技巧:如果你需要计算多期累计收益,用对数收益率相加再取指数,比用简单收益率连乘更稳定。比如:cum_return = np.exp(log_return.sum()) - 1。
1.4 知识体系总览
下面这张图,是我自己画的本章知识结构。你可以把它当作一个“地图”,随时回来看看。
1.5 实战中的选择建议
好了,理论讲完了,咱们聊聊实战中怎么选。
| 场景 | 推荐操作 | 原因 |
|---|---|---|
| 价格预测(日频) | 对数收益率 + 滞后1-5期 | 价格非平稳,收益率平稳;短期记忆足够 |
| 波动率预测 | 滞后波动率 + 一阶差分 | 波动率有聚集效应,差分去除趋势 |
| 季节性数据(如天气) | 季节性差分 + 滞后1期 | 去除年周期,保留短期波动 |
| 高频数据(毫秒级) | 简单收益率 + 大量滞后特征 | 高频下对数收益率近似简单收益率,滞后阶数需更多 |
我个人习惯是:先用对数收益率做基础特征,然后根据ACF/PACF图选择滞后阶数。如果序列有明显季节性,再加季节性差分。记住,特征不是越多越好,而是越有效越好。
最后说一句:滞后特征和差分是时序特征工程的“基本功”。别小看它们,很多复杂的模型(比如LSTM、Transformer)本质上也是在学习这些滞后和差分关系。把基础打牢,后面的路才能走稳。
公众号:蓝海数据掘金营,微信deep3321