3、时间序列基础特征:滞后特征、滚动窗口统计、EWMA与时间差
时间序列的特征工程,说白了就是跟「过去」打交道。你想想看,金融数据里没有无缘无故的涨跌,今天的价格往往带着昨天的影子。我做了这么多年量化,最深的体会就是:时间序列的特征,核心就四个字——以史为鉴。
这一章我们聊四个最基础、也最实用的时间序列特征。它们几乎出现在每一个实盘策略里,是因子挖掘的「基本功」。
3.1 滞后特征(Lag Features)
滞后特征,就是把过去某个时刻的值拿过来当特征。比如今天的收盘价,昨天的收盘价,前天的收盘价……
为什么有用? 金融市场存在记忆效应。今天的走势往往跟昨天、前天有关。我见过很多新手一上来就搞复杂的深度学习模型,结果还不如一个简单的滞后特征有效。
举个代码例子,用 pandas 实现滞后特征非常方便:
import pandas as pd
import numpy as np
# 模拟收盘价数据
df = pd.DataFrame({
'close': [100, 102, 101, 105, 107, 106, 110]
})
# 生成滞后1天、2天、3天的特征
df['lag_1'] = df['close'].shift(1)
df['lag_2'] = df['close'].shift(2)
df['lag_3'] = df['close'].shift(3)
print(df)
输出结果:
close lag_1 lag_2 lag_3
0 100 NaN NaN NaN
1 102 100.0 NaN NaN
2 101 102.0 100.0 NaN
3 105 101.0 102.0 100.0
4 107 105.0 101.0 102.0
5 106 107.0 105.0 101.0
6 110 106.0 107.0 105.0
我曾经在一个高频策略里,只用了 lag_1 到 lag_5 这5个特征,加上一个简单的线性回归,就跑出了不错的夏普比率。你想想看,有时候简单的东西反而更稳健。
3.2 滚动窗口统计(Rolling Mean / Std)
滚动窗口统计,就是在一个固定大小的窗口内计算统计量。最常见的两个:滚动均值和滚动标准差。
滚动均值可以平滑噪声,识别趋势。滚动标准差则衡量波动率。这两个在风控和择时里都是标配。
代码实现:
# 计算5日滚动均值和标准差
df['rolling_mean_5'] = df['close'].rolling(window=5).mean()
df['rolling_std_5'] = df['close'].rolling(window=5).std()
print(df[['close', 'rolling_mean_5', 'rolling_std_5']])
输出:
close rolling_mean_5 rolling_std_5
0 100 NaN NaN
1 102 NaN NaN
2 101 NaN NaN
3 105 NaN NaN
4 107 103.0 2.915476
5 106 104.2 2.588436
6 110 105.8 3.563706
除了均值和标准差,滚动窗口还可以计算最大值、最小值、中位数、偏度、峰度等。但说实话,均值和标准差是最稳定、最不容易过拟合的。我在实盘里很少用滚动偏度这类高阶统计量,因为样本量不够时它们很不稳定。
3.3 指数加权移动平均(EWMA)
EWMA 跟滚动均值很像,但有一个关键区别:它给近期的数据更高的权重。越老的数据权重越小,呈指数衰减。
为什么需要 EWMA?因为金融市场里,今天的行情比10天前的行情更重要。滚动均值对所有数据一视同仁,这其实不太合理。
其中 α 是平滑系数,取值范围 (0, 1)。α 越大,对近期数据越敏感。
代码实现:
# 计算 EWMA,alpha=0.3
df['ewma_0.3'] = df['close'].ewm(alpha=0.3, adjust=False).mean()
# 也可以指定 span(相当于窗口大小)
df['ewma_span_5'] = df['close'].ewm(span=5, adjust=False).mean()
print(df[['close', 'ewma_0.3', 'ewma_span_5']])
输出:
close ewma_0.3 ewma_span_5
0 100 100.0000 100.000000
1 102 100.6000 100.666667
2 101 100.7200 100.777778
3 105 102.0040 102.185185
4 107 103.5028 103.790123
5 106 104.2520 104.526749
6 110 105.9764 106.351166
EWMA 在实战中非常常用。比如很多技术指标(MACD、布林带)底层用的就是 EWMA。我个人习惯用 EWMA 替代简单滚动均值,因为它更符合「近因效应」的直觉。
3.4 时间差特征(Time Delta Features)
时间差特征,就是计算两个时间点之间的间隔。这在金融数据里太常见了:
- 距离上一次交易的时间
- 距离上一次涨停/跌停的时间
- 距离财报发布的时间
- 相邻两笔交易的时间间隔
时间差特征能捕捉到「事件密度」和「节奏变化」。比如,如果某只股票突然交易频率变高,往往意味着有大事发生。
代码示例:
# 模拟带时间戳的数据
df_time = pd.DataFrame({
'timestamp': pd.to_datetime([
'2024-01-01 09:30:00',
'2024-01-01 09:30:05',
'2024-01-01 09:30:12',
'2024-01-01 09:30:20',
'2024-01-01 09:30:35'
]),
'price': [100, 101, 102, 101, 103]
})
# 计算相邻时间差(秒)
df_time['time_diff'] = df_time['timestamp'].diff().dt.total_seconds()
print(df_time)
输出:
timestamp price time_diff
0 2024-01-01 09:30:00 100 NaN
1 2024-01-01 09:30:05 101 5.0
2 2024-01-01 09:30:12 102 7.0
3 2024-01-01 09:30:20 101 8.0
4 2024-01-01 09:30:35 103 15.0
知识体系总览
下面这张图总结了本章的核心内容,帮你快速建立框架:
实战要点总结
嗯,到这里四个基础特征就讲完了。最后我分享几个实战中的要点:
- 不要贪多:滞后特征不是越多越好。我见过有人一口气生成 lag_1 到 lag_100,结果模型严重过拟合。一般 lag_1 到 lag_5 就够用了。
- 注意数据泄露:滚动窗口和 EWMA 在计算时,一定要确保只用到了历史数据。pandas 默认是左闭右开的,但如果你不小心用了未来数据,回测结果就是假的。
- 组合使用效果更好:比如用 EWMA 作为趋势信号,用滚动标准差作为波动率信号,两者结合可以构建一个简单的均值回归策略。
- 时间差特征别忽略:很多人在做特征工程时只关注价格和成交量,却忘了时间本身就是一个重要维度。尤其是在高频数据里,时间差特征往往能带来意想不到的收益。
公众号:蓝海资料掘金营,微信deep3321