4、数据准备与清洗:数据源选择、缺失值处理、异常值识别、复权处理

多因子选股模型的稳健性,本质上取决于输入数据的质量。业界常说“Garbage in, Garbage out”,在量化研究场景中,数据源不一致、缺失值未处理、异常值未识别、复权方式错误,都会直接导致因子失效、回测失真甚至实盘亏损。本章围绕数据准备与清洗的四个核心环节展开:数据源选择、缺失值处理、异常值识别、复权处理,帮助学员建立一套可落地、可复核的数据工程标准流程。

数据准备与清洗工程链路 数据源选择 Wind / 聚宽 / 米筐 Tushare / 自建库 缺失值处理 删除 / 填充 / 插值 行业均值 / 前向填充 异常值识别 MAD / 分位数 / Z-score 行业中性化处理 复权处理 前复权 / 后复权 涨跌幅还原 数据质量校验层 ✓ 时间戳对齐 ✓ 股票代码一致性 ✓ 字段类型校验 ✓ 交易日历匹配 清洗后输出标准 面板数据 (Panel Data) 因子值 = f(价格, 财务, 一致预期) 可回溯 / 可复核 / 可审计 清洗流程闭环 原始数据 → 格式标准化 → 缺失/异常处理 → 复权 → 质量校验 → 因子计算

4.1 数据源选择:多源交叉验证与主数据源确定

数据源选择是数据工程的第一步,也是决定后续清洗工作量的关键。不同数据源在字段定义、更新频率、历史深度、复权算法上存在显著差异。例如,Wind 的财务数据字段最全,但价格数据的前复权因子在除权除息日可能产生微小偏差;聚宽和米筐的数据更偏向于量化研究场景,接口友好但历史深度可能受限;Tushare 免费版适合教学和原型验证,但稳定性和字段完整性需要额外校验。

核心原则是:确定一个主数据源,至少一个辅助数据源用于交叉验证。主数据源负责日常因子计算和回测,辅助数据源用于关键字段(如收盘价、总股本、净利润)的抽样比对。对于财务数据,建议以定期报告披露的原始值为主,避免使用数据商已经做过的“调整后”字段,因为不同数据商的调整逻辑可能不同。

数据源 优势 劣势 适用场景
Wind 字段最全、机构认可度高 费用高、接口较重 机构实盘、正式研究
聚宽 / 米筐 量化友好、因子库丰富 历史深度有限 策略研发、回测
Tushare 免费、社区活跃 限流、字段不稳定 教学、原型验证
自建数据库 完全可控、可定制 维护成本高 长期生产环境
实战建议:在项目启动阶段,先下载同一只股票(如贵州茅台)近三年的日线数据,从两个不同数据源获取,对比收盘价、成交量、复权因子的差异。如果差异率超过 0.1%,需要排查是复权算法差异还是数据源本身的问题。这个“数据源体检”步骤能避免后续因子计算中的系统性偏差。

4.2 缺失值处理:分层策略与行业中性化填充

缺失值是面板数据中最常见的问题,来源包括停牌、新股上市初期、财务数据未及时披露、数据商采集遗漏等。处理缺失值不能一刀切,需要根据缺失比例和缺失原因分层处理。

第一层:删除策略。对于缺失比例超过 30% 的字段(如某些冷门财务指标),直接删除该字段,避免后续因子计算引入大量噪声。对于单只股票在某个时间窗口内缺失超过 20 个交易日的,考虑剔除该股票在该窗口的数据。

第二层:填充策略。对于时间序列型数据(如日收益率、成交量),优先使用前向填充(Forward Fill)或线性插值。对于截面型数据(如市盈率、市净率),使用行业均值或行业中位数填充。这里的关键是行业中性化填充——用同行业、同市值区间的股票均值填充,避免填充值本身带有行业偏差。

第三层:标记策略。对于无法准确填充的缺失值,建议在因子计算时增加一个“缺失标记”虚拟变量,让模型自行学习缺失模式是否具有预测信息。例如,某股票连续停牌后复牌,其缺失期间的数据不应简单填充,而应标记为“停牌状态”。

# 缺失值处理伪代码示例
def handle_missing(df, industry_col='industry', value_col='pe_ttm'):
    # 按行业分组填充中位数
    df[value_col] = df.groupby(industry_col)[value_col].transform(
        lambda x: x.fillna(x.median())
    )
    # 剩余缺失值用全局中位数填充
    df[value_col] = df[value_col].fillna(df[value_col].median())
    # 增加缺失标记
    df[value_col + '_missing'] = df[value_col].isnull().astype(int)
    return df
风险提示:不要对所有缺失值都使用“0”填充。在财务因子中,缺失可能意味着“不适用”或“未披露”,用 0 填充会严重扭曲因子分布。例如,某公司没有长期借款,其“长期借款/总资产”字段应为 0 还是缺失?这需要结合业务含义判断,不能机械处理。

4.3 异常值识别:MAD 法与分位数截尾

异常值(Outlier)对因子值的影响远大于缺失值。一个极端值可能让因子排序完全失真,导致回测结果被少数股票主导。常用的异常值识别方法有三种:Z-score 法、MAD 法、分位数截尾法。

Z-score 法假设数据服从正态分布,将超过均值 3 个标准差的值视为异常。但金融数据普遍具有厚尾特征,Z-score 法容易将正常的高收益误判为异常。

MAD 法(Median Absolute Deviation)基于中位数和偏差,对厚尾分布更稳健。计算方式为:MAD = median(|x_i - median(x)|),将偏离中位数超过 3 倍 MAD 的值视为异常。MAD 法不需要数据服从正态分布,更适合处理市盈率、市净率等具有明显偏态的财务比率。

分位数截尾法直接将因子值上下 1% 或 2.5% 的极值替换为边界值(Winsorize)。这种方法简单直观,但会损失尾部信息。在实际操作中,建议先使用 MAD 法识别异常值,再对识别出的异常值进行 Winsorize 处理,而不是直接删除。

方法 适用场景 优点 缺点
Z-score 近似正态分布的数据 计算简单 厚尾数据误判率高
MAD 厚尾分布、财务比率 稳健、抗极端值 计算稍复杂
分位数截尾 因子排序前处理 直观、易解释 损失尾部信息
实战案例:某学员在构建“市盈率倒数”因子时,发现回测净值曲线在 2015 年 6 月出现异常陡峭的上升。排查后发现,当时部分股票市盈率为负(亏损企业),其倒数仍为负值,但值极大(如 -0.5),导致因子排序严重失真。通过 MAD 法识别后,将负市盈率股票的因子值单独处理——要么剔除,要么单独分组,最终回测曲线恢复正常。

4.4 复权处理:前复权、后复权与涨跌幅还原

复权处理是数据清洗中最容易出错、但影响最大的环节。股票在除权除息日(如送股、配股、分红)会出现价格跳空,如果不做复权处理,收益率计算会失真。复权分为前复权、后复权和涨跌幅还原三种方式。

前复权以当前价格为基准,调整历史价格。优点是当前价格与市场一致,适合技术分析和因子计算;缺点是每次新除权事件发生,历史价格都会变化,导致历史数据不可回溯。

后复权以上市首日价格为基准,调整后续价格。优点是历史价格固定,适合长期回测;缺点是当前价格与市场不一致,不便于直观理解。

涨跌幅还原是更精细的处理方式:不直接调整价格,而是计算每日涨跌幅时,将除权除息日的涨跌幅用“除权除息参考价”还原。这种方式最准确,但需要数据商提供完整的除权除息因子。

在多因子模型中,建议使用后复权价格计算收益率,因为因子计算需要历史价格的一致性。但在展示净值曲线时,可以转换为前复权价格,便于投资者理解。

常见误区:很多初学者直接使用数据商提供的“复权因子”字段,但不同数据商的复权因子定义不同。有的复权因子是乘法因子,有的是加法因子;有的包含分红再投资假设,有的不包含。务必阅读数据商的文档,确认复权因子的计算逻辑,并在代码中显式标注。

4.5 实战场景:从原始数据到可用因子面板

下面通过一个完整案例,串联本章所有知识点。假设我们需要构建一个包含“市盈率倒数(EP)”、“市净率倒数(BP)”、“过去 20 日收益率(MOM20)”三个因子的模型,数据源为聚宽,时间范围为 2018 年 1 月至 2023 年 12 月。

第一步:数据源体检。从聚宽下载全部 A 股日线数据,与 Wind 数据对比 10 只样本股票的收盘价,发现 2019 年 7 月某只股票在聚宽的收盘价与 Wind 差异 0.3%,排查后确认是聚宽在该日未处理停牌状态,导致价格未更新。解决方案:在数据下载时增加“停牌标记”字段,后续计算收益率时跳过停牌日。

第二步:缺失值处理。财务数据(PE、PB)存在约 5% 的缺失,主要集中在次新股和 ST 股。采用行业中性化填充:按申万一级行业分组,用行业中位数填充。对于 ST 股,单独标记,不参与填充,因为 ST 股的财务数据本身具有特殊性。

第三步:异常值识别。对 EP 和 BP 因子分别计算 MAD,发现 EP 因子有 2.3% 的异常值,BP 因子有 1.8% 的异常值。对这些异常值进行 1% 分位数 Winsorize 处理。MOM20 因子没有发现异常值,因为收益率本身已经经过标准化。

第四步:复权处理。使用聚宽提供的后复权价格计算 MOM20 因子。在除权除息日,聚宽的后复权价格已经自动调整,无需额外处理。但需要验证:随机抽取 10 只股票,手动计算除权日的涨跌幅,与聚宽数据对比,确认误差在 0.01% 以内。

第五步:质量校验。生成最终面板数据后,检查以下指标:时间戳是否连续、股票代码是否唯一、因子值分布是否合理(EP 因子应在 -0.1 到 0.1 之间,BP 因子应在 0 到 1 之间)、是否存在极端值(超过 5 倍 MAD)。

案例复盘:该流程耗时约 2 个工作日,其中数据源体检占 0.5 天,缺失值处理占 0.5 天,异常值识别占 0.5 天,复权验证占 0.5 天。最终得到的因子面板数据,在后续回测中表现稳定,未出现因数据问题导致的净值异常。关键经验是:数据清洗不是一次性工作,而是需要建立自动化流水线,每次新增数据时自动执行相同的清洗逻辑,并输出质量报告。

4.6 总结复盘:数据清洗的五个核心原则

数据准备与清洗是量化研究中最“枯燥”但最“值钱”的环节。总结五个核心原则:

  1. 可追溯性:每一步清洗操作都要有日志记录,确保任何因子值都可以回溯到原始数据。
  2. 行业中性化:填充和异常值处理都要考虑行业差异,避免引入行业偏差。
  3. 稳健优先:优先使用 MAD 等稳健统计量,而不是依赖正态分布假设。
  4. 复权一致性:整个研究流程中,收益率计算必须统一使用同一种复权方式,不能混用。
  5. 自动化与监控:将清洗流程封装为自动化脚本,每次数据更新后自动运行,并输出质量报告(缺失率、异常率、复权因子变化等)。

数据清洗的质量直接决定了因子有效性的上限。一个优秀的量化研究员,首先是一个优秀的数据工程师。掌握本章内容,你就为后续的因子计算、组合优化和回测验证打下了坚实的地基。