第九章 曲面套利策略四:跨品种曲面套利
各位,前面我们聊了同品种的曲面套利,比如用沪深300的当月和次月曲面做文章。今天咱们换个玩法——跨品种曲面套利。说白了,就是利用两个相关资产(比如沪深300和上证50)的波动率曲面之间的相对价值差异来赚钱。
我刚开始做这个策略时,总觉得两个指数走势差不多,曲面应该也差不多。结果一跑回测,发现里面门道还挺深。嗯,今天就把我踩过的坑和总结的经验,一次性讲清楚。
9.1 为什么跨品种曲面存在套利机会?
你想想看,沪深300和上证50,都是大盘蓝筹股的代表。但它们的成分股构成、行业权重、甚至流动性都有差异。这些差异会导致它们的隐含波动率曲面出现定价偏差。
举个例子:
- 上证50更偏金融、银行股
- 沪深300行业分布更均衡
当市场出现某个行业的大事件时,两个曲面的反应速度和幅度会不一样。这种时间差和幅度差,就是我们的利润来源。
9.2 跨品种曲面套利的三种模式
我个人习惯把跨品种曲面套利分成三类,每种都有不同的适用场景:
| 模式 | 操作方式 | 适用场景 |
|---|---|---|
| 曲面水平套利 | 做多一个品种的曲面,做空另一个品种的曲面 | 两个曲面整体水平出现明显偏离 |
| 曲面斜率套利 | 利用两个曲面在期限结构上的斜率差异 | 短期和长期波动率预期不一致 |
| 曲面偏度套利 | 利用两个曲面在虚值/实值区域的偏度差异 | 市场对尾部风险的定价不同 |
我记得有一次,沪深300的曲面整体比上证50高了3个vol点,但历史数据显示正常价差只有1个vol点。这就是典型的曲面水平套利机会。
9.3 实战:构建跨品种曲面价差指标
要做跨品种套利,第一步就是构建一个价差指标。我一般用以下方法:
import numpy as np
import pandas as pd
def calculate_cross_vol_spread(surface_1, surface_2):
"""
计算两个波动率曲面的价差矩阵
surface_1: 品种1的波动率曲面 (DataFrame, index=期限, columns=行权价)
surface_2: 品种2的波动率曲面
"""
# 确保两个曲面的期限和行权价对齐
common_tenors = surface_1.index.intersection(surface_2.index)
common_strikes = surface_1.columns.intersection(surface_2.columns)
# 提取共同部分
s1 = surface_1.loc[common_tenors, common_strikes]
s2 = surface_2.loc[common_tenors, common_strikes]
# 计算价差矩阵
vol_spread = s1.values - s2.values
# 计算整体价差水平(加权平均)
weights = np.ones_like(vol_spread) / vol_spread.size
overall_spread = np.sum(vol_spread * weights)
return vol_spread, overall_spread
# 示例:计算沪深300与上证50的曲面价差
hsi300_surface = get_surface('000300.SH') # 假设已有数据
sz50_surface = get_surface('000016.SH')
spread_matrix, avg_spread = calculate_cross_vol_spread(hsi300_surface, sz50_surface)
print(f"当前曲面平均价差: {avg_spread:.2f} vol点")
9.4 核心流程图:跨品种曲面套利决策逻辑
下面这张图是我自己总结的决策流程,每次做策略前我都会过一遍:
9.5 避坑指南:我踩过的三个大坑
做跨品种曲面套利,有几个坑特别容易踩。我一个个说:
我曾经在沪深300和上证50之间做套利,结果上证50的远月合约流动性极差,滑点吃掉了我大部分利润。后来我学乖了,只选两个品种流动性都好的期限和行权价。
2020年疫情那会儿,沪深300和上证50的相关性从0.95骤降到0.6。两个曲面完全脱钩,价差越拉越大。如果你没设止损,可能亏得很惨。所以,一定要监控相关性,相关性低于0.8时暂停策略。
两个指数的股息率不同,会影响期权定价。特别是分红季,上证50的股息率通常比沪深300高,这会导致上证50的看涨期权更便宜。如果你没考虑这个因素,可能会误判价差。
9.6 实战案例:一次完整的跨品种曲面套利
说个我去年做过的案例吧。2023年8月,我发现沪深300和上证50的曲面价差达到了2.8个vol点,而历史均值只有0.8个vol点,标准差是0.6。这意味着价差偏离了3个标准差以上。
我的操作是这样的:
- 做空沪深300曲面:卖出沪深300的平值跨式期权(ATM straddle)
- 做多上证50曲面:买入上证50的平值跨式期权
- Delta对冲:每天收盘前做一次Delta对冲,保持中性
持有10个交易日后,价差回归到1.2个vol点。我平仓出场,扣除交易成本后净赚了约3.2%的收益。年化下来大概有38%。
9.7 代码实现:完整的跨品种曲面套利策略
下面是我常用的策略框架,你可以直接拿去改:
class CrossAssetVolArbitrage:
def __init__(self, asset1, asset2, lookback=60, z_threshold=2.0):
self.asset1 = asset1
self.asset2 = asset2
self.lookback = lookback
self.z_threshold = z_threshold
self.spread_history = []
def update_surfaces(self, surface1, surface2):
"""更新曲面数据并计算价差"""
spread, _ = calculate_cross_vol_spread(surface1, surface2)
self.spread_history.append(spread)
# 只保留最近lookback天的数据
if len(self.spread_history) > self.lookback:
self.spread_history.pop(0)
def generate_signal(self):
"""生成交易信号"""
if len(self.spread_history) < self.lookback:
return 0 # 数据不足,不交易
current_spread = self.spread_history[-1]
mean_spread = np.mean(self.spread_history)
std_spread = np.std(self.spread_history)
z_score = (current_spread - mean_spread) / std_spread
if z_score > self.z_threshold:
return -1 # 做空价差(做空asset1,做多asset2)
elif z_score < -self.z_threshold:
return 1 # 做多价差(做多asset1,做空asset2)
else:
return 0 # 不交易
# 使用示例
arb = CrossAssetVolArbitrage('000300.SH', '000016.SH')
for day in range(100):
s1 = get_surface_for_day('000300.SH', day)
s2 = get_surface_for_day('000016.SH', day)
arb.update_surfaces(s1, s2)
signal = arb.generate_signal()
if signal != 0:
print(f"第{day}天: 信号={signal}, 执行交易")
嗯,代码看着简单,但实际跑起来要注意的地方不少。比如数据对齐、滑点处理、保证金管理,这些细节都会影响最终收益。
好了,跨品种曲面套利的核心内容就这些。说白了就是找两个相关资产的曲面价差,等它偏离大了就进去,回归了就出来。听起来简单,但要做好,需要你对两个品种的特性有深刻理解。
记住我前面说的三个坑,特别是流动性问题。我刚开始做的时候,就是因为没注意这个,白白亏了不少手续费。