第二章:因子数据准备——数据源选择、清洗与对齐
做量化研究,有一句老话叫「垃圾进,垃圾出」。因子再漂亮,数据源选错了、清洗不到位,结果全是废的。这一章,我重点聊聊数据准备的那些坑。
2.1 数据源选择:Wind、Tushare、聚宽,怎么选?
我个人习惯,先看研究阶段。做学术研究或个人回测,Tushare 和聚宽完全够用。但如果你在机构里做实盘,Wind 几乎是标配。
为什么会这样?说白了,数据源的差异主要在三点:
- 覆盖度:Wind 覆盖 A 股、港股、期货、期权,甚至债券。Tushare 和聚宽偏股票和基金。
- 时效性:Wind 实时行情延迟低,Tushare 免费版有 15 分钟延迟。
- 清洗程度:Wind 的数据已经做过初步清洗,比如复权、停牌标记。Tushare 和聚宽需要你自己处理。
我的建议:初期用 Tushare 或聚宽做因子探索,等因子稳定了,再切换到 Wind 做最终验证。别一上来就买 Wind,贵且没必要。
我记得有一次,团队用 Tushare 跑了一个因子,回测夏普比 2.3,兴奋得不行。结果换到 Wind 上一跑,夏普比直接掉到 0.8。查了半天,原来是 Tushare 的复权数据有 bug。嗯,从那以后,我养成了「双源验证」的习惯。
2.2 数据清洗:去极值、缺失值、复权处理
数据清洗是因子研究里最枯燥、但最重要的一步。你想想看,原始数据里什么妖魔鬼怪都有。
2.2.1 去极值
极值怎么来的?可能是数据录入错误,也可能是极端行情。比如某只股票一天涨了 1000%,这明显是异常。
我常用的方法有两种:
- MAD 法:中位数 ± 3 倍绝对中位差。稳健,不受极端值影响。
- 百分位法:直接截掉 1% 和 99% 以外的数据。简单粗暴,但有效。
# 用 MAD 法去极值
import numpy as np
def winsorize_mad(series, n=3):
median = np.median(series)
mad = np.median(np.abs(series - median))
upper = median + n * mad
lower = median - n * mad
return np.clip(series, lower, upper)
小技巧:去极值不要用均值 ± 3 倍标准差。均值对极值敏感,你越去极值,均值越偏。MAD 法才是正解。
2.2.2 缺失值处理
缺失值在因子数据里太常见了。停牌、新股上市、数据源漏了,都会导致缺失。
我的处理原则很简单:
- 横截面缺失:用行业均值填充。比如某只股票的市盈率缺失,用同行业其他股票的市盈率均值补上。
- 时间序列缺失:用前向填充。比如今天的数据缺失,用昨天的数据代替。
- 连续缺失太多:直接删除。比如连续停牌超过 20 天,这只股票这段时间的数据就别用了。
注意:千万不要用 0 填充缺失值。0 本身是一个有效数值,你填了 0,相当于引入了一个错误信号。我曾经见过有人用 0 填充市盈率缺失值,结果因子选出了一堆亏损股,回测效果奇差。
2.2.3 复权处理
复权是 A 股特有的坑。分红、送股、配股,都会导致股价跳空。如果不复权,你的因子计算全是错的。
我个人习惯用后复权。为什么?后复权能真实反映股票的历史收益。前复权虽然更直观,但会改变历史价格,影响因子计算。
# 后复权价格计算
def calc_adj_close(df):
# df 包含 close, adj_factor 字段
df['adj_close'] = df['close'] * df['adj_factor']
return df
嗯,这里要注意:不同数据源的复权因子定义可能不同。Wind 的复权因子是累积的,Tushare 的复权因子是当期的。用之前一定要看清楚文档。
2.3 数据对齐与频率统一
数据对齐,说白了就是让不同频率的数据能在同一个时间点上比较。你想想看,日频数据和周频数据,怎么放在一起算因子?
我常用的对齐方法:
- 低频转高频:比如把周频数据填充到日频。用前向填充,不要用插值。
- 高频转低频:比如把日频数据聚合成周频。用均值或最后一个值。
- 跨市场对齐:A 股和港股交易日不同,需要对齐到共同的交易日。
核心原则:因子计算时,必须使用「未来不可知」的数据。也就是说,你在 T 日计算因子,只能用 T 日及之前的数据。千万别用未来的数据填充缺失值,那是未来函数。
我记得有一次,团队里一个新同事用插值法填充了缺失的财务数据。结果因子在回测里表现极好,但实盘一跑就崩。查了半天,原来是插值用到了未来的财务数据。嗯,从那以后,我要求所有数据对齐都必须用前向填充。
2.4 本章知识体系
下面这张图,是我做数据准备时的核心流程。你可以把它当作一个检查清单。
数据准备这件事,说白了就是「磨刀不误砍柴工」。你花 60% 的时间在数据上,剩下的 40% 时间做因子研究,效率反而最高。我见过太多人一上来就写因子代码,结果数据全是脏的,白忙活一场。
我的习惯:每次开始新的因子研究前,先花一天时间检查数据。跑一遍去极值、缺失值统计、复权验证。数据没问题了,再开始写因子代码。这个习惯帮我省了无数时间。
好了,数据准备就聊到这里。记住一句话:数据质量决定了因子上限,因子模型只是逼近这个上限的手段。