第二章 数据获取与清洗:数据源选择、字段说明与清洗流程

做量化回测,第一步就是搞数据。

数据搞不定,后面全是白搭。我见过太多人,策略写得花里胡哨,结果数据源选错了,或者复权没处理好,回测曲线漂亮得像假的一样。嗯,今天我们就来聊聊数据获取与清洗这档子事。

2.1 数据源选择:tushare / akshare / baostock

国内常用的免费数据源,我主要用过这三个:tushare、akshare、baostock。各有各的脾气。

数据源 特点 适合场景 我的评价
tushare 数据全,但高权限需要积分 专业回测、因子研究 老牌,稳定,但门槛渐高
akshare 免费,接口丰富,更新快 快速原型、小规模回测 我最近用得最多
baostock 免费,无需注册,数据规范 入门学习、简单回测 省心,但数据量有限

我个人习惯是:做研究用 baostock,做策略开发用 akshare,做正式回测用 tushare。为什么?因为 tushare 的复权数据最干净,我踩过坑才知道。

注意: tushare 的 pro 接口需要 token,而且高频调用会被限流。我曾经一次性拉5年数据,结果被 ban 了半小时。

2.2 数据字段说明

不管用哪个数据源,核心字段就那么几个。我列个表,你对照着看。

字段名 含义 类型 备注
trade_date 交易日期 datetime 注意格式统一
open 开盘价 float 复权后价格
high 最高价 float 同上
low 最低价 float 同上
close 收盘价 float 核心字段
volume 成交量 int 单位:股
amount 成交额 float 单位:元

你想想看,如果拿到的数据里 open 比 close 还高,或者 volume 是负数,那肯定有问题。我遇到过某数据源某天的 volume 字段全是 0,查了半天才发现是接口 bug。

2.3 数据清洗流程

数据清洗,说白了就是「去伪存真」。我的标准流程分四步:

  1. 格式统一:日期转 datetime,价格转 float,成交量转 int
  2. 排序去重:按日期升序,删除重复行
  3. 异常值检测:价格不能为负,成交量不能为 0(停牌除外)
  4. 缺失值处理:见下一节

代码示例,我一般这么写:

import pandas as pd

def clean_stock_data(df):
    # 1. 格式统一
    df['trade_date'] = pd.to_datetime(df['trade_date'])
    df = df.sort_values('trade_date')
    
    # 2. 去重
    df = df.drop_duplicates(subset=['trade_date'])
    
    # 3. 异常值过滤
    df = df[(df['close'] > 0) & (df['volume'] >= 0)]
    
    # 4. 缺失值处理(前向填充)
    df = df.fillna(method='ffill')
    
    return df
小技巧: 我习惯在清洗后加一个「数据完整性检查」,比如看看日期是否连续,有没有跳空。曾经有个策略因为数据跳了三天,回测结果完全失真。

2.4 缺失值处理

缺失值怎么处理?分情况。

  • 停牌导致的缺失:用前一天的收盘价填充,或者直接删除该行
  • 数据源本身缺失:比如某天没有数据,我建议用前向填充(ffill)
  • 节假日缺失:正常现象,不用处理

我个人习惯是:回测时用 ffill,实盘时用插值。为什么?因为回测是事后看,用前一天的价格更合理;实盘是实时,插值能平滑一些。

避坑指南: 我曾经用均值填充缺失值,结果把一只连续跌停的股票填成了上涨,回测曲线漂亮得不行,实盘直接亏哭。从那以后,我再也不敢乱填缺失值了。

2.5 复权数据处理

复权,这是个大坑。

说白了,股票分红送股后,价格会跳空。如果不复权,你的回测会失真。比如一只股票从 100 块跌到 50 块,你以为亏了 50%,其实是 10 送 10,实际没亏。

复权有两种:

  • 前复权:调整历史价格,让价格连续。适合看趋势
  • 后复权:调整当前价格,适合算真实收益

我建议回测时用 前复权。为什么?因为前复权后的价格更接近真实交易成本。后复权算出来的收益虽然准确,但价格太高,看着不直观。

代码示例,用 tushare 获取前复权数据:

import tushare as ts

pro = ts.pro_api('你的token')
df = pro.daily(ts_code='000001.SZ', 
               start_date='20200101', 
               end_date='20231231',
               adj='qfq')  # qfq 表示前复权
我的经验: 如果你用 akshare,复权参数是 adjust="qfq"。baostock 默认返回的就是前复权数据,省心。但记得检查一下,我遇到过 baostock 某只股票复权数据有误的情况。

2.6 本章知识体系图

下面这张图,是我自己总结的数据获取与清洗流程。你照着走,基本不会出大问题。

数据获取与清洗流程 数据源选择 tushare/akshare/baostock 数据获取 字段:open/close/volume 数据清洗 格式/去重/异常 缺失值处理 ffill/插值/删除 复权处理 前复权/后复权 最终数据 可用于回测的干净数据 关键检查点 ✅ 日期是否连续? ✅ 价格是否为正? ✅ 复权是否正确? ✅ 成交量是否合理? ✅ 是否有异常跳空?

核心要点:

  • 数据源选对,后面省一半功夫
  • 清洗流程要标准化,别偷懒
  • 缺失值处理要谨慎,别乱填
  • 复权必须做,前复权是首选

好了,数据获取与清洗就聊这么多。记住一句话:数据质量决定回测质量。你花 80% 的时间在数据上,都不为过。

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