3、特征工程基础:常见选股因子(估值、动量、质量、情绪)。特征标准化与缺失值处理。

好,我们直接进入正题。特征工程,说白了就是给模型喂“好料”。你想想看,模型再厉害,喂进去的是垃圾,出来的肯定也是垃圾。在量化选股里,这些“料”就是我们常说的选股因子。

我个人习惯把因子分成四大类:估值、动量、质量、情绪。这四类基本覆盖了市场上主流的选股逻辑。咱们一个一个来看。

3.1 常见选股因子

3.1.1 估值因子

估值因子,就是看股票“贵不贵”。便宜的不一定涨,但太贵的往往风险大。我在项目中遇到过,有些股票PE(市盈率)高得离谱,但市场还在疯狂炒作。这时候估值因子就能帮你避开一些坑。

常用的估值因子有:

  • 市盈率(PE):股价 / 每股收益。越低越便宜。
  • 市净率(PB):股价 / 每股净资产。适合银行、周期股。
  • 市销率(PS):股价 / 每股销售额。适合亏损但营收高的公司。
  • 股息率:每股分红 / 股价。高股息率往往代表公司现金流好。

嗯,这里要注意:估值因子不能单独用。我曾经见过一个策略,只用低PE选股,结果选了一堆银行股,市场风格一转,直接跑输大盘。所以估值因子最好和其他因子搭配使用。

3.1.2 动量因子

动量因子,说白了就是“追涨杀跌”的量化版本。它的逻辑很简单:过去涨的股票,未来一段时间还会涨;过去跌的,还会跌。听起来有点反直觉,但实证研究表明,短期动量确实存在。

我常用的动量因子:

  • 过去1个月收益率:短期动量。
  • 过去12个月收益率(剔除最近1个月):中期动量,也叫“动量因子”。
  • RSI(相对强弱指标):衡量近期涨跌幅度。

你可能会问:“那什么时候动量会失效?” 嗯,市场剧烈反转的时候。比如2020年疫情刚爆发时,所有动量策略都亏得很惨。所以动量因子需要配合风险控制。

3.1.3 质量因子

质量因子,看的是公司“好不好”。好公司不一定涨,但长期来看,质量高的公司更抗跌。我建议把质量因子作为“压舱石”。

常见的质量因子:

  • ROE(净资产收益率):净利润 / 净资产。越高说明盈利能力越强。
  • 毛利率:毛利 / 营收。反映产品竞争力。
  • 资产负债率:总负债 / 总资产。越低越安全。
  • 现金流比率:经营现金流 / 营收。防止“纸面富贵”。

我记得有一次,一个朋友用ROE选股,选出来的全是高杠杆的房地产公司。后来地产暴雷,他的组合直接崩了。所以质量因子一定要看现金流,别只看利润表。

3.1.4 情绪因子

情绪因子,反映的是市场参与者的“心态”。比如散户的恐慌、机构的贪婪。这些情绪会直接影响股价短期波动。

我常用的情绪因子:

  • 换手率:交易活跃度。换手率突然飙升,往往意味着情绪过热。
  • 融资余额变化:杠杆资金的进出。
  • 北向资金净流入:外资的动向。
  • 分析师评级调整:卖方研究的态度变化。

情绪因子有个特点:它和基本面因子往往负相关。比如一只股票基本面很好,但情绪很差(没人关注),这时候反而是买入机会。我曾经用情绪因子做过一个“逆向投资”策略,效果还不错。

3.2 特征标准化

好,因子有了,但它们的量纲不一样。比如PE可能是几十,换手率可能是百分之几。如果不做标准化,模型会天然地“偏爱”数值大的特征。这显然不合理。

我常用的标准化方法有两种:

3.2.1 Z-score标准化

把数据变成均值为0、标准差为1的分布。公式很简单:

z = (x - mean) / std

这种方法适合数据近似正态分布的情况。我建议在因子数据比较“干净”的时候用。

3.2.2 Min-Max标准化

把数据缩放到[0,1]区间。公式:

scaled = (x - min) / (max - min)

这种方法对异常值比较敏感。如果数据里有极端值,Min-Max会把大部分数据压缩到很小的区间。嗯,这时候我一般会用“截尾”处理,先去掉上下1%的极端值,再做标准化。

代码示例(Python):

import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# 假设df是因子数据
scaler = StandardScaler()
df_zscore = scaler.fit_transform(df)

scaler_mm = MinMaxScaler()
df_minmax = scaler_mm.fit_transform(df)

3.3 缺失值处理

现实中的数据,永远有缺失。有些股票停牌了,有些数据没更新。如果不处理,模型会报错,或者学到错误的关系。

我处理缺失值的几个原则:

  • 删除:如果缺失比例超过50%,直接删掉这个特征。
  • 填充:如果缺失比例在10%以内,用中位数或均值填充。我个人习惯用中位数,因为它不受异常值影响。
  • 行业均值填充:对于估值因子,不同行业的差异很大。用行业均值填充比全局均值更合理。
  • 标记缺失:有时候“缺失”本身也是一种信息。比如某只股票没有分析师覆盖,可能意味着它被市场忽略。这时候可以单独加一个“是否缺失”的哑变量。

我曾经犯过一个错误:用全局均值填充PE,结果把银行股和科技股的PE混在一起,模型完全乱了。后来改成行业均值填充,效果好了很多。

代码示例:

# 中位数填充
df.fillna(df.median(), inplace=True)

# 行业均值填充
df['pe'] = df.groupby('industry')['pe'].transform(lambda x: x.fillna(x.median()))

3.4 知识体系图

下面这张图,是我自己总结的特征工程核心逻辑。你可以把它当作一个检查清单:

特征工程 估值因子 动量因子 质量因子 情绪因子 特征标准化 缺失值处理 Z-score标准化 Min-Max标准化 删除 填充 标记 干净、标准化的特征矩阵

核心要点:

  • 四大因子(估值、动量、质量、情绪)是选股的基础,缺一不可。
  • 标准化让不同量纲的特征“平等对话”。
  • 缺失值处理要分情况讨论,别一刀切。

我的小技巧:

在做特征工程时,我习惯先跑一个简单的线性回归,看看每个因子的系数方向是否符合逻辑。如果PE的系数是正的(PE越高,预期收益越高),那肯定有问题。这能帮你快速发现数据错误。

注意:

千万不要在训练集上做标准化和缺失值填充后,直接应用到测试集。一定要先fit训练集,再用训练集的参数transform测试集。否则会造成数据泄露,模型效果虚高。

专注资料整理