4. 基差计算与可视化:计算主力合约基差,绘制基差时序图与分布直方图

好,咱们进入第四步。这一步说白了,就是把基差从「理论概念」变成「能看见、能分析的数据」。我个人觉得,这是整个套利模型里最直观、也最容易出成就感的一环。

你想想看,基差就是现货价格减去期货价格。但实际算起来,坑不少。我刚开始做的时候,就吃过「合约换月」的亏——主力合约一换,基差直接跳空,我还以为是行情异动,差点下了错单。

核心逻辑:基差 = 现货价格 - 期货价格。正值叫「升水」,负值叫「贴水」。我们做套利,盯的就是这个值的波动。

4.1 数据准备:你需要什么?

要算基差,你得有两样东西:

  • 现货价格序列:比如沪深300指数、螺纹钢现货价、比特币现货价。注意,要选同一标的。
  • 期货主力合约价格序列:这里有个关键点——「主力合约」不是固定的。每个月或每季度,持仓量和成交量最大的合约会变。

我在项目中遇到过最头疼的事,就是主力合约切换时,数据源没同步更新。结果基差图里出现了一个巨大的尖峰,我还以为是套利机会,差点冲进去。后来我养成了一个习惯:每次跑模型前,先手动确认一下当前主力合约是哪个月份

4.2 基差计算:代码实现

好,咱们直接上代码。这里我用的是Python,pandas处理数据,matplotlib画图。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 假设你已经有了两个DataFrame
# spot_df: 包含 'date' 和 'price' 列
# futures_df: 包含 'date', 'contract', 'price' 列

# 第一步:筛选主力合约
# 我习惯用持仓量来判定,但如果没有持仓量数据,也可以用成交量
# 这里简化处理:假设我们已经有主力合约的标识
main_contract = futures_df[futures_df['is_main'] == True]

# 第二步:合并数据
merged = pd.merge(spot_df, main_contract, on='date', how='inner', suffixes=('_spot', '_futures'))

# 第三步:计算基差
merged['basis'] = merged['price_spot'] - merged['price_futures']

# 看看结果
print(merged[['date', 'price_spot', 'price_futures', 'basis']].head())

避坑指南:我曾经直接用「成交量最大」来判定主力合约,结果遇到股指期货交割周,成交量异常放大,选错了合约。后来我改用「持仓量+成交量」加权判断,准确率高很多。

4.3 基差时序图:看趋势

时序图能告诉你基差在时间轴上是如何变化的。我一般会叠加现货和期货的价格线,这样能直观看到基差是怎么形成的。

fig, axes = plt.subplots(2, 1, figsize=(14, 10))

# 上图:现货 vs 期货价格
axes[0].plot(merged['date'], merged['price_spot'], label='现货', color='#2E86AB')
axes[0].plot(merged['date'], merged['price_futures'], label='期货主力', color='#A23B72')
axes[0].set_ylabel('价格')
axes[0].legend()
axes[0].set_title('现货 vs 期货主力价格')

# 下图:基差
axes[1].plot(merged['date'], merged['basis'], color='#F18F01', linewidth=1.5)
axes[1].axhline(y=0, color='gray', linestyle='--', alpha=0.7)
axes[1].set_ylabel('基差')
axes[1].set_title('基差时序图')

plt.tight_layout()
plt.show()

嗯,这里要注意:如果基差长期在0轴上方,说明市场处于升水状态;反之则是贴水。我见过最极端的案例是2020年原油期货,基差一度跌到-40美元,那真是活久见。

4.4 分布直方图:看统计特征

时序图看趋势,直方图看分布。它能告诉你基差通常落在什么区间,有没有极端值。

fig, ax = plt.subplots(figsize=(10, 6))

# 绘制直方图
sns.histplot(merged['basis'], bins=50, kde=True, color='#2E86AB', ax=ax)
ax.axvline(x=merged['basis'].mean(), color='red', linestyle='--', label=f'均值: {merged["basis"].mean():.2f}')
ax.axvline(x=merged['basis'].median(), color='green', linestyle='--', label=f'中位数: {merged["basis"].median():.2f}')
ax.set_xlabel('基差')
ax.set_ylabel('频次')
ax.set_title('基差分布直方图')
ax.legend()

plt.show()

关键统计量

指标 含义 套利意义
均值 基差的平均水平 判断当前基差是否偏离常态
标准差 基差的波动程度 决定套利开仓的阈值
偏度 分布是否对称 正偏态说明贴水机会更多
峰度 极端值出现的概率 高峰度意味着需要更严格的风控

我一般会结合这两个图来做决策:如果基差偏离均值超过2个标准差,而且分布直方图显示这个位置属于极端值区域,那就是一个潜在的套利机会。

4.5 本章知识体系

下面这张图,是我自己总结的基差计算与可视化的完整流程。你照着这个走,基本不会漏掉关键步骤。

基差计算与可视化流程 数据输入 主力合约筛选 基差计算 时序图 分布直方图 统计特征分析 套利决策 数据清洗 → 主力合约判定 → 基差计算 → 可视化分析 → 策略决策

重要提醒:基差计算看似简单,但数据频率一定要对齐。我见过有人用日频的现货数据,配了分钟频的期货数据,算出来的基差完全没法用。记住:时间戳必须精确匹配

好了,基差计算和可视化这部分就讲到这里。你拿到数据后,先画时序图看看整体趋势,再画直方图看看分布特征。这两个图配合起来,基本能帮你判断当前市场处于什么状态。

我个人习惯是把这两个图做成自动化报表,每天开盘前跑一遍。这样心里有底,知道基差是处于正常波动范围,还是出现了极端机会。

专注资料整理