3. 因子数据获取:数据源选择、数据清洗与对齐、数据存储方案

因子研究的第一步是获取高质量、可回溯的原始数据。数据源的选择直接影响因子复现的可靠性、研究效率以及后续模型服务化的成本。本节将系统对比主流数据源,并给出数据清洗、对齐与存储的工程化方案。

3.1 数据源选择:Wind、Tushare、聚宽对比

国内量化研究常用的数据源可分为三类:商业终端(Wind)、开源社区平台(Tushare)以及在线量化平台(聚宽/JQData)。三者在数据覆盖、更新频率、获取方式与成本上存在显著差异。

对比维度 Wind (WindPy) Tushare Pro 聚宽 (JQData)
数据覆盖 A股、港股、期货、期权、债券、基金、宏观、行业等全品类 A股、指数、基金、期货、港股通、部分宏观 A股、指数、基金、期货、行业、财务、估值
历史深度 1990年至今,日/分钟/ tick 级别 2000年至今,日/分钟级别 2005年至今,日/分钟级别
更新频率 实时行情,盘后数据通常在 17:00 前完成 盘后更新,通常在 18:00-20:00 盘后更新,通常在 17:30-19:00
获取方式 本地客户端 + COM/DLL/Python API (WindPy) HTTP RESTful API (Token 鉴权) Python SDK (JQData) / HTTP API
费用 年费数万至数十万(机构为主) 积分制,基础免费,高频/高级数据需付费 按量计费或订阅制,有免费额度
本地化部署 需安装 Wind 客户端,依赖 Windows 环境 纯云端 API,无需本地数据库 纯云端 API,无需本地数据库
典型场景 机构投研、实时风控、全品种覆盖 个人研究、因子回测、中小团队 在线策略开发、回测、模拟交易
选型建议: 机构环境优先使用 Wind 作为权威数据源,确保数据合规与审计要求;个人或小团队研究可选用 Tushare Pro 或聚宽 JQData,成本低且上手快。若需高频 tick 数据或深度财务明细,Wind 仍是首选。

3.2 数据清洗与对齐:因子研究的“地基工程”

原始数据通常存在缺失值、异常值、复权不一致、停牌、退市等问题。数据清洗与对齐的目标是生成一张干净、连续、可计算的“因子宽表”。

3.2.1 核心清洗步骤

  1. 缺失值处理: 对日频数据,前向填充(ffill)或行业均值填充;对财务数据,使用最新报告期数据。
  2. 异常值检测: 使用 MAD(中位数绝对偏差)或百分位截尾法(如 1%/99% 截尾)处理极端值。
  3. 复权处理: 统一使用后复权价格计算收益率,避免分红送股导致的收益率跳跃。
  4. 停牌与退市标记: 停牌期间收益率置为 NaN,退市股票在退市日之后剔除。
  5. 行业分类对齐: 统一使用申万一级/二级行业分类,避免不同数据源分类不一致。

3.2.2 数据对齐:时间戳与股票池

多因子模型要求所有因子在同一时间截面、同一股票池内对齐。对齐规则如下:

  • 时间对齐: 交易日历统一使用上交所/深交所交易日历,剔除非交易日。
  • 股票池对齐: 每日仅保留上市状态正常、非 ST、非停牌的股票。
  • 频率对齐: 日频因子与日频收益率对齐;分钟因子需先聚合为日频再对齐。
对齐后的数据格式(示例): 一张宽表,行索引为日期,列索引为股票代码,值为因子值或收益率。这是后续因子检验与模型训练的标准输入。

3.3 数据存储方案:从本地文件到分布式数据库

数据存储方案需兼顾读写性能、存储成本与扩展性。根据数据规模与使用场景,推荐以下分层存储架构。

因子数据分层存储架构 第1层:原始数据层 (Raw Data) Wind / Tushare / 聚宽 原始API数据,按日期+品种分区存储 第2层:清洗对齐层 (Cleaned & Aligned) 缺失填充、异常截尾、复权统一、股票池对齐后的因子宽表 第3层:因子存储层 (Factor Store) Parquet 列存 / ClickHouse / DolphinDB,支持快速截面查询 第4层:服务化层 (Model Serving)

3.3.1 存储方案对比

存储方案 适用场景 优点 缺点
Parquet 文件 单机研究、小团队(< 1TB) 列存压缩、与 Pandas/Polars 无缝集成、成本低 不支持并发写入、无索引
ClickHouse 中大规模因子库(1TB-10TB) 列存、高压缩比、支持 SQL 实时查询 运维成本较高、不适合频繁更新
DolphinDB 高频因子、时序大数据 内置时序引擎、窗口函数优化、分布式 学习曲线陡、社区较小
PostgreSQL + TimescaleDB 中小规模、需要事务支持 成熟生态、支持 SQL 与时间分区 列存性能不如专用方案

3.3.2 推荐实践:Parquet + 分区 + 索引

对于大多数因子研究团队,推荐使用 Parquet 格式 + 日期分区 + 股票代码排序 的存储方案。示例代码:

import pandas as pd
import pyarrow.parquet as pq

# 假设 factor_df 为清洗对齐后的宽表
# 列:date, stock_code, factor_value, return_1d
factor_df['date'] = pd.to_datetime(factor_df['date'])

# 按日期分区存储
for date_val, group_df in factor_df.groupby(factor_df['date'].dt.date):
    partition_path = f"data/factors/{date_val}/factor_data.parquet"
    group_df.to_parquet(
        partition_path,
        index=False,
        compression='snappy',
        row_group_size=100000
    )

# 读取指定日期范围的数据
start_date = '2024-01-01'
end_date = '2024-06-30'
read_df = pd.read_parquet(
    'data/factors/',
    filters=[('date', '>=', start_date), ('date', '<=', end_date)]
)
print(f"Loaded {len(read_df)} rows from {start_date} to {end_date}")
避坑提示: 避免将原始数据直接存入关系型数据库(如 MySQL)进行因子计算。行存数据库在截面查询(查询某日所有股票因子值)时性能极差,且存储膨胀严重。始终优先使用列存格式或时序数据库。

3.4 数据流水线工程化

将数据获取、清洗、对齐、存储串联为自动化流水线,是因子研究可复现的基础。推荐使用 Airflow / Prefect 调度 DAG,每日自动执行:

  1. 数据拉取: 从 Wind/Tushare 拉取日频行情、财务数据。
  2. 清洗对齐: 执行缺失填充、异常处理、复权、股票池过滤。
  3. 因子计算: 调用因子计算模块,生成因子宽表。
  4. 存储写入: 将因子数据写入 Parquet 分区或 ClickHouse 表。
  5. 数据校验: 检查数据完整性(行数、缺失率、极值),触发告警。
关键指标: 一个典型的日频因子流水线(覆盖全A股,约5000只股票,10年历史)在单机 SSD 上可在 15-30 分钟内完成全流程。若使用 ClickHouse 或 DolphinDB,查询单日截面因子值可在毫秒级返回。