3、数据准备与清洗:数据源选择、数据对齐、缺失值处理、异常值处理、行业分类标准化
数据准备,说白了就是给因子做「体检」。
我见过太多人,因子逻辑漂亮得不行,回测曲线也好看,结果一上实盘就崩。为什么?数据没洗干净。你想想看,垃圾数据进去,出来的因子能靠谱吗?
这一章,我就把数据清洗的四个核心环节掰开揉碎讲清楚。嗯,都是我在项目里踩过的坑。
3.1 数据源选择:别在源头就输了
我个人习惯,数据源至少要备两个。一个做主库,一个做交叉验证。
国内常用的数据源,我列个表给你看:
| 数据源 | 优点 | 缺点 | 我的建议 |
|---|---|---|---|
| Wind | 覆盖全,机构认可度高 | 贵,接口慢 | 做主力数据源 |
| 聚宽/JQData | 便宜,Python友好 | 历史数据深度不够 | 做快速验证 |
| Tushare | 免费,社区活跃 | 稳定性一般 | 做辅助校验 |
| 自己爬的 | 定制化强 | 维护成本高 | 慎用,除非你有人力 |
3.2 数据对齐:时间轴必须对齐
数据对齐,是新手最容易忽略的环节。
你想想看,因子数据是日频的,收益率数据也是日频的,但它们的交易日历可能不一样。A股有调休、有停牌,港股有台风休市,美股有节假日。如果不做对齐,因子和收益之间就存在「时间错位」。
我一般这样做:
- 统一交易日历:以交易所公布的交易日为准,剔除所有非交易日
- 前向填充:因子数据遇到缺失的交易日,用上一个有效值填充
- 后向对齐:因子T日的数据,对齐到T+1日的收益(防止未来信息)
3.3 缺失值处理:别一股脑全删了
缺失值怎么处理?很多人上来就dropna(),这其实很危险。
为什么?因为缺失值本身可能包含信息。比如某只股票突然停牌了,它的因子数据缺失,这恰恰说明这只股票处于「异常状态」。你把它删了,反而会引入幸存者偏差。
我的处理策略分三步:
- 先分类:看缺失是随机的,还是系统性的
- 再处理:
- 随机缺失(比如某天数据没传上来):用行业均值填充
- 系统性缺失(比如新股上市前没有数据):直接剔除该时间段
- 停牌导致的缺失:保留NaN,单独作为一个类别
- 最后检查:填充后的数据分布是否发生明显偏移
# 我常用的缺失值处理代码
import pandas as pd
import numpy as np
def handle_missing(df, factor_col, group_col='industry'):
"""
df: 包含因子值和行业分类的DataFrame
factor_col: 因子列名
group_col: 行业列名
"""
# 1. 计算行业均值
industry_mean = df.groupby(group_col)[factor_col].transform('mean')
# 2. 用行业均值填充
df[factor_col] = df[factor_col].fillna(industry_mean)
# 3. 如果填充后还有缺失(比如整个行业都缺失),用全局均值
global_mean = df[factor_col].mean()
df[factor_col] = df[factor_col].fillna(global_mean)
return df
3.4 异常值处理:别把金子当垃圾扔了
异常值处理,是最考验经验的地方。
我记得有一次,一个因子在某个行业里表现特别好,我以为是发现了新规律。后来一查,原来是那个行业里有一家公司的数据录入错了,多了一个零。嗯,这种异常值必须处理。
但有些异常值,其实是真正的alpha信号。比如某只股票突然放量暴跌,它的因子值可能偏离正常范围,但这恰恰是交易机会。
我的处理原则:
- 先识别,再判断:用3-sigma或IQR方法找出异常值
- 不要直接删除:先看看这些异常值对应的股票,是不是有合理的解释
- 缩尾处理(Winsorize):把极端值拉到某个分位数上,而不是直接删掉
# 缩尾处理示例
def winsorize_series(s, lower=0.01, upper=0.99):
"""
对序列进行缩尾处理
"""
q_low = s.quantile(lower)
q_high = s.quantile(upper)
return s.clip(lower=q_low, upper=q_high)
3.5 行业分类标准化:统一口径才能比较
行业分类,看着简单,其实坑最多。
国内有申万行业、中信行业、证监会行业,国外有GICS、ICB。不同分类标准,同一只股票可能被分到不同行业。你想想看,如果因子在行业内部做中性化处理,行业分类不一致,结果能对吗?
我的做法:
- 统一到一套标准:我个人习惯用申万一级行业,因为覆盖面广,更新及时
- 建立映射表:把其他分类标准映射到申万行业上
- 处理综合类公司:有些公司业务多元,会被分到「综合」行业。这类股票我一般单独处理,不参与行业中性化
3.6 数据清洗的整体流程
说了这么多,我画个流程图,把整个数据清洗的逻辑串起来:
这个流程,我建议你每次做因子研究之前都走一遍。别嫌麻烦,数据清洗花的时间,会在后面的建模和回测阶段十倍百倍地省回来。
公众号:蓝海资料掘金营,微信deep3321