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 财务数据获取与对齐
财务数据的关键在于时间对齐:财报的“报告期”与“发布日期”不同。因子计算时,必须使用在回测日期之前已发布的财务数据,避免未来信息泄露。
财务数据对齐的核心规则:
- 使用最新可用财报:对于每个交易日,取该日期之前最新发布的季报或年报。
- 避免前向偏差:不能使用未来发布的财报数据来计算当日的因子值。
- 处理缺失值:新上市股票或刚披露财报的股票,需用前一期数据填充或剔除。
下表展示了财务数据对齐的典型逻辑:
| 交易日 | 最新可用财报报告期 | 财报发布日期 | 对齐后的净利润(万元) |
|---|---|---|---|
| 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 数据对齐:多源数据的时间戳统一
行情数据、财务数据和因子数据通常来自不同系统,时间戳格式和精度可能不一致。数据对齐的核心是建立一个统一的交易日历,将所有数据映射到该日历上。
对齐后的数据以面板数据形式存储,每一行代表一个股票在某个交易日的因子值。标准格式如下:
| 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 类或函数,并加入日志记录。每次运行回测前自动执行数据校验,可大幅减少因数据问题导致的回测错误。
完成以上步骤后,我们就拥有了一个干净、对齐、可用于因子研究的面板数据集。下一阶段将基于这些数据计算具体的因子值,并评估其预测能力。