当前位置:首页>python>期货跨期价差到底怎么看?用 Python 判断当前价差是否“偏贵”或“偏便宜”

期货跨期价差到底怎么看?用 Python 判断当前价差是否“偏贵”或“偏便宜”

  • 2026-09-12 18:48:08
期货跨期价差到底怎么看?用 Python 判断当前价差是否“偏贵”或“偏便宜”

一. 前言

书接上文,

https://mp.weixin.qq.com/s/udYseLr-t_etz8AZqkzErg

Python金融笔记,公众号:Python金融笔记拒绝盲目猜测:用 Python 回测 5 年数据,揭秘螺纹钢跨期套利的“黄金区间
上一篇大概写了一些关于螺纹钢的跨期套利的一些内容,只是写了一个大概,这一篇,我拿甲醇来举例子,看看看价差怎么看,怎么算是高,怎么算是低,我们又该怎么做,这篇给写的清楚一点

二.价差看的是什么?

通常所说的价差高,价差低,到底是什么意思,在跨期套利里面,价差指
近月合约的价格 - 远月合约的价格
价差为正数就意味着近月合约的价格>远月合约的价格,反之则是近月合约的价格<远月合约的价格,通常来说,近月合约的价格会低于远月合约的价格,他们天然会有一点价差,主要产生的原因是仓储费。价差只是一个数字,比如螺纹钢01合约现价3000,05合约现价3050,价差为50,我们是看不出来价差是高还是低的,需要把这个数字放到长历史周期里面去看,才会知道是高还是低。

三.先计算价差

在之前的文章里面例子是螺纹钢,现在用甲醇为例子来做,流程还是和上面一篇是一样的,我这里就直接放图了。
这里就有引出了一个问题了,如果把甲醇的01,05,09合约放到一张图里面,如果价差假如是0,这个价差在01-05的跨期中是偏小的,在09-第二年的01合约却是偏大的,所以,对于甲醇季节性比较强的品种,不能直接把所有的配对的价差放到一起来比较价差的高低,所以我是把01-05,05-09,01-09的同一个配对的合约放到一起来比较的,图如下
看起来也比较正常了,也是比较合适的用来比较价差了。

四.判断方法

现在的主力合约是09合约,这里就拿09-01来举例子,怎么去判断,第一个判断方法是历史分位数,意思就是,现在的价差的位置处在多少百分位,如7.6日的价差值为-16
如上面的折线图,7.6日的价差在最近的2609-2701的价差是属于偏小的,但是放到大历史里面,确是属于偏高的。这里需要注意,这种划分只是统计上的参考,不是固定的交易标准。不同品种、不同合约组合,其价差波动特征并不相同。
方法二是通过z-score衡量偏离程度,历史分位数告诉我们当前价差排在什么位置,但不能直接告诉我们当前价差距离均值有多远。公式如下
Z-score =(当前价差 - 历史均值)÷ 历史标准差
Z-score等于0:当前价差接近历史均值;Z-score大于0:当前价差高于历史均值;Z-score小于0:当前价差低于历史均值;Z-score绝对值越大,说明偏离越明显。
这里我直接贴代码,计算一下当前价差值的Z-score
mean_09_01 = long_df_09_01['spread_value'].mean()std_09_01 = long_df_09_01['spread_value'].std()long_df_09_01['zscore'] = (    long_df_09_01['spread_value'] - mean_09_01) / std_09_01courrent = long_df_09_01.iloc[-1]['zscore']print(f"历史均值:{mean_09_01:.2f}")print(f"历史标准差:{std_09_01:.2f}")print(f"当前Z-score:{courrent:.2f}")
历史均值:-51.36历史标准差:68.25当前Z-score:0.52,表示当前价差比历史均值高出大约0.5个标准差,属于相对正常的位置。
但是,价差是一成不变的吗?
答案通常是否定的。商品期货价差会受到库存、需求、交割、季节性和市场结构的影响,几年前的均值不一定适合直接衡量现在。因此,与其使用全部历史数据计算一个固定均值,更常见的方法是使用滚动窗口。
计算滚动zscorelong_df_09_01['roll_mean'] = long_df_09_01['spread_value'].rolling(window=30).mean()long_df_09_01['roll_std'] = long_df_09_01['spread_value'].rolling(window=30).std()long_df_09_01['roll_zscore'] = (    long_df_09_01['spread_value'] - long_df_09_01['roll_mean']) / long_df_09_01['roll_std']courrent = long_df_09_01.iloc[-1]['roll_zscore']fig, ax = plt.subplots(figsize=(14, 7))ax.plot(long_df_09_01['date_text'], long_df_09_01['roll_zscore'], label='滚动Z-score')ax.axhline(0, color='black', linestyle='--', linewidth=1)N = 50for i, label inenumerate(ax.get_xticklabels()):    label.set_visible(i % N == 0)# 标出最新值ax.scatter(long_df_09_01['date_text'].iloc[-1], long_df_09_01['roll_zscore'].iloc[-1], color='red', zorder=5, label=f'最新值={courrent:.2f}')ax.legend()plt.tight_layout()plt.show()
从滚动 Z-score 图可以看到,09-01 价差的最新滚动 Z-score 为-1.69。这说明当前价差已经低于近期滚动均值,并且偏离程度接近 2 个标准差。按照统计角度理解,当前价差已经进入短期偏低区域,但还没有达到极端偏离的程度。这个时候眼尖的同学就会问了, 之前计算历史分位数来说,他不是在历史高位吗,这个z-score却表示他是历史低位,这个不是矛盾吗,这里需要注意,z-socre衡量的是现在的值对最近的均值的偏离程度,而历史分位数来看是现在的价差处于什么位置,所以会存在不同结论,7.6日价差的滚动 Z-score 为-1.69,说明它相对于近期均值偏低;但历史分位数为85.19%,说明它相对于长期历史样本仍然偏高。这说明当前 09-01 价差并不是处在长期历史低位,而是从近期较高水平快速回落,已经跌到了短期均值下方。所以结论是,长期看仍偏高,短期看已经偏弱。直接看这俩是不可以直接开仓做多或者做空价差的,需要这两个相互印证,以这个例子来说,如果滚动z-score是在1.5左右,这个时候就可以去做空价差,空近月,多远月,(注意还需要观察基本面的信息,有没有战争什么因素的产生。)

五、总结

判断跨期价差是否偏贵或者偏便宜,不能只看当前价差是正数还是负数,也不能只看它比昨天上涨还是下跌。更合理的分析流程是:
计算价差
↓
观察历史走势
↓
计算历史分位数
↓
计算滚动Z-score
↓
与往年同期进行比较
↓
检查基本面和合约流动性
↓
判断是否值得进一步研究
这篇主要解决的是:当前的价差是存在什么位置。
但它还没有解决另一个更重要的问题:
价差偏离之后,是否真的会回归?需要多长时间回归?按照什么标准开仓和平仓?
所以这个问题,下一篇再来。
最后,投资有风险,入市须谨慎,仅为知识分享,不构成投资建议。

最新文章

随机文章