3. 特征工程(下):波动率与收益率特征构建、资金流向与成交量特征、特征降维(PCA主成分分析)、特征重要性评估
好,咱们接着聊特征工程。上一节我们把基础的价格特征和基本面特征搞定了,这一节要动真格的了——波动率、收益率、资金流向,这些才是量化选股的灵魂。我个人习惯把这一节叫做「特征工程的深水区」,因为这里稍不注意,你的模型就会学到一堆噪音。
3.1 波动率与收益率特征构建
先说波动率。很多人以为波动率就是标准差,其实没那么简单。我在项目中遇到过一个问题:用简单标准差算出来的波动率,对极端行情反应太慢。后来我改用指数加权波动率(EWMA),效果好了不少。
核心思路:波动率要能反映近期市场情绪的变化,而不是平均主义。
具体怎么构建?我一般会做这几类:
- 历史波动率:过去5日、20日、60日的收益率标准差
- EWMA波动率:给近期数据更高权重,衰减因子λ通常取0.94
- 日内波动率:用最高价/最低价估算,公式是 (high - low) / (high + low) * 2
- 波动率变化率:今天的波动率相比昨天是变大了还是变小了
收益率特征呢?说白了就是看股票过去涨得怎么样。但别只算简单收益率,我建议做这些:
- 对数收益率:ln(P_t / P_{t-1}),比简单收益率更符合正态分布假设
- 累计收益率:过去5天、20天的累计涨跌幅
- 超额收益率:个股收益率减去大盘收益率,剔除市场系统性影响
- 收益率偏度:过去一段时间收益率的偏斜程度,判断涨跌不对称性
小技巧:构建收益率特征时,记得做「未来信息屏蔽」。我曾经犯过这个错——用当天的收盘价去算过去5天的收益率,结果模型在回测里表现完美,实盘一塌糊涂。嗯,血的教训。
3.2 资金流向与成交量特征
资金流向特征,说白了就是看「谁在买、谁在卖」。A股市场里,主力资金和大单资金的行为往往能预示短期走势。我一般会构建以下特征:
| 特征名称 | 计算方式 | 说明 |
|---|---|---|
| 主力净流入 | 大单买入额 - 大单卖出额 | 反映机构资金态度 |
| 资金强度 | 净流入额 / 成交额 | 归一化后的资金力度 |
| 大单占比 | 大单成交额 / 总成交额 | 判断是否由主力主导 |
| 资金集中度 | 前5大单净流入 / 总净流入 | 资金是否集中在少数机构 |
成交量特征呢?成交量是市场的「燃料」。没有成交量的上涨,说白了就是虚涨。我常用的成交量特征有:
- 成交量变化率:今日成交量 / 过去5日均量 - 1
- 量价配合度:当日涨跌幅与成交量变化的相关系数
- 换手率:成交量 / 流通股本,反映股票活跃度
- 成交量变异系数:成交量标准差 / 成交量均值,判断成交稳定性
避坑指南:我曾经在构建资金流向特征时,直接用分钟级数据算净流入,结果发现数据源里的大单定义不一致。有的数据商把50万以上算大单,有的把100万以上算大单。所以,用之前一定要确认数据口径。
3.3 特征降维(PCA主成分分析)
特征多了,问题就来了。你想想看,几十个特征之间肯定有相关性。比如波动率和振幅高度相关,资金净流入和成交量也高度相关。这时候PCA就派上用场了。
PCA说白了就是「把多个相关特征压缩成几个不相关的综合指标」。我一般这样用:
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# 标准化:PCA对尺度敏感,必须先标准化
scaler = StandardScaler()
features_scaled = scaler.fit_transform(features)
# PCA降维:保留95%的方差信息
pca = PCA(n_components=0.95)
features_pca = pca.fit_transform(features_scaled)
# 看看每个主成分的解释方差比
print(f"主成分数量: {pca.n_components_}")
print(f"解释方差比: {pca.explained_variance_ratio_}")
这里有个关键点:PCA后的特征失去了可解释性。第一个主成分可能是波动率、收益率、资金流向的某种线性组合,你很难说它具体代表什么。所以,如果你需要向老板解释模型逻辑,建议谨慎使用PCA。
我的经验:PCA适合用在聚类分析的前置步骤。先把50个特征降到10个主成分,然后用这10个主成分做聚类,效果往往比直接用原始特征好。因为PCA去掉了噪音,保留了核心结构。
3.4 特征重要性评估
特征建好了,降维也做了,接下来要问:哪些特征真正有用?特征重要性评估,说白了就是给每个特征打个分。
我常用的方法有三种:
- 基于树模型的特征重要性:用随机森林或XGBoost训练一个模型,直接输出特征重要性分数。优点是快,缺点是偏向于数值型特征。
- 相关系数法:计算每个特征与目标变量(比如未来收益率)的相关系数。简单直观,但只能捕捉线性关系。
- Permutation Importance:打乱某个特征的值,看模型效果下降多少。下降越多,特征越重要。这个方法最稳健,但计算量大。
举个例子,用随机森林看特征重要性:
from sklearn.ensemble import RandomForestRegressor
# 训练一个简单的随机森林
rf = RandomForestRegressor(n_estimators=100, random_state=42)
rf.fit(features, target)
# 获取特征重要性
importance = rf.feature_importances_
feature_names = features.columns
# 排序展示
sorted_idx = np.argsort(importance)[::-1]
for i in range(10):
print(f"{feature_names[sorted_idx[i]]}: {importance[sorted_idx[i]]:.4f}")
注意:特征重要性高不代表因果关系。我曾经遇到一个特征「昨日涨停」重要性排第一,但仔细一想,这是因为涨停的股票第二天往往有惯性上涨,而不是这个特征本身有预测能力。所以,特征重要性要结合业务逻辑去理解。
最后,我建议把特征重要性做成可视化图表,一目了然。用matplotlib画个水平条形图,把最重要的10个特征标出来,方便跟团队沟通。
好了,特征工程的核心内容就这些。从波动率到资金流向,从PCA降维到特征重要性评估,每一步都有坑,但也都有对应的解法。我个人觉得,特征工程做得好不好,直接决定了模型的天花板。算法可以调参,但特征不行就是不行。