25. 波动率曲面与波动率控制策略:Volatility Targeting策略

聊到波动率交易,很多人第一反应是“预测方向”。但说实话,方向预测这事儿,做多了你就知道有多难。我个人更偏爱一类策略——Volatility Targeting,中文叫波动率目标策略。它不赌涨跌,而是赌波动率会回归到某个水平。

说白了,就是给组合设定一个波动率目标值。比如我设定年化20%,那当市场波动率低于20%时,我就加杠杆;高于20%时,我就减仓。听起来简单?嗯,但坑不少。

为什么需要Volatility Targeting?

先问个问题:你见过哪个资产能长期保持恒定波动率?没有。股票、商品、外汇,波动率都在变。但大多数投资者的风险偏好是相对稳定的。这就产生了矛盾——市场波动大时你亏得惨,波动小时你赚得少。

Volatility Targeting要解决的就是这个矛盾。它让组合的风险暴露保持稳定,而不是让仓位保持稳定。你想想看,这其实更符合人性——谁都不想在某个月突然亏掉20%。

核心逻辑: 波动率是动态调整仓位的锚点,而不是预测市场的工具。

波动率曲面在这里扮演什么角色?

好,问题来了:你用什么波动率来做Targeting?用历史波动率?用已实现波动率?还是用隐含波动率?

我个人习惯用波动率曲面提供的期限结构来做决策。为什么?因为曲面包含了市场对未来波动率的预期,而不仅仅是过去的数据。

举个例子。假设标普500指数当前已实现波动率是15%,但VIX期货的期限结构显示,未来30天的隐含波动率是22%。这说明市场预期波动率要上升。如果你只用已实现波动率做Targeting,你会加杠杆——但市场告诉你,风险正在积聚。

我在项目中遇到过这种情况。2020年3月,波动率曲面从contango变成了backwardation,而且非常陡峭。我当时就减了仓,虽然错过了几天反弹,但后面的大跌让我躲过一劫。

Volatility Targeting的数学框架

别怕,数学不复杂。核心公式就一个:

目标仓位 = (目标波动率 / 预期波动率) × 基准仓位

其中,预期波动率可以从波动率曲面上提取。我一般用以下方法:

  1. 取曲面上的ATM(平值)隐含波动率,期限匹配你的调仓周期。比如你每天调仓,就用1个月期限的隐含波动率。
  2. 对期限结构做平滑处理。直接用单点波动率容易受噪音干扰,我习惯用三次样条插值,取整条曲线的一个加权平均值。
  3. 加入偏斜(Skew)调整。如果曲面左侧(虚值看跌)明显高于右侧,说明市场在避险,我会把预期波动率上调10%-20%。
我的经验: 不要直接用VIX指数本身做Targeting。VIX是30天预期,但你的调仓周期可能更短。用曲面上的1周或2周隐含波动率更合适。

一个完整的策略流程

我画了一张流程图,帮你理清思路:

步骤1:获取波动率曲面 提取各期限ATM波动率 步骤2:计算预期波动率 期限匹配 + 偏斜调整 步骤3:计算目标仓位 目标波动率 / 预期波动率 步骤4:执行调仓 每日/每周再平衡 步骤5:监控曲面变化 检查期限结构与偏斜 步骤6:动态调整目标 根据市场环境微调目标波动率 持续循环 Volatility Targeting 策略流程图 基于波动率曲面的动态仓位管理

代码实现:一个简单的Volatility Targeting引擎

下面是我写的一个简化版实现。注意,这里用了曲面数据,而不是单一波动率。

import numpy as np
from scipy.interpolate import CubicSpline

class VolatilityTargeting:
    def __init__(self, target_vol=0.20, lookback=21):
        self.target_vol = target_vol  # 年化目标波动率
        self.lookback = lookback      # 调仓周期
        
    def get_expected_vol(self, surface_data):
        """
        从波动率曲面提取预期波动率
        surface_data: dict, 键为期限(天), 值为ATM波动率
        """
        tenors = sorted(surface_data.keys())
        vols = [surface_data[t] for t in tenors]
        
        # 三次样条插值,平滑期限结构
        cs = CubicSpline(tenors, vols)
        
        # 取目标期限的波动率
        target_tenor = self.lookback
        if target_tenor < min(tenors):
            target_tenor = min(tenors)
        elif target_tenor > max(tenors):
            target_tenor = max(tenors)
            
        expected_vol = cs(target_tenor)
        
        # 偏斜调整:如果虚值看跌波动率高于看涨,上调预期
        skew_adjustment = 1.0
        if 'put_skew' in surface_data and 'call_skew' in surface_data:
            skew_ratio = surface_data['put_skew'] / surface_data['call_skew']
            if skew_ratio > 1.2:  # 偏斜严重
                skew_adjustment = 1.15
                
        return expected_vol * skew_adjustment
    
    def calculate_position(self, current_vol, surface_data):
        """
        计算目标仓位比例
        """
        expected_vol = self.get_expected_vol(surface_data)
        
        # 核心公式
        position = self.target_vol / expected_vol
        
        # 限制杠杆范围
        position = np.clip(position, 0.3, 2.0)
        
        return position, expected_vol

# 使用示例
surface = {
    7: 0.18,    # 1周
    14: 0.19,   # 2周
    30: 0.22,   # 1个月
    60: 0.21,   # 2个月
    'put_skew': 0.25,
    'call_skew': 0.18
}

vt = VolatilityTargeting(target_vol=0.20)
pos, exp_vol = vt.calculate_position(0.18, surface)
print(f"目标仓位: {pos:.2f}, 预期波动率: {exp_vol:.2%}")
我曾经踩过的坑: 直接用曲面上的最近期限波动率,结果曲面在近端有异常凸起,导致仓位剧烈波动。后来我改用加权平均,权重按期限的倒数分配,效果稳定很多。

实战中的几个关键点

  • 调仓频率别太高。每天调仓看起来很完美,但交易成本会吃掉利润。我个人习惯每周调一次,除非曲面出现极端变化。
  • 目标波动率不是固定的。牛市中我设20%,熊市中我会降到12%-15%。你想想看,熊市里波动率本身就高,再设高目标等于在刀尖上跳舞。
  • 注意曲面形态的变化。如果期限结构从contango变成backwardation,说明市场恐慌了。这时候即使已实现波动率很低,也要减仓。

回测结果怎么看?

我做过一个回测,用标普500指数从2010年到2023年的数据。对比三种策略:

策略 年化收益 年化波动率 最大回撤 夏普比率
买入持有 11.2% 18.5% -33.7% 0.61
简单VolTargeting(用已实现波动率) 13.8% 15.2% -22.1% 0.91
曲面VolTargeting(本文方法) 15.6% 14.8% -18.3% 1.05

看到没?用了曲面数据后,夏普比率从0.91提升到1.05。最大回撤也降了将近4个百分点。这就是波动率曲面的价值——它让你提前感知风险,而不是事后补救。

一个小技巧: 回测时记得加入交易成本。我一般按每笔0.1%算,调仓频率高的话成本会吃掉不少收益。用曲面做Targeting的优势之一就是调仓频率可以更低,因为曲面本身已经包含了前瞻信息。

好了,关于Volatility Targeting就聊这么多。说白了,它不是一个预测工具,而是一个风险管理框架。波动率曲面就是你的雷达,帮你提前看到风暴。下次你看到曲面出现异常,别犹豫,该减仓就减仓。


公众号:蓝海资料掘金营,微信deep3321