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

做因子研究,第一步就是搞数据。这一步要是没做好,后面所有模型都是空中楼阁。我见过太多人花大把时间调参数,结果发现是数据没对齐——白忙活一场。

今天咱们就聊聊,怎么把数据这关过得漂亮。

3.1 数据源选择:各有各的脾气

国内主流的数据源,我接触过三个:Wind、Tushare、聚宽。每个都有自己的性格,选哪个得看你的场景。

数据源 优势 劣势 适合场景
Wind 数据全、权威、更新快 贵、接口老、需要本地环境 机构、实盘、高频
Tushare 免费、社区活跃、文档好 有积分限制、偶尔不稳定 个人研究、回测
聚宽 一站式、因子库内置、回测方便 数据范围有限、定制化弱 快速验证、入门

我个人习惯:研究阶段用Tushare,跑实盘用Wind。为什么?Tushare免费,随便折腾不心疼。但真要上实盘,Wind的数据质量更稳,少踩坑。

小技巧:如果你刚开始做因子研究,别一上来就买Wind。先用Tushare把逻辑跑通,等要上实盘了再换。省钱又省心。

3.2 数据清洗:脏数据是最大的敌人

数据拿到手,第一件事不是算因子,而是洗数据。你想想看,如果原始数据里就有错误,算出来的因子能靠谱吗?

我遇到过最离谱的一次:某只股票某天的收盘价突然跳了20%,查了半天,原来是数据源把除权除息日搞错了。嗯,从那以后我养成了个习惯——每次拿到数据,先做三件事。

3.2.1 缺失值处理

股票停牌、数据缺失,太常见了。我的处理原则是:

  • 单日缺失:用前向填充,也就是用上一个交易日的数据补上
  • 连续多日缺失:直接剔除,别硬补
  • 上市不满60天:剔除,新股数据不稳定
# 一个简单的清洗函数
def clean_data(df):
    # 前向填充单日缺失
    df = df.fillna(method='ffill')
    # 剔除上市不满60天的股票
    df = df[df['list_days'] >= 60]
    # 剔除连续缺失超过5天的
    df = df[df['missing_days'] <= 5]
    return df
注意:千万别用均值填充金融数据!股票价格不是正态分布,均值填充会引入巨大偏差。我曾经见过有人这么干,结果因子IC直接崩了。

3.2.2 异常值处理

什么叫异常值?比如某只股票市盈率突然变成10000倍,或者换手率突然飙到50%。这些多半是数据错误,不是市场行为。

我的做法是:用MAD(中位数绝对偏差)法,比3σ更稳健。为什么?因为金融数据本身就有厚尾,3σ会把很多正常值误杀。

def mad_outlier_detection(series, n=5):
    median = series.median()
    mad = (series - median).abs().median()
    threshold = n * mad
    return (series - median).abs() > threshold

3.3 数据对齐:时间是个大问题

做多因子模型,最头疼的就是对齐。不同股票的交易时间不一样,不同数据源的更新频率也不一样。你想想看,如果A股和港股的数据没对齐,算出来的因子能准吗?

核心原则:以最慢的数据源为准。比如你的因子需要用到财务数据,财务数据是季度更新,那所有日频数据都得对齐到季度末。

我一般这么做:

  1. 先确定因子计算的最小时间单位(日频、周频、月频)
  2. 把所有数据都resample到这个频率
  3. 用前向填充,保证每个时间点都有数据
避坑指南:我曾经犯过一个错——用当天的收盘价和当天的财务数据算因子。但财务数据是盘后发布的,当天根本拿不到。正确的做法是用T-1的财务数据配T的收盘价。

3.4 数据存储:选对方案省一半时间

数据存得好不好,直接影响回测速度。我见过有人把所有数据存成CSV,回测一次跑三天。换个存储方案,可能半小时就搞定了。

3.4.1 存储方案对比

方案 读取速度 存储空间 易用性 适合场景
CSV 小规模、临时
HDF5 中等规模、单机
Parquet 极快 极小 大规模、分布式
数据库 团队协作、生产

我的推荐:个人研究用HDF5,团队协作用Parquet+数据库。别问我为什么不用CSV——等你数据量到10G以上,CSV的读取速度会让你崩溃。

3.4.2 存储结构设计

我习惯按因子类型分目录存储,每个因子一个文件。这样查找方便,更新也简单。

data/
├── factor/
│   ├── momentum/
│   │   ├── momentum_1m.h5
│   │   ├── momentum_3m.h5
│   │   └── momentum_6m.h5
│   ├── value/
│   │   ├── pe.h5
│   │   ├── pb.h5
│   │   └── ps.h5
│   └── quality/
│       ├── roe.h5
│       └── roa.h5
└── raw/
    ├── price.h5
    ├── volume.h5
    └── financial.h5
小建议:每次更新数据时,保留一份原始数据备份。万一清洗逻辑出错了,还能回滚。我吃过这个亏,现在每次更新都先备份。

3.5 知识体系总览

说了这么多,咱们用一张图把整个流程串起来。从数据源到最终存储,每一步都有讲究。

因子数据获取流程 数据源选择 数据清洗 数据对齐 数据存储 Wind / Tushare / 聚宽 缺失值 / 异常值处理 时间对齐 / 频率统一 HDF5 / Parquet / 数据库

说白了,数据获取这件事,80%的功夫都在清洗和对齐上。数据源选对了,存储方案选好了,剩下的就是耐心和细心。别嫌麻烦,这一步做好了,后面的回测才能又快又准。

专注资料整理