第二章:数据获取与清洗——股票/期货数据源与实战清洗
做量化交易,数据就是你的“原材料”。
我见过太多人,策略写得天花乱坠,结果一跑回测,数据全是坑。嗯,今天我们就来聊聊,怎么拿到靠谱的数据,以及怎么把它洗得干干净净。
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 数据清洗实战:去重、填充、异常值处理
数据拿到手,别急着跑策略。先看看有没有脏数据。我一般按这个流程走:
- 去重:同一根 K 线出现两次,直接删掉。
- 填充:缺失值用前值填充,或者用插值法。
- 异常值:涨跌幅超过 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 本章知识体系
下面这张图,是我自己总结的数据清洗流程。你照着做,基本不会出大问题。
这张图的核心逻辑是:获取 → 去重 → 填充 → 异常值处理 → 检查。如果检查不通过,就回到去重那一步重新来。说白了,数据清洗是个迭代的过程,别指望一次搞定。
最后说一句:数据清洗占了我整个量化工作量的 60% 以上。别嫌麻烦,这一步做扎实了,后面的策略开发会顺很多。