第三章 金融数据获取:Tushare/AkShare库介绍、股票行情数据获取、财务数据获取、宏观经济数据获取、数据存储与读取
做量化投资,数据就是你的弹药库。
没有数据,再牛的策略也是空中楼阁。我个人习惯把数据获取比作「做饭前的买菜」——菜买不好,厨艺再高也白搭。
这一章,咱们就聊聊怎么「买菜」。而且我会告诉你哪些菜新鲜、哪些菜容易踩坑。
3.1 两大主流数据库:Tushare vs AkShare
国内做量化,绕不开两个库:Tushare 和 AkShare。
说白了,它们都是帮你从各大交易所、财经网站抓数据的「搬运工」。但性格完全不同。
| 对比维度 | Tushare | AkShare |
|---|---|---|
| 数据源 | 自建数据库,稳定 | 爬取公开网站,实时 |
| 免费额度 | 有积分限制,高级数据需付费 | 完全免费 |
| 数据质量 | 高,经过清洗校验 | 中等,偶有缺失 |
| 文档友好度 | 详细,但更新慢 | 更新快,但文档略乱 |
| 适合场景 | 专业研究、回测 | 快速原型、实时监控 |
我自己的经验是:做回测用Tushare,做实时监控用AkShare。两个搭配着用,基本覆盖了90%的场景。
3.2 股票行情数据获取
行情数据,就是股票每天的开高低收、成交量这些。这是最基础、最常用的数据。
3.2.1 用Tushare获取日线行情
import tushare as ts
# 设置token(需要去官网注册获取)
ts.set_token('你的token')
pro = ts.pro_api()
# 获取平安银行2024年1月日线数据
df = pro.daily(
ts_code='000001.SZ',
start_date='20240101',
end_date='20240131'
)
print(df.head())
这里有个坑:token一定要保管好。我曾经把token直接写在代码里,结果不小心上传到了GitHub……嗯,那天的教训很深刻。
3.2.2 用AkShare获取实时行情
import akshare as ak
# 获取A股实时行情
df = ak.stock_zh_a_spot_em()
# 只看前5只股票
print(df.head())
AkShare的好处是「开箱即用」。不需要注册,不需要token。但坏处是——数据源网站一改版,它就可能挂。我遇到过好几次,早上起来发现策略报错,就是因为AkShare的爬虫失效了。
3.3 财务数据获取
财务数据,说白了就是公司的「体检报告」。营收、利润、资产负债……这些是基本面分析的核心。
3.3.1 Tushare财务数据
# 获取贵州茅台2023年财务数据
df = pro.fina_indicator(
ts_code='600519.SH',
start_date='20230101',
end_date='20231231'
)
# 只看关键指标
print(df[['roe', 'eps', 'bps', 'profit_dedt']].head())
财务数据有个特点:更新慢。季报一般要等一个月才出全。你想想看,如果你用一季度的数据做策略,等数据出来都二季度了……所以做财务因子时,一定要考虑「时滞」。
3.3.2 AkShare财务数据
import akshare as ak
# 获取A股上市公司利润表
df = ak.stock_profit_sheet_by_report_em(
symbol="600519",
date="20231231"
)
print(df.head())
我个人习惯:用Tushare做历史回测,用AkShare做实时监控。Tushare的数据更干净,AkShare的数据更新更快。
3.4 宏观经济数据获取
宏观经济数据,就是「大环境」。GDP、CPI、PMI、利率……这些会影响整个市场的走向。
3.4.1 用AkShare获取宏观经济数据
import akshare as ak
# 获取中国GDP数据
df_gdp = ak.macro_china_gdp()
# 获取CPI数据
df_cpi = ak.macro_china_cpi_monthly()
print(df_gdp.head())
print(df_cpi.head())
宏观经济数据有个特点:频率低。GDP一年才4次,CPI一个月一次。所以做宏观因子时,别指望它能帮你做高频交易。
3.4.2 用Tushare获取宏观数据
# 获取存款准备金率
df = pro.cn_m(
start_date='20230101',
end_date='20231231'
)
print(df.head())
3.5 数据存储与读取
数据拿到了,存哪儿?这是个好问题。
我刚开始做量化时,每次跑策略都重新拉数据。结果发现:90%的时间花在等数据上。后来学乖了——存起来,用的时候直接读。
3.5.1 存成CSV
# 存成CSV
df.to_csv('stock_data.csv', index=False)
# 读取CSV
df = pd.read_csv('stock_data.csv')
CSV是最简单的方式。但有个问题:大文件读写慢。如果你有几百只股票、几年数据,CSV会把你急死。
3.5.2 存成HDF5
# 存成HDF5
df.to_hdf('stock_data.h5', key='daily', mode='w')
# 读取HDF5
df = pd.read_hdf('stock_data.h5', key='daily')
HDF5是我个人最推荐的格式。读写快、压缩率高、支持多表。我自己的数据库就是用HDF5存的,几百万条数据秒级读取。
3.5.3 存到数据库
import sqlite3
# 连接数据库
conn = sqlite3.connect('quant.db')
# 存数据
df.to_sql('stock_daily', conn, if_exists='replace', index=False)
# 读数据
df = pd.read_sql('SELECT * FROM stock_daily WHERE date > "2024-01-01"', conn)
数据库适合做「增量更新」。每天只更新当天的数据,不用全量重写。我建议:小项目用SQLite,大项目用MySQL/PostgreSQL。
3.6 本章知识体系
下面这张图,帮你理清本章的核心逻辑:
3.7 避坑指南
做数据获取这几年,我踩过的坑不少。分享几个给你:
- 数据对齐问题:不同数据源的日期格式可能不一样。Tushare是YYYYMMDD,AkShare可能是YYYY-MM-DD。合并数据前一定要统一格式。
- 复权问题:股票有分红送股,不复权的数据没法用。Tushare有复权接口,AkShare也有。记得用「后复权」做回测。
- 缺失值处理:停牌、节假日都会导致数据缺失。别直接dropna,想想怎么填充更合理。
- 频率问题:日线、周线、月线,不同频率的数据不能混用。我见过有人用日线数据算周线因子……结果可想而知。
好了,数据获取这块就聊到这儿。记住:数据质量决定策略上限。花80%的时间在数据上,都不为过。