4. 特征工程基础:技术指标计算与数据预处理
在量化策略中,原始行情数据(开盘价、收盘价、最高价、最低价、成交量)通常不能直接作为 LightGBM 模型的输入。特征工程的目标是从这些原始数据中提取出能够预测未来价格走势的有效信息。本章将系统讲解经典技术指标的计算方法、特征标准化以及缺失值处理,为后续模型训练打下坚实基础。
4.1 经典技术指标计算
技术指标是量化特征工程的核心组成部分。以下四个指标覆盖了趋势、动量、波动率三个维度,是构建策略特征的常用起点。
4.1.1 移动平均线(MA)
MA 是最基础的趋势指标,用于平滑价格序列,识别趋势方向。常用周期包括 5 日、20 日、60 日。
# 计算 5 日和 20 日简单移动平均线
import pandas as pd
df['MA5'] = df['close'].rolling(window=5).mean()
df['MA20'] = df['close'].rolling(window=20).mean()
4.1.2 指数平滑异同移动平均线(MACD)
MACD 由快线(DIF)、慢线(DEA)和柱状线(MACD Histogram)组成,用于判断趋势强度与反转信号。
# 计算 MACD 指标
exp12 = df['close'].ewm(span=12, adjust=False).mean()
exp26 = df['close'].ewm(span=26, adjust=False).mean()
df['DIF'] = exp12 - exp26
df['DEA'] = df['DIF'].ewm(span=9, adjust=False).mean()
df['MACD'] = 2 * (df['DIF'] - df['DEA'])
4.1.3 相对强弱指标(RSI)
RSI 衡量价格变动的速度和幅度,用于识别超买(通常 > 70)和超卖(通常 < 30)状态。
# 计算 14 日 RSI
delta = df['close'].diff()
gain = delta.where(delta > 0, 0.0)
loss = -delta.where(delta < 0, 0.0)
avg_gain = gain.rolling(window=14).mean()
avg_loss = loss.rolling(window=14).mean()
rs = avg_gain / avg_loss
df['RSI'] = 100 - (100 / (1 + rs))
4.1.4 布林带(Bollinger Bands)
布林带由中轨(MA)、上轨(中轨 + k 倍标准差)和下轨(中轨 - k 倍标准差)组成,反映价格的波动区间。k 通常取 2。
# 计算布林带(20 日周期,2 倍标准差)
df['BB_MID'] = df['close'].rolling(window=20).mean()
std = df['close'].rolling(window=20).std()
df['BB_UP'] = df['BB_MID'] + 2 * std
df['BB_DN'] = df['BB_MID'] - 2 * std
df['BB_WIDTH'] = df['BB_UP'] - df['BB_DN'] # 带宽特征
特征组合建议: 不要单独使用某个指标,建议将 MA 斜率、MACD 柱线变化、RSI 分位数、布林带位置(价格在带宽中的百分比)等衍生特征组合使用,能显著提升 LightGBM 模型的预测能力。
4.2 特征标准化
LightGBM 是基于树的模型,理论上对特征尺度不敏感。但在实际量化场景中,标准化仍然至关重要:
- 加速收敛: 当特征包含学习率或正则化参数时,标准化有助于稳定训练过程。
- 特征重要性可比: 标准化后的特征重要性排序更可靠,便于特征筛选。
- 避免数值溢出: 某些衍生特征(如成交量放大倍数)可能数值极大,标准化可防止计算过程中的数值不稳定。
常用的标准化方法有两种:
| 方法 | 公式 | 适用场景 |
|---|---|---|
| Z-score 标准化 | \( z = \frac{x - \mu}{\sigma} \) | 特征近似正态分布,无严格上下界 |
| Min-Max 归一化 | \( x' = \frac{x - x_{min}}{x_{max} - x_{min}} \) | 特征有明确边界,如 RSI(0-100) |
# Z-score 标准化示例
from sklearn.preprocessing import StandardScaler
features = ['MA5', 'MA20', 'DIF', 'DEA', 'MACD', 'RSI', 'BB_WIDTH']
scaler = StandardScaler()
df[features] = scaler.fit_transform(df[features])
回测陷阱: 标准化时必须使用训练集的统计量(μ, σ)来转换测试集,避免未来信息泄露。建议在滚动时间窗口内重新计算统计量,或使用扩展窗口方式。
4.3 缺失值处理
技术指标计算必然产生缺失值,尤其是在窗口期开始阶段。LightGBM 原生支持缺失值,但量化场景下需要谨慎处理。
4.3.1 缺失值来源
- 窗口期不足: 如计算 20 日 MA,前 19 行数据为 NaN。
- 停牌或数据中断: 股票停牌导致某日无交易数据。
- 除权除息: 价格跳空导致指标计算异常。
4.3.2 处理策略对比
| 策略 | 方法 | 量化场景推荐度 |
|---|---|---|
| 向前填充 | 用上一个有效值填充 | 高(停牌场景首选) |
| 向后填充 | 用下一个有效值填充 | 低(引入未来信息) |
| 删除缺失行 | 直接丢弃 NaN 行 | 中(损失早期样本) |
| 插值法 | 线性/多项式插值 | 中(适用于短间隔缺失) |
| LightGBM 原生 | 模型自动学习分裂方向 | 高(但需结合业务理解) |
# 推荐处理流程:向前填充 + 删除窗口期头部
df = df.sort_values('date') # 确保时间顺序
df = df.fillna(method='ffill') # 向前填充
df = df.dropna() # 删除仍为 NaN 的行(通常是窗口期头部)
最佳实践: 对于 LightGBM 模型,建议保留缺失值并让模型自行处理,同时额外添加一个“是否缺失”的二元特征(如
is_MA20_missing),帮助模型捕捉缺失模式中的信息。
4.4 特征工程完整流程
下图展示了从原始行情数据到最终特征矩阵的完整处理链路:
4.5 本章小结
特征工程是量化策略从“想法”到“模型”的关键桥梁。本章涵盖的技术指标计算、标准化和缺失值处理,构成了 LightGBM 策略灰度回测中特征流水线的核心骨架。在实际项目中,建议按照以下顺序构建特征:
- 原始数据清洗: 处理复权、停牌、异常值。
- 指标计算: 批量计算 MA、MACD、RSI、布林带等基础指标。
- 衍生特征: 构造交叉特征(如 RSI 与布林带位置组合)、统计特征(滚动相关系数)。
- 缺失值处理: 向前填充 + 删除窗口期头部,或保留缺失并添加掩码特征。
- 标准化: 在训练集上拟合 scaler,转换训练集和测试集。
- 滚动验证: 确保每一步都不引入未来信息。
进阶提示: 本章仅涉及最基础的四个技术指标。在完整策略中,还可以加入成交量加权指标(VWAP)、波动率指标(ATR)、市场微观结构指标(买卖价差)等。特征数量建议控制在 20-50 个之间,避免维度灾难。