数据基础设施(一):数据源选择、清洗与对齐

做量化回测,数据就是你的命根子。

这话听起来有点夸张,但你想想看,策略写得再漂亮,数据一塌糊涂,结果全是垃圾。我在这个坑里摔过好几次,所以今天专门聊聊数据基础设施的第一部分——数据源怎么选,数据怎么洗,怎么对齐。

一、数据源选择:Wind、Tushare、Quandl

市面上数据源很多,但真正能用的,其实就那几家。我个人习惯把数据源分成三类:机构级、开源级、国际级。

数据源 类型 适用场景 成本
Wind 机构级 私募、券商、公募 高(年费数万)
Tushare 开源级 个人、小团队 低(积分制)
Quandl 国际级 全球宏观、期货 部分免费

1. Wind:机构标配,但别迷信

Wind 的数据质量确实高,字段全,更新快。但说实话,它也有坑。我记得有一次做国债期货回测,Wind 的连续合约数据在换月时居然有跳空,差点把我的策略搞崩了。

用 Wind 的话,我建议你注意两点:一是它的 API 返回格式经常变,二是历史数据偶尔会有修正。所以哪怕用 Wind,也要做二次校验。

2. Tushare:个人玩家的首选

Tushare 是我个人用得最多的。免费、文档全、社区活跃。但有个问题——它的数据偶尔会缺失,尤其是早期数据。比如 2015 年之前的某些小盘股,日线数据可能少几天。

我曾经因为 Tushare 的复权数据没对齐,导致回测结果差了 3 个点。后来我养成了一个习惯:拿到数据后,先跟 Wind 或者交易所官网交叉验证一下。

3. Quandl:做全球宏观必备

如果你做的是全球宏观策略,Quandl 几乎是绕不开的。它的美联储数据、各国 GDP、CPI 都很全。但要注意,Quandl 的免费额度有限,而且有些数据集更新频率很低。

嗯,这里有个小技巧:Quandl 的数据可以用 pandas-datareader 直接拉,省去手动下载的麻烦。

核心建议:不要只依赖一个数据源。我自己的做法是:Wind 做主数据源,Tushare 做补充,Quandl 做国际数据。三个源交叉验证,基本能覆盖 99% 的问题。

二、数据清洗:脏数据是回测的头号杀手

数据源选好了,接下来就是洗数据。说白了,就是把那些乱七八糟的脏数据清理掉。

1. 常见脏数据类型

  • 重复数据:同一时间戳出现多条记录
  • 空值:某一天的数据完全缺失
  • 异常值:价格突然跳涨 1000% 这种
  • 格式错误:日期格式不统一、数字带逗号等

我遇到过最离谱的一次,是某数据源把 2023-01-01 的数据写成了 2023-01-00。这种低级错误,人工查根本查不出来,必须靠代码自动化检测。

2. 清洗流程示例

import pandas as pd
import numpy as np

def clean_data(df):
    # 1. 去重
    df = df.drop_duplicates(subset=['date', 'code'])
    
    # 2. 处理空值
    df = df.fillna(method='ffill')  # 前向填充
    
    # 3. 异常值检测(3-sigma)
    for col in ['open', 'high', 'low', 'close']:
        mean = df[col].mean()
        std = df[col].std()
        df = df[(df[col] > mean - 3*std) & (df[col] < mean + 3*std)]
    
    return df

个人经验:前向填充(ffill)在大多数情况下够用,但遇到停牌或者节假日,最好用插值法。我一般用 pandas 的 interpolate 方法,效果比 ffill 好很多。

三、数据对齐:不同频率的数据怎么合并

做宏观量化,你经常要把日频的股票数据和月频的宏观经济数据放在一起。频率不一样,怎么对齐?

1. 对齐原则

  • 低频向高频对齐:月频数据填充到日频,用前向填充
  • 高频向低频对齐:日频数据聚合到月频,用均值或末值
  • 时间戳对齐:确保所有数据使用同一时区

举个例子,你要把 CPI(月频)和股票收益率(日频)放在一起做回归。我的做法是:先把 CPI 数据前向填充到每个交易日,然后再跟股票数据 merge。

# 低频向高频对齐示例
cpi_daily = cpi_monthly.resample('D').ffill()
merged = pd.merge(stock_daily, cpi_daily, on='date', how='left')

注意:对齐时最容易犯的错误是「未来数据」。比如你用当月的 CPI 数据去预测当月的股票收益,这在回测中是违规的。一定要确保对齐时只使用历史数据。

四、处理缺失值与异常值

数据清洗的最后一步,就是处理那些漏网之鱼。

1. 缺失值处理策略

缺失比例 推荐方法 适用场景
< 5% 前向填充 / 插值 大部分金融数据
5% - 20% 模型预测填充 宏观经济数据
> 20% 直接删除该特征 数据质量太差时

2. 异常值检测方法

我常用的方法有三种:

  • Z-score 法:适合正态分布的数据
  • IQR 法:适合偏态分布的数据
  • 业务规则法:比如股票价格不能为负,涨跌幅不能超过 100%

曾经有一次,我用 Z-score 检测异常值,结果把 2015 年股灾那几天的数据全删了。后来我才意识到,极端行情下的数据不是异常值,而是真实的市场行为。所以我现在更倾向于用业务规则法,结合人工判断。

# IQR 法检测异常值
def detect_outliers_iqr(df, column):
    Q1 = df[column].quantile(0.25)
    Q3 = df[column].quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    return df[(df[column] >= lower_bound) & (df[column] <= upper_bound)]

核心原则:处理缺失值和异常值时,一定要先理解业务背景。不要机械地套用统计方法,否则你会把有用的信息也删掉。

五、本章知识体系

下面这张图,是我自己总结的数据基础设施核心流程。你可以把它当成一个检查清单,每次做数据准备时对照着走一遍。

数据基础设施核心流程 数据源选择 数据清洗 数据对齐 缺失值处理 异常值处理 干净对齐的数据 Wind / Tushare / Quandl 去重 / 格式统一 低频→高频 / 高频→低频 ffill / interpolate / 删除 Z-score / IQR / 业务规则

嗯,数据基础设施这部分内容比较多,今天先讲到这里。记住一句话:数据质量决定了回测的天花板。数据没处理好,后面所有工作都是白费。

蓝海数据掘金营,专注资料整理