第三章 数据获取:股票数据源选择、Tushare/AkShare接口使用、数据清洗与预处理、数据存储方案

做量化回测,数据就是你的原材料。原材料不行,再好的策略也白搭。我见过太多人花几个月写策略,最后发现数据有坑,回测结果全是假的。今天咱们就把数据获取这件事聊透。

3.1 股票数据源怎么选?

国内主流的数据源,说白了就这几家:Tushare、AkShare、Wind、聚宽、米筐。我个人习惯把数据源分成两类:免费的和收费的。

数据源 费用 特点 适合场景
Tushare Pro 免费+积分制 数据全面,文档规范 个人研究、小规模回测
AkShare 完全免费 接口丰富,更新快 快速原型、学习练手
Wind 收费(年费几万) 数据质量最高 机构、实盘级应用
聚宽/米筐 部分免费 自带回测平台 不想自己搭系统

我建议初学者先从AkShare入手。为什么呢?零成本,接口多,踩坑了也不心疼。等你的策略跑通了,再考虑升级到Tushare或者Wind。

⚠️ 注意: 免费数据源通常有频率限制。比如Tushare每分钟最多调200次接口。我刚开始做回测时没注意这个,结果跑着跑着突然报错,排查了半天才发现是触发了限流。

3.2 Tushare接口使用实战

Tushare Pro需要注册获取token。注册地址我就不贴了,百度一下就有。拿到token后,先初始化:

import tushare as ts

# 初始化
pro = ts.pro_api('你的token')

# 获取日线数据
df = pro.daily(
    ts_code='000001.SZ',
    start_date='20230101',
    end_date='20231231'
)
print(df.head())

嗯,这里要注意。Tushare的股票代码格式是「6位代码+交易所后缀」。上交所是.SH,深交所是.SZ。我见过有人把平安银行的代码写成000001,结果啥也查不到。

除了日线,Tushare还提供分钟线、财务数据、资金流向等。我个人最常用的是这几个:

  • daily() - 日线行情
  • fundamental() - 财务指标
  • moneyflow() - 个股资金流向
  • trade_cal() - 交易日历
💡 小技巧: 交易日历很重要。我每次做回测前,都会先拉一下交易日历,确保数据对齐。否则遇到节假日,你的时间序列就乱了。

3.3 AkShare接口使用实战

AkShare的用法更直接。它不需要token,直接pip安装就能用:

import akshare as ak

# 获取A股日线数据
df = ak.stock_zh_a_hist(
    symbol="000001",
    period="daily",
    start_date="20230101",
    end_date="20231231",
    adjust="qfq"  # 前复权
)
print(df.head())

AkShare的接口命名有点随性。比如获取龙虎榜数据,接口名叫stock_lhb_detail_em()。我第一次用的时候找了半天,后来发现它的命名规则是「功能+数据源缩写」。em代表东方财富,sina代表新浪,thsm代表同花顺。

为什么会这样?因为AkShare本质上是把各个网站的数据接口封装了一下。好处是数据源多,坏处是接口不稳定——万一对方网站改版,你的代码可能就挂了。

核心建议: 生产环境用Tushare,原型开发用AkShare。两条腿走路,哪个挂了都不慌。

3.4 数据清洗与预处理

数据拿到手,别急着用。先做清洗。我总结了一套标准流程:

  1. 去重 - 检查是否有重复行
  2. 补空 - 处理缺失值
  3. 对齐 - 统一时间索引
  4. 复权 - 处理分红送股
  5. 异常值 - 剔除涨跌停等极端数据

举个例子,缺失值处理:

# 前向填充(用上一个交易日的数据补)
df.fillna(method='ffill', inplace=True)

# 或者直接删除缺失行
df.dropna(inplace=True)

我曾经遇到过一个坑:某只股票停牌了三个月,复牌后直接跌停。如果用前向填充,那三个月的价格都是停牌前的价格,回测结果会严重失真。后来我加了一个判断:如果连续缺失超过5天,就标记为停牌,单独处理。

⚠️ 注意: 复权处理一定要做。我见过有人用不复权的数据做回测,结果策略在分红日附近表现异常。说白了,分红除权会导致价格跳空,不复权的话你的策略会误判。

3.5 数据存储方案

数据清洗完了,得存起来。我推荐三种方案:

存储方式 优点 缺点 推荐场景
CSV文件 简单、可读性强 查询慢、占用空间大 小规模、个人研究
HDF5 压缩率高、读写快 不支持并发 中等规模、单机使用
SQLite/MySQL 支持查询、并发好 配置稍复杂 团队协作、生产环境

我个人习惯用HDF5。为什么呢?因为量化数据通常是时间序列,HDF5对这种结构化数据支持得很好。而且pandas直接支持to_hdf()和read_hdf(),代码写起来很顺手。

# 存储到HDF5
df.to_hdf('stock_data.h5', key='000001', mode='a')

# 读取
df = pd.read_hdf('stock_data.h5', key='000001')

如果你要存MySQL,记得建索引。我刚开始没建索引,查一次数据要好几秒,加了索引后毫秒级返回。索引建在日期和股票代码上就行。

总结一下: 数据获取这件事,80%的精力花在清洗和存储上。接口调用反而是最简单的。你想想看,数据质量直接决定回测的可信度。数据有坑,策略再牛也是白搭。

数据获取与处理流程图 数据源选择 Tushare Pro AkShare 数据清洗与预处理 去重 补空 对齐 复权 异常值 数据存储方案 CSV HDF5 SQLite/MySQL
💡 最后说一句: 数据获取是整个回测系统的地基。地基打牢了,后面盖楼才稳。别急着跑策略,先把数据链路跑通、跑稳。我见过太多人在这上面栽跟头了。

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