2. 数据准备:获取股票行情数据、财务数据、因子原始数据清洗与对齐

因子研究的第一步也是最耗时的一步,是构建高质量、对齐良好的数据集。本章将系统讲解如何获取股票行情数据、财务数据,并对因子原始数据进行清洗与对齐,确保后续分析建立在可靠的数据基础之上。

2.1 数据获取来源与类型

量化研究通常需要两类核心数据:行情数据(高频或日频)和财务数据(季报/年报)。下表对比了常见数据源及其特点:

数据类别 常见来源 频率 关键字段 注意事项
日频行情 Wind、Tushare、聚宽 日 open, high, low, close, volume, adj_factor 需复权处理,注意除权除息日
分钟行情 Level-2、掘金 1min / 5min 开盘价、收盘价、成交量、成交额 数据量大,需压缩存储
财务数据 Wind、东方财富、CSMAR 季 / 年 营业收入、净利润、总资产、净资产 注意财报发布日期 vs 报告期
因子数据 自建 / 第三方 日 / 月 估值、动量、质量、情绪等 需对齐时间戳与股票池
实战建议:优先使用日频行情 + 季频财务数据作为入门组合。日频数据平衡了信息量与存储成本,季频财务数据则能覆盖大部分基本面因子计算需求。

2.2 行情数据获取与复权处理

获取行情数据时,复权处理是必须完成的步骤。未复权的价格序列会因分红、送股、配股等事件产生跳空,导致技术指标失真。复权分为前复权和后复权:

  • 前复权:调整历史价格,使当前价格保持不变。适合回测,因为最新价格是真实交易价。
  • 后复权:调整当前价格,使历史价格保持不变。适合分析长期收益率。

以下代码展示了使用 Python 获取日频行情并执行前复权的典型流程:

import pandas as pd
import numpy as np

def fetch_daily_data(code, start_date, end_date):
    """
    模拟获取日频行情数据(实际使用中替换为API调用)
    返回包含复权因子的DataFrame
    """
    # 模拟数据:包含原始价格和复权因子
    dates = pd.date_range(start=start_date, end=end_date, freq='B')
    n = len(dates)
    df = pd.DataFrame({
        'date': dates,
        'close': np.random.randn(n).cumsum() + 20,
        'adj_factor': np.linspace(1.0, 1.5, n)  # 模拟复权因子递增
    })
    df['adj_close'] = df['close'] * df['adj_factor']
    return df

# 前复权:调整历史价格
df = fetch_daily_data('000001.SZ', '2023-01-01', '2023-12-31')
df['pre_adj_close'] = df['adj_close'] / df['adj_factor'].iloc[-1] * df['adj_factor'].iloc[-1]
print(df[['date', 'close', 'adj_close', 'pre_adj_close']].head())
常见陷阱:部分数据源提供的复权因子是累计复权因子,需确认其计算基准。另外,复权因子在除权除息日才会更新,回测时需避免使用未来复权因子。

2.3 财务数据获取与对齐

财务数据的关键在于时间对齐:财报的“报告期”与“发布日期”不同。因子计算时,必须使用在回测日期之前已发布的财务数据,避免未来信息泄露。

财务数据对齐的核心规则:

  1. 使用最新可用财报:对于每个交易日,取该日期之前最新发布的季报或年报。
  2. 避免前向偏差:不能使用未来发布的财报数据来计算当日的因子值。
  3. 处理缺失值:新上市股票或刚披露财报的股票,需用前一期数据填充或剔除。

下表展示了财务数据对齐的典型逻辑:

交易日 最新可用财报报告期 财报发布日期 对齐后的净利润(万元)
2023-04-20 2022年报 2023-03-31 12,500
2023-04-28 2023一季报 2023-04-26 3,200
2023-07-15 2023一季报 2023-04-26 3,200
2023-07-20 2023中报 2023-07-18 6,800

2.4 因子原始数据清洗流程

因子原始数据通常包含缺失值、异常值和幸存者偏差等问题。标准清洗流程包含以下步骤:

  • 缺失值处理:对于缺失率超过 50% 的因子,直接剔除;对于低缺失率因子,使用截面中位数或行业均值填充。
  • 异常值处理:采用 MAD(中位数绝对偏差)方法,将超过 5 倍 MAD 的极端值缩尾至 5 倍 MAD。
  • 标准化:将因子值转换为 Z-score,或进行排序分位数处理(Rank),消除量纲影响。
  • 行业与市值中性化:对因子值做行业和市值回归,取残差作为中性化后的因子值。
清洗效果验证:清洗前后因子分布应发生明显变化。清洗后因子应近似正态分布,且极端值被有效控制。建议在清洗前后分别绘制因子分布直方图进行对比。

2.5 数据对齐:多源数据的时间戳统一

行情数据、财务数据和因子数据通常来自不同系统,时间戳格式和精度可能不一致。数据对齐的核心是建立一个统一的交易日历,将所有数据映射到该日历上。

多源数据对齐流程 多源数据对齐流程 行情数据 日频 / 分钟频 财务数据 季频 / 年频 因子原始数据 自建 / 第三方 统一交易日历(A股交易日) 剔除周末、法定节假日、停牌日 对齐处理 行情复权 → 财务向前填充 → 因子截面匹配 对齐后的因子面板数据

对齐后的数据以面板数据形式存储,每一行代表一个股票在某个交易日的因子值。标准格式如下:

trade_date stock_code adj_close pe_ttm momentum_20d volatility_60d
2023-01-04 000001.SZ 12.35 8.52 0.032 0.185
2023-01-04 000002.SZ 9.87 6.14 -0.015 0.221
2023-01-05 000001.SZ 12.42 8.55 0.028 0.183

2.6 数据质量检查清单

在完成数据准备后,建议逐项检查以下内容,确保数据质量:

  • 时间范围完整性:检查每个股票在回测区间内是否有连续的交易记录。
  • 复权因子合理性:复权因子应单调递增(后复权)或递减(前复权),且变化幅度与分红送股比例匹配。
  • 财务数据无未来信息:随机抽取若干交易日,验证使用的财务数据确实在该日期之前已发布。
  • 因子值分布:清洗后因子值的偏度和峰度应接近正态分布,极端值占比低于 1%。
  • 跨截面一致性:同一交易日不同股票的因子值应具有可比性,行业中性化后行业均值应接近零。
效率提升技巧:将数据获取、清洗和对齐流程封装为可复用的 Python 类或函数,并加入日志记录。每次运行回测前自动执行数据校验,可大幅减少因数据问题导致的回测错误。

完成以上步骤后,我们就拥有了一个干净、对齐、可用于因子研究的面板数据集。下一阶段将基于这些数据计算具体的因子值,并评估其预测能力。