第一章 数据模块设计:行情数据获取、数据清洗与对齐、数据存储方案
做量化回测,第一关就是数据。我见过太多人策略写得漂亮,结果数据一塌糊涂,回测曲线美如画,实盘直接崩。说白了,数据模块是整个回测系统的地基,地基不稳,上面盖什么都白搭。
这一章,咱们就聊聊行情数据怎么拿、怎么洗、怎么存。我会把我在实战中踩过的坑、总结的经验,一股脑倒出来。
1.1 行情数据获取:从哪里来,怎么拿
行情数据来源,无非就几种:
- 交易所官方接口:比如上交所、深交所的Level-2行情。数据最准,但门槛高,要申请牌照。
- 第三方数据商:Wind、聚宽、Tushare、AKShare。我早期做回测时,用的就是Tushare,免费、够用。
- 券商内部数据:如果你在机构,一般有内部数据库,直接拉就行。
我个人习惯,先用免费数据源做原型验证,等策略稳定了,再换付费数据。为什么呢?因为免费数据偶尔会有缺失或延迟,但做回测初期,够用了。
举个例子,用Python拉取A股日线数据:
import tushare as ts
# 设置token(去tushare官网注册)
pro = ts.pro_api('你的token')
# 获取平安银行日线数据
df = pro.daily(ts_code='000001.SZ', start_date='20200101', end_date='20231231')
print(df.head())
嗯,这里要注意:免费接口有频率限制,比如每分钟最多请求200次。我曾经写了个循环批量拉数据,结果被限流了,卡了半小时。后来加了个time.sleep(0.3),问题解决。
1.2 数据清洗与对齐:脏数据是回测的隐形杀手
数据拿到手,别急着用。先看看有没有坑。
常见问题:
- 缺失值:某天停牌,数据直接空着。你想想看,如果回测时没处理,策略会以为那天没交易,结果算出来的收益率全是错的。
- 异常值:比如某只股票突然涨了1000%,一看是除权除息没处理。我遇到过,回测曲线直接飞上天,吓我一跳。
- 时间戳不一致:不同数据源的时间格式不同,有的用'2023-01-01',有的用'20230101'。不对齐的话,合并数据时会乱套。
清洗流程:
- 去重:检查是否有重复行,有的话删掉。
- 填充缺失值:停牌日的数据,用前一天的收盘价填充。或者直接删除,看你的策略需求。
- 处理异常值:用3σ原则或IQR方法,把明显离谱的数据标记出来,人工复核。
- 复权处理:股票分红送股后,价格会跳空。必须做前复权或后复权,否则回测失真。
数据对齐,说白了就是让不同品种的数据在时间轴上对齐。比如你要同时交易茅台和五粮液,它们的交易日可能不完全重合。茅台停牌那天,五粮液还在交易。这时候,要么把茅台那天的数据填充为NaN,要么直接剔除那天。
代码示例:
import pandas as pd
# 假设df1是茅台日线,df2是五粮液日线
# 按日期对齐,缺失值用前向填充
df_aligned = pd.merge(df1, df2, on='date', how='outer', suffixes=('_maotai', '_wuliangye'))
df_aligned = df_aligned.sort_values('date').fillna(method='ffill')
1.3 数据存储方案:HDF5 vs Parquet
数据清洗完了,得存起来。存成CSV?别闹,几百万行数据,CSV读写慢得要命,而且不支持压缩。
我推荐两种格式:HDF5 和 Parquet。它们各有千秋。
| 特性 | HDF5 | Parquet |
|---|---|---|
| 读写速度 | 快,尤其适合大量小文件 | 更快,列式存储,查询部分列时极快 |
| 压缩率 | 中等 | 高,Snappy压缩后体积小很多 |
| 跨语言支持 | Python、C++、Java | 几乎所有大数据框架都支持 |
| 适用场景 | 单机回测、小团队 | 分布式系统、大数据量 |
我个人习惯:单机回测用HDF5,因为pandas直接支持,读写方便。生产环境用Parquet,因为要对接Spark、Flink这些大数据框架。
HDF5存储示例:
import pandas as pd
# 存储为HDF5
df.to_hdf('stock_data.h5', key='daily', mode='w', complevel=9)
# 读取
df = pd.read_hdf('stock_data.h5', key='daily')
Parquet存储示例:
# 存储为Parquet
df.to_parquet('stock_data.parquet', compression='snappy')
# 读取
df = pd.read_parquet('stock_data.parquet')
1.4 本章知识体系图
下面这张图,概括了数据模块的核心流程。你可以把它当作一个检查清单,每次做数据准备时,对着走一遍。
这张图里,我特意把「数据校验」画成了一个循环。为什么?因为数据问题往往不是一次就能解决的。你校验发现行数不对,回去查,可能是数据源漏了某天,也可能是清洗时误删了。反复迭代几次,数据才能用。
好了,数据模块的核心内容就这些。记住一句话:数据质量决定回测可信度。别嫌麻烦,把数据搞干净了,后面的策略开发才能安心。