第二章:数据获取与清洗——股票/期货数据源与实战清洗

做量化交易,数据就是你的“原材料”。

我见过太多人,策略写得天花乱坠,结果一跑回测,数据全是坑。嗯,今天我们就来聊聊,怎么拿到靠谱的数据,以及怎么把它洗得干干净净。

2.1 三大主流数据源:tushare、akshare、baostock

国内做量化,绕不开这三个库。我个人的习惯是:tushare 做深度分析,akshare 做快速验证,baostock 做免费回测。你想想看,各有各的脾气。

数据源 特点 适合场景 注意点
tushare 数据全、质量高,但部分接口需要积分 专业回测、因子研究 token 要提前申请,别等到跑代码才想起来
akshare 免费、接口多,但偶尔不稳定 快速原型、实时数据 网络波动时容易断,建议加重试机制
baostock 纯免费、数据干净,但更新有延迟 历史回测、教学演示 不支持日内高频数据
我的小建议:刚开始学,先用 baostock 练手。等你要做实盘了,再上 tushare。别一上来就充积分,先看看自己到底需要什么。

2.2 数据获取实战:三行代码搞定

说白了,获取数据就是调个 API。但这里有个坑——日期格式。我曾经因为日期传了个字符串,结果数据全乱套了。

# 用 baostock 获取平安银行日线数据
import baostock as bs
import pandas as pd

# 登录
lg = bs.login()
# 获取数据
rs = bs.query_history_k_data_plus(
    "sz.000001",
    "date,open,high,low,close,volume",
    start_date='2023-01-01',
    end_date='2023-12-31',
    frequency='d',
    adjustflag='3'  # 复权类型:3 表示不复权
)
# 转成 DataFrame
data_list = []
while (rs.error_code == '0') & rs.next():
    data_list.append(rs.get_row_data())
df = pd.DataFrame(data_list, columns=rs.fields)
bs.logout()
print(df.head())
避坑指南:我曾经在循环里忘记调用 rs.next(),结果死循环了半小时。记得检查 error_code,别偷懒。

2.3 数据清洗实战:去重、填充、异常值处理

数据拿到手,别急着跑策略。先看看有没有脏数据。我一般按这个流程走:

  1. 去重:同一根 K 线出现两次,直接删掉。
  2. 填充:缺失值用前值填充,或者用插值法。
  3. 异常值:涨跌幅超过 20% 的,多半是数据错误。

2.3.1 去重:别让重复数据骗了你

为什么会重复?有时候是网络重传,有时候是 API 抽风。我习惯用 drop_duplicates(),但要注意指定列。

# 去重:按日期和股票代码去重
df = df.drop_duplicates(subset=['date', 'code'])
# 检查还有没有重复
print(df.duplicated(subset=['date', 'code']).sum())
重点:去重一定要指定 subset,不然会把所有列都一样的行删掉。你想想看,如果两根 K 线除了日期不同其他都一样,那就不该删。

2.3.2 填充:缺失值怎么补?

缺失值在期货数据里特别常见,尤其是节假日。我个人的经验是:股票用前值填充,期货用插值法

# 前值填充(适合股票)
df['close'] = df['close'].fillna(method='ffill')

# 线性插值(适合期货)
df['close'] = df['close'].interpolate(method='linear')
我的习惯:填充前先看看缺失比例。如果超过 5%,那可能是数据源有问题,别硬填。

2.3.3 异常值处理:别让一根针毁了整个策略

我记得有一次回测,策略收益高得离谱。一查,原来是某天收盘价多了一个零。嗯,这种异常值必须处理。

# 用 3 倍标准差法检测异常值
import numpy as np

mean = df['close'].mean()
std = df['close'].std()
df['is_outlier'] = (np.abs(df['close'] - mean) > 3 * std)

# 将异常值替换为前值
df.loc[df['is_outlier'], 'close'] = df['close'].shift(1)
注意:别一棍子打死所有异常值。比如 2015 年股灾,那几天涨跌幅确实大,但那是真实行情。我建议结合 涨跌幅阈值成交量 一起判断。

2.4 本章知识体系

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

数据获取与清洗核心流程 数据获取 tushare / akshare / baostock 去重 drop_duplicates(subset) 填充缺失值 ffill / interpolate 异常值处理 3σ / 涨跌幅阈值 / 成交量辅助 数据质量检查 缺失比例 / 重复率 / 极值 发现问题?返回重新清洗

这张图的核心逻辑是:获取 → 去重 → 填充 → 异常值处理 → 检查。如果检查不通过,就回到去重那一步重新来。说白了,数据清洗是个迭代的过程,别指望一次搞定。

最后说一句:数据清洗占了我整个量化工作量的 60% 以上。别嫌麻烦,这一步做扎实了,后面的策略开发会顺很多。

专注资料整理