5. 数据获取与处理:用Python搞定期货与现货行情
做基差交易,第一步就是拿数据。没有数据,什么策略都是空中楼阁。
我个人习惯用 tushare 和 akshare 这两个库。它们免费、稳定,而且覆盖了国内期货和现货的主要品种。今天我就带你走一遍完整的流程:从获取数据,到清洗对齐,最后算出基差序列。
5.1 数据源的选择与配置
先说说这两个库的区别。tushare 是老牌选手,数据质量高,但部分接口需要积分。akshare 是后起之秀,接口更丰富,完全免费。我一般这样搭配:
- 期货主力连续合约:用 tushare 的
fut_daily接口 - 现货指数:用 akshare 的
index_daily接口 - 跨期价差:两个库都能拿,看哪个顺手
5.2 获取期货行情数据
拿螺纹钢期货举例。我们需要的不是单个合约,而是 主力连续合约。为什么?因为单个合约会到期,基差序列会断掉。
import tushare as ts
import pandas as pd
# 初始化 tushare
pro = ts.pro_api('你的token')
# 获取螺纹钢主力连续合约日线数据
df_fut = pro.fut_daily(
ts_code='RB9999.XSGE', # 9999 代表主力连续
start_date='20230101',
end_date='20231231',
fields='trade_date, close, settle, volume, open_interest'
)
# 重命名列
df_fut.rename(columns={
'trade_date': 'date',
'close': 'fut_close',
'settle': 'fut_settle'
}, inplace=True)
# 日期排序
df_fut['date'] = pd.to_datetime(df_fut['date'])
df_fut.sort_values('date', inplace=True)
df_fut.reset_index(drop=True, inplace=True)
print(df_fut.head())
嗯,这里要注意:settle 是结算价,close 是收盘价。计算基差时,我建议用 结算价。因为期货的结算价是交易所官方价格,比收盘价更稳定,不容易被尾盘操纵。
5.3 获取现货行情数据
螺纹钢的现货价格,我一般用 上海螺纹钢价格指数。akshare 可以直接拿。
import akshare as ak
# 获取螺纹钢现货价格指数
df_spot = ak.index_daily(
symbol='sh000000', # 上证指数示例,实际用螺纹钢现货指数代码
start_date='20230101',
end_date='20231231'
)
# 重命名列
df_spot.rename(columns={
'date': 'date',
'close': 'spot_price'
}, inplace=True)
df_spot['date'] = pd.to_datetime(df_spot['date'])
print(df_spot.head())
5.4 数据清洗与对齐
数据拿到手,第一件事就是清洗。你想想看,两个数据源的时间戳可能不一样,有的日期期货有数据但现货没有,反过来也一样。
我的标准流程是:
- 去重:检查是否有重复日期
- 填充缺失值:用前向填充法(ffill)处理短期缺失
- 对齐日期:只保留两者都有的交易日
# 合并期货和现货数据
df = pd.merge(df_fut, df_spot, on='date', how='inner')
# 检查缺失值
print(df.isnull().sum())
# 前向填充(最多填充1天)
df.fillna(method='ffill', limit=1, inplace=True)
# 删除仍然缺失的行
df.dropna(inplace=True)
# 重置索引
df.reset_index(drop=True, inplace=True)
print(f"对齐后的数据量:{len(df)} 条")
这里有个坑:前向填充不能滥用。如果连续缺失超过3天,我建议直接删除。因为现货价格在长时间缺失后,用前值填充会严重失真。
5.5 计算基差序列
基差的计算公式很简单:
基差 = 现货价格 - 期货价格
但实际应用中,我习惯同时计算 基差率,方便不同品种之间比较。
# 计算基差
df['basis'] = df['spot_price'] - df['fut_settle']
# 计算基差率(百分比)
df['basis_pct'] = (df['basis'] / df['fut_settle']) * 100
# 查看结果
print(df[['date', 'spot_price', 'fut_settle', 'basis', 'basis_pct']].head())
你看,这样我们就得到了一个完整的基差序列。接下来就可以做统计分析、画图、找套利机会了。
- 基差为正 → 现货溢价(backwardation)
- 基差为负 → 期货溢价(contango)
- 基差绝对值越大 → 套利空间越大
5.6 可视化基差序列
光看数字不够直观。我习惯把基差序列画成图,一眼就能看出趋势和异常点。
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 6))
plt.plot(df['date'], df['basis'], label='基差', color='#2E86AB')
plt.axhline(y=0, color='red', linestyle='--', alpha=0.5)
plt.title('螺纹钢基差序列(2023)')
plt.xlabel('日期')
plt.ylabel('基差(元/吨)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
说实话,画图这一步很重要。我见过很多新手,算完基差就直接上策略,结果忽略了数据中的异常跳变。画个图,一眼就能发现问题。
5.7 本章知识体系
下面这张图,是我自己总结的数据处理流程。你照着做,基本不会出错。
5.8 避坑指南
最后,分享几个我踩过的坑:
- 合约换月:主力连续合约在换月时会有跳空。我一般用 复权处理,或者直接使用指数合约(如 RB8888)。
- 夜盘数据:期货有夜盘,但现货没有。如果你用日线数据,这个问题不大。但如果是日内高频,一定要对齐时间窗口。
- 数据源切换:不要混用不同数据源的同一品种。我试过 tushare 和 akshare 的螺纹钢数据,收盘价差了 5 块钱,基差直接偏了。
好了,数据获取与处理就讲到这里。你按照这个流程走一遍,基差序列就能稳稳地算出来。下一节我们聊聊如何用这个序列去识别套利机会。
公众号:蓝海资料掘金营,微信deep3321