4、时间序列基础特征:滚动均值、滚动标准差、滚动最大值/最小值、滚动分位数
在高频行情中,原始逐笔数据或快照数据包含大量噪声和微观结构效应。直接使用原始价格或成交量进行建模,往往会导致过拟合或信号不稳定。滚动统计量(Rolling Statistics)通过对固定窗口内的数据进行局部聚合,能够有效平滑噪声、捕捉短期趋势与波动特征,是特征工程中最基础且最有效的工具之一。
4.1 滚动统计量的核心概念
滚动统计量以固定长度的滑动窗口在时间序列上逐点移动,对窗口内的子序列计算指定统计函数。窗口长度(Window Size)是唯一的关键超参数,决定了特征的时间尺度。常见窗口类型包括:
- 滚动均值(Rolling Mean):窗口内数据的算术平均,反映局部趋势与价格中枢。
- 滚动标准差(Rolling Std):窗口内数据的标准差,度量局部波动率与价格离散程度。
- 滚动最大值/最小值(Rolling Max/Min):窗口内的极值,用于识别局部支撑/阻力位或价格突破。
- 滚动分位数(Rolling Quantile):窗口内指定分位点的值(如 25%、75%),刻画局部分布形态与尾部风险。
关键原则:滚动窗口长度必须与策略交易频率匹配。对于高频 tick 级数据,常用窗口为 5、10、20、50 笔;对于 1 秒或 1 分钟快照,常用窗口为 5、10、30、60 个周期。窗口过小则噪声残留,窗口过大则信号滞后严重。
4.2 滚动统计量的计算流程
以下为滚动特征的标准计算步骤,以 Python 的 pandas 库为例:
import pandas as pd
import numpy as np
# 假设 df 包含高频行情数据,index 为时间戳,'price' 列为最新成交价
df = pd.DataFrame({
'price': [100.1, 100.3, 100.2, 100.5, 100.4, 100.7, 100.6, 100.9, 101.0, 100.8]
})
window = 5 # 滚动窗口大小
# 滚动均值
df['rolling_mean'] = df['price'].rolling(window=window).mean()
# 滚动标准差
df['rolling_std'] = df['price'].rolling(window=window).std()
# 滚动最大值
df['rolling_max'] = df['price'].rolling(window=window).max()
# 滚动最小值
df['rolling_min'] = df['price'].rolling(window=window).min()
# 滚动分位数(25% 和 75%)
df['rolling_q25'] = df['price'].rolling(window=window).quantile(0.25)
df['rolling_q75'] = df['price'].rolling(window=window).quantile(0.75)
print(df)
工程注意:高频数据量极大,建议使用
numba 或 cython 加速滚动计算,或采用增量更新算法(如指数移动平均替代简单移动平均)以降低计算复杂度。
4.3 滚动统计量的对比与选择
| 特征名称 | 数学定义 | 高频行情应用场景 | 对噪声敏感度 | 信号滞后 |
|---|---|---|---|---|
| 滚动均值 | \(\bar{x}_t = \frac{1}{n}\sum_{i=t-n+1}^{t} x_i\) | 趋势方向、价格中枢、移动平均线 | 低 | 中 |
| 滚动标准差 | \(\sigma_t = \sqrt{\frac{1}{n-1}\sum_{i=t-n+1}^{t} (x_i - \bar{x}_t)^2}\) | 波动率估计、价差宽度、风险度量 | 中 | 中 |
| 滚动最大值 | \(max_t = \max\{x_{t-n+1}, ..., x_t\}\) | 局部阻力位、突破信号、止盈参考 | 高 | 低 |
| 滚动最小值 | \(min_t = \min\{x_{t-n+1}, ..., x_t\}\) | 局部支撑位、止损参考、价格回撤 | 高 | 低 |
| 滚动分位数 | \(Q_p(t) = \text{第 } p \text{ 百分位}\) | 分布形态、异常值检测、价差分布 | 中 | 中 |
4.4 滚动特征在标签优化中的作用
滚动统计量不仅作为原始特征输入模型,更常用于对标签(Label)进行预处理和优化:
- 标签平滑:对收益率或价格变化标签应用滚动均值,减少微观噪声导致的虚假信号。
- 波动率调整:使用滚动标准差对收益率进行标准化(Z-score),使标签在不同波动时段具有可比性。
- 极值截断:利用滚动分位数(如 1% 和 99%)对标签进行 winsorize 处理,抑制极端值对模型训练的干扰。
- 动态阈值:基于滚动最大值/最小值设定自适应止盈止损阈值,避免固定阈值在趋势行情中过早离场。
常见陷阱:滚动特征在窗口初期会产生 NaN 值,必须妥善处理(如填充前向值或丢弃)。此外,滚动统计量存在天然的自相关性,直接作为特征输入线性模型可能导致多重共线性,建议结合差分或正交化处理。
4.5 滚动特征计算流程示意图
下图展示了滚动统计量在时间序列上的滑动计算过程,以窗口大小为 5 的滚动均值为例:
4.6 多窗口滚动特征融合策略
单一窗口的滚动特征只能捕捉一个时间尺度的信息。高频行情特征工程中,通常采用多窗口融合策略,将不同尺度的滚动统计量拼接为高维特征向量:
# 多窗口滚动特征生成示例
windows = [5, 10, 20, 50]
for w in windows:
df[f'mean_{w}'] = df['price'].rolling(w).mean()
df[f'std_{w}'] = df['price'].rolling(w).std()
df[f'max_{w}'] = df['price'].rolling(w).max()
df[f'min_{w}'] = df['price'].rolling(w).min()
df[f'q25_{w}'] = df['price'].rolling(w).quantile(0.25)
df[f'q75_{w}'] = df['price'].rolling(w).quantile(0.75)
实践建议:高频行情中,建议使用指数加权移动平均(EWMA)替代简单移动平均,因其对近期数据赋予更高权重,信号响应更快。同时,滚动标准差可与滚动均值结合构造布林带(Bollinger Bands)类特征,用于识别价格突破与回归。
4.7 滚动特征与标签的联动优化
下图展示了滚动特征如何直接参与标签优化流程,形成从原始行情到优化标签的完整链路:
4.8 实践避坑指南
- 数据泄露:滚动统计量必须使用历史窗口数据,严禁引入未来信息。在回测中务必使用
shift(1)将滚动特征向后平移一个时间步,确保当前时刻的特征仅基于历史数据。 - 窗口边界效应:窗口初期的 NaN 值建议使用
min_periods参数控制最小有效观测数,避免过早输出不稳定统计量。 - 计算性能:高频数据每秒可达数千笔,建议使用增量算法(如 Welford 在线算法)计算滚动均值和标准差,避免重复全量计算。
- 特征冗余:高度相关的滚动特征(如窗口 5 和窗口 6 的均值)会导致模型过拟合,建议通过特征选择或 PCA 降维。
进阶方向:滚动统计量可与时间衰减权重结合,构造自适应窗口(如基于波动率变化动态调整窗口长度),进一步提升特征对市场状态变化的响应能力。