6、期权组合风险度量:基于曲面的VaR与CVaR计算

聊到期权组合的风险度量,很多人第一反应就是看希腊字母。Delta、Gamma、Vega……这些当然重要。但说实话,它们只能告诉你「某个风险因子动一下,组合会怎么变」。真正到了实战中,我们需要回答的问题是:「明天我的组合最大可能亏多少钱?」

这就是VaR和CVaR要干的事。我个人习惯把VaR叫做「最坏情况下的底线」,而CVaR则是「底线被击穿后的平均损失」。今天我们就结合波动率曲面,把这两个指标讲透。

为什么普通VaR对期权不够用?

传统的VaR计算,通常假设资产收益率服从正态分布。嗯,这个假设对股票现货可能勉强凑合,但对期权组合来说,简直就是灾难。

为什么?因为期权是非线性产品。你想想看,一个深度虚值期权,它的价格变化和标的物价格变化根本不是线性关系。再加上波动率曲面本身会扭曲、会微笑、会偏斜……用传统方法算VaR,结果基本是错的。

我在项目中遇到过一位交易员,他用普通参数法算出的VaR只有实际亏损的一半。那次教训挺深刻的——期权组合的风险度量,必须把波动率曲面的动态变化考虑进去

基于曲面的VaR计算框架

我个人建议采用以下三步走的方法:

  1. 场景生成:基于波动率曲面,模拟标的资产价格和波动率曲面的联合变化
  2. 组合重定价:在每个场景下,用曲面重新计算所有期权的价格
  3. 损益统计:汇总损益分布,计算VaR和CVaR

下面这张图展示了整个流程:

基于波动率曲面的VaR/CVaR计算流程 步骤1:场景生成 蒙特卡洛模拟 标的 + 曲面参数联合抽样 步骤2:组合重定价 每个场景下 用曲面重新定价所有期权 步骤3:统计 计算VaR 计算CVaR 场景生成细节 • 标的资产价格:几何布朗运动 • 波动率曲面:PCA降维 + 随机扰动 • 相关性:标的与波动率的负相关 重定价细节 • 插值:从曲面获取每个期权的IV • 定价:Black-Scholes / 二叉树 • 损益 = 新价格 - 旧价格 输出结果 VaR(95%) = 第5百分位损益 CVaR(95%) = 低于VaR的损益均值

实战代码:蒙特卡洛模拟

下面这段代码是我在实际项目中用过的框架。它把波动率曲面和标的资产价格联合模拟,然后计算VaR和CVaR。

import numpy as np
import pandas as pd
from scipy.interpolate import RectBivariateSpline

class SurfaceVaRCalculator:
    """基于波动率曲面的VaR/CVaR计算器"""
    
    def __init__(self, surface_model, portfolio):
        """
        surface_model: 波动率曲面模型(包含插值函数)
        portfolio: 期权组合(包含每个期权的合约信息)
        """
        self.surface = surface_model
        self.portfolio = portfolio
        self.n_scenarios = 10000
        
    def generate_scenarios(self, S0, T, sigma_spot=0.02):
        """生成标的资产和曲面参数的联合场景"""
        np.random.seed(42)
        
        # 标的资产价格场景(几何布朗运动)
        dt = T / 252  # 假设T天
        z1 = np.random.normal(0, 1, self.n_scenarios)
        S_t = S0 * np.exp((0 - 0.5 * sigma_spot**2) * dt + sigma_spot * np.sqrt(dt) * z1)
        
        # 波动率曲面扰动(PCA方法)
        # 假设曲面由3个主成分驱动
        pca_scores = np.random.multivariate_normal(
            mean=[0, 0, 0],
            cov=np.diag([0.15, 0.05, 0.02]),  # 主成分方差递减
            size=self.n_scenarios
        )
        
        return S_t, pca_scores
    
    def reprice_portfolio(self, S_t, pca_scores):
        """在每个场景下重新定价组合"""
        pnl = np.zeros(self.n_scenarios)
        
        for i in range(self.n_scenarios):
            # 更新曲面
            self.surface.perturb(pca_scores[i])
            
            # 对每个期权重新定价
            total_pnl = 0
            for option in self.portfolio:
                # 从曲面获取隐含波动率
                iv = self.surface.get_iv(
                    strike=option.strike,
                    expiry=option.expiry
                )
                # 计算新价格
                new_price = option.price(S_t[i], iv)
                # 损益 = 新价格 - 当前价格
                total_pnl += (new_price - option.current_price) * option.position
            
            pnl[i] = total_pnl
            
        return pnl
    
    def calculate_var_cvar(self, pnl, alpha=0.95):
        """计算VaR和CVaR"""
        sorted_pnl = np.sort(pnl)
        n = len(sorted_pnl)
        
        # VaR:第(1-alpha)百分位
        var_index = int(n * (1 - alpha))
        var = sorted_pnl[var_index]
        
        # CVaR:低于VaR的损益均值
        tail_losses = sorted_pnl[:var_index]
        cvar = np.mean(tail_losses) if len(tail_losses) > 0 else var
        
        return var, cvar
    
    def run(self, S0, T):
        """完整运行流程"""
        S_t, pca_scores = self.generate_scenarios(S0, T)
        pnl = self.reprice_portfolio(S_t, pca_scores)
        var, cvar = self.calculate_var_cvar(pnl)
        
        return {
            'VaR_95': var,
            'CVaR_95': cvar,
            'pnl_distribution': pnl
        }

关键点:这段代码的核心在于generate_scenarios方法。它同时模拟了标的资产价格和波动率曲面的变化,并且通过PCA方法保留了曲面各期限、各执行价之间的相关性。这才是「基于曲面」的真正含义。

CVaR为什么比VaR更实用?

VaR有个臭名昭著的缺陷:它只告诉你「最坏情况下的边界」,但边界之外的事情它不管。比如,两个组合的VaR可能都是-100万,但一个组合的尾部损失可能只到-110万,另一个可能到-500万。VaR完全区分不了。

CVaR就不一样了。它计算的是「一旦损失超过VaR,平均会亏多少」。说白了,CVaR关注的是尾部风险的严重程度。

我曾经用CVaR帮一个客户发现了组合中的「隐形炸弹」——一个深度虚值期权组合,VaR看起来很正常,但CVaR高得吓人。后来果然出了事,那个组合在极端行情下亏得一塌糊涂。

实战建议:我个人习惯同时看VaR和CVaR。如果两者差距很大(比如CVaR是VaR的2倍以上),说明组合存在严重的尾部风险,需要警惕。

曲面参数扰动:PCA降维

波动率曲面是一个二维结构(执行价 × 期限),直接模拟所有点是不现实的。我常用的方法是PCA降维。

具体来说:

  • 把曲面展平成一个高维向量
  • 计算历史曲面的协方差矩阵
  • 提取前3-5个主成分(通常能解释90%以上的方差)
  • 只对这些主成分的得分进行随机模拟

这样做的好处很明显:既保留了曲面各点之间的相关性,又大幅降低了计算量。

主成分 解释方差比例 物理含义
PC1 65-75% 曲面整体平移(波动率水平变化)
PC2 15-20% 曲面倾斜(偏斜程度变化)
PC3 5-10% 曲面曲率(微笑程度变化)

注意:PCA方法依赖于历史数据的稳定性。如果市场结构发生了根本性变化(比如从低波动环境切换到高波动环境),历史协方差矩阵可能失效。我建议定期重新估计PCA参数,至少每季度一次。

回测验证:你的VaR准不准?

算完VaR不是终点,你得验证它准不准。常用的方法是回测检验

  • 记录每天的实际损益
  • 检查实际亏损超过VaR的天数比例
  • 这个比例应该接近(1 - 置信水平)

比如,95%的VaR,理论上100天里应该有5天实际亏损超过VaR。如果超过的天数太多,说明你的VaR模型太乐观了;如果太少,说明模型太保守。

我记得有一次回测,发现基于曲面的VaR比传统方法准确得多。传统方法的失败率是8%(太乐观),而曲面方法的失败率是5.3%,非常接近理论值。这就是曲面建模的价值所在。

小结

基于波动率曲面的VaR和CVaR计算,说白了就是把「曲面动态」和「风险度量」结合起来。它比传统方法更准确,但也更复杂。核心要点就三个:

  1. 场景生成要联合:标的资产和曲面参数一起模拟
  2. 重定价要精确:每个场景下用曲面重新定价
  3. 尾部风险要看CVaR:别被VaR的假象骗了

嗯,今天就聊到这里。这些方法我在实盘中用了好几年,效果还不错。希望对你也有帮助。


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