第四节:数据获取——用Tushare和AkShare抓取期货主力合约
做跨品种套利,数据是地基。地基不稳,房子再漂亮也得塌。
我个人习惯,先把数据源搞定再谈策略。今天咱们就聊聊怎么用Tushare和AkShare这两个库,把期货主力合约数据拿到手。
4.1 为什么选主力合约?
期货市场有个特点——每个品种都有好多月份合约同时交易。比如螺纹钢,有RB2101、RB2105、RB2110……你总不能全拿来做套利吧?
主力合约,说白了就是当前成交量最大、持仓量最多的那个合约。它流动性好,滑点小,最能代表这个品种的真实价格。
我在项目中遇到过一个问题:有次用次主力合约做回测,结果策略表现很好,实盘却亏得一塌糊涂。后来一查,原来是次主力流动性太差,滑点把利润全吃掉了。嗯,从那以后我只用主力合约做套利分析。
4.2 Tushare获取主力合约
Tushare是老牌数据源了,数据质量高,但需要注册获取token。我个人习惯用pro版接口,稳定。
先安装:
pip install tushare
然后获取主力合约连续行情:
import tushare as ts
# 设置token(去tushare官网注册获取)
ts.set_token('你的token')
pro = ts.pro_api()
# 获取螺纹钢主力合约日线数据
df = pro.fut_daily(
ts_code='RB.SHF', # 螺纹钢,上海期货交易所
start_date='20230101',
end_date='20231231',
fields='trade_date,open,high,low,close,vol,oi'
)
print(df.head())
Tushare返回的数据里,vol是成交量,oi是持仓量。主力合约的判定标准就是看这两个指标——谁最大谁就是主力。
4.3 AkShare获取主力合约
AkShare是国产开源库,免费且无需注册。我个人觉得它更适合快速原型开发,数据更新也及时。
安装:
pip install akshare
获取主力合约数据:
import akshare as ak
# 获取螺纹钢主力合约行情
df = ak.futures_main_sina(
symbol='RB0', # RB0代表螺纹钢主力连续
start_date='20230101',
end_date='20231231'
)
print(df.head())
AkShare返回的数据包含日期、开盘价、收盘价、最高价、最低价、成交量、持仓量。跟Tushare结构类似,但字段名略有不同。
4.4 两种数据源对比
| 对比项 | Tushare | AkShare |
|---|---|---|
| 注册 | 需要 | 不需要 |
| 费用 | 基础免费,高级付费 | 完全免费 |
| 数据质量 | 高,有校验 | 较高,偶尔有延迟 |
| 接口稳定性 | 稳定 | 偶尔变动 |
| 适合场景 | 生产环境 | 研究/原型开发 |
我个人建议:做研究用AkShare,跑实盘用Tushare。为什么?AkShare免费且方便,但接口偶尔会改,实盘时突然报错就麻烦了。Tushare虽然要token,但稳定多了。
4.5 主力合约切换处理
这里有个坑——主力合约不是一成不变的。比如螺纹钢,可能1月是RB2105是主力,2月就变成RB2110了。两个合约价格有差异,直接拼接会出现跳空。
我曾经吃过这个亏:回测时没处理主力切换,结果策略显示年化收益50%,实盘直接亏了。后来才发现是数据拼接出了问题。
处理方法有两种:
- 向前复权: 把历史数据按当前主力合约调整,消除跳空。Tushare的fut_daily接口默认做了复权处理。
- 向后复权: 把当前数据按历史合约调整。AkShare的futures_main_sina返回的是原始数据,需要自己处理。
我个人习惯用向前复权,因为更直观——你看到的价格就是当前主力合约的实际价格。
4.6 实战:获取多品种主力数据
咱们来写一个完整的例子,同时获取螺纹钢和热卷的主力数据,为后续套利做准备:
import akshare as ak
import pandas as pd
def get_main_contract(symbol, start, end):
"""
获取主力合约连续数据
symbol: 品种代码,如RB0, HC0
"""
df = ak.futures_main_sina(
symbol=symbol,
start_date=start,
end_date=end
)
# 重命名列,统一格式
df.rename(columns={
'日期': 'date',
'开盘价': 'open',
'收盘价': 'close',
'最高价': 'high',
'最低价': 'low',
'成交量': 'volume',
'持仓量': 'open_interest'
}, inplace=True)
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
return df
# 获取螺纹钢和热卷数据
rb = get_main_contract('RB0', '20230101', '20231231')
hc = get_main_contract('HC0', '20230101', '20231231')
# 合并成一个DataFrame
data = pd.DataFrame({
'RB_close': rb['close'],
'HC_close': hc['close'],
'RB_volume': rb['volume'],
'HC_volume': hc['volume']
})
# 计算价差
data['spread'] = data['RB_close'] - data['HC_close']
print(data.head())
这段代码我用了好几年,基本没出过问题。唯一要注意的是,AkShare偶尔会返回空数据,建议加个重试机制。
4.7 本章知识体系
下面这张图帮你理清数据获取的整个流程:
这张图把整个流程串起来了。你从Tushare或AkShare拿到数据,判定主力合约,处理切换问题,最后得到干净的价差数据。每一步都有坑,但踩过一次就记住了。