第十七章:曲面在风险管理中的应用:希腊字母计算、VaR分析
波动率曲面这东西,平时我们用它来定价、找套利机会。但说实话,它最值钱的地方,是在风险管理里。
我见过太多交易员,曲面画得漂亮,希腊字母算得飞快,结果市场一波动,亏得莫名其妙。为什么?因为曲面本身是动态的,你只盯着一个点看,风险根本藏不住。
这一章,我们就来聊聊怎么用曲面做风险管理。核心就两件事:希腊字母的曲面化计算,和基于曲面的VaR分析。
17.1 曲面上的希腊字母:不再是单个点
传统教科书里,希腊字母都是针对单个期权的。比如Delta、Gamma、Vega,都是给定行权价和到期日算一个数。
但在曲面框架下,我们关心的是整个曲面的风险暴露。说白了,就是当市场参数变化时,你的整个期权组合会怎么动。
17.1.1 曲面Delta:不只是标的价格
普通Delta衡量标的价格变动对期权价格的影响。但曲面Delta要考虑更多——标的价格变了,隐含波动率也会跟着变(这就是所谓的“粘性行权价”或“粘性Delta”效应)。
我个人习惯把曲面Delta拆成两部分:
- 直接Delta:标的价格变动,隐含波动率不变时的Delta
- 间接Delta:标的价格变动导致隐含波动率变化,进而影响期权价格
实际计算时,我一般用有限差分法。代码大概长这样:
def surface_delta(option_price_func, S, K, T, r, surface, eps=1e-4):
# 直接Delta
price_up = option_price_func(S*(1+eps), K, T, r, surface)
price_down = option_price_func(S*(1-eps), K, T, r, surface)
direct_delta = (price_up - price_down) / (2 * S * eps)
# 间接Delta:考虑波动率变化
vol_up = surface.get_vol(S*(1+eps), K, T)
vol_down = surface.get_vol(S*(1-eps), K, T)
vega = surface_vega(option_price_func, S, K, T, r, surface)
indirect_delta = vega * (vol_up - vol_down) / (2 * S * eps)
return direct_delta + indirect_delta
嗯,这里要注意:间接Delta有时候比直接Delta还大。我在做美股指数期权时遇到过,标的一跌,恐慌情绪上来,波动率飙升,间接Delta直接把组合打爆了。
17.1.2 曲面Vega:别只盯着一个期限
普通Vega只算一个到期日的波动率变化。但曲面Vega要算整个波动率期限结构的变化。
我建议的做法是:把曲面Vega拆成平行移动Vega和斜率变化Vega。
| Vega类型 | 含义 | 计算方式 |
|---|---|---|
| 平行移动Vega | 整个曲面上下平移1% | 所有期限波动率+1%,重新定价 |
| 斜率变化Vega | 短期vs长期波动率差变化 | 短期+1%,长期-1%,重新定价 |
| 曲度变化Vega | 中期波动率相对变化 | 中期+1%,两端-0.5%,重新定价 |
这样做的好处是,你能知道组合到底怕什么。是怕整体波动率上升?还是怕期限结构变陡?
17.2 基于曲面的VaR分析
VaR(Value at Risk)是风险管理的老祖宗了。但传统VaR有个大问题——它假设波动率是常数。
你想想看,市场恐慌时波动率会飙升,尾部风险比正态分布预测的大得多。用曲面来做VaR,就是要把波动率的随机性和曲面形态的变化都考虑进去。
17.2.1 历史模拟法 + 曲面重构
我个人最喜欢的方法,是历史模拟法加上曲面重构。步骤很简单:
- 取过去N天的历史数据(标的价格、曲面参数)
- 对每一天,用当天的曲面参数重新定价整个组合
- 计算每天的损益序列
- 取第5百分位数(95% VaR)或第1百分位数(99% VaR)
代码实现大概这样:
def surface_var(portfolio, historical_data, confidence=0.95):
pnl_list = []
for day_data in historical_data:
# 用当天的曲面重新定价
S_t = day_data['spot']
surface_t = day_data['surface']
portfolio_value = portfolio.price(S_t, surface_t)
pnl = portfolio_value - portfolio.initial_value
pnl_list.append(pnl)
pnl_list.sort()
var_index = int(len(pnl_list) * (1 - confidence))
return -pnl_list[var_index]
这里有个坑:历史数据要足够长,至少500个交易日以上。我见过有人用100天数据算VaR,结果样本太少,VaR值忽高忽低,根本没法用。
17.2.2 蒙特卡洛模拟 + 曲面动态
如果你想要更精确的VaR,那就得上蒙特卡洛模拟。核心是模拟标的价格和曲面参数的联合随机过程。
我一般用两步走:
- 第一步:模拟标的价格路径(用Heston模型或SABR模型)
- 第二步:根据标的价格路径,更新曲面参数(用粘性Delta假设或粘性行权价假设)
代码框架:
def monte_carlo_var(portfolio, S0, surface0, n_sim=10000, horizon=1):
pnl_list = []
for i in range(n_sim):
# 模拟标的价格
S_T = simulate_spot(S0, surface0, horizon)
# 更新曲面
surface_T = update_surface(surface0, S_T, S0)
# 重新定价
portfolio_value = portfolio.price(S_T, surface_T)
pnl = portfolio_value - portfolio.initial_value
pnl_list.append(pnl)
pnl_list.sort()
var_95 = -pnl_list[int(n_sim * 0.05)]
var_99 = -pnl_list[int(n_sim * 0.01)]
return var_95, var_99
这里要注意:模拟次数不能太少。我一般至少跑1万次,关键组合跑10万次。不然VaR的置信区间太宽,没有实际意义。
17.3 曲面风险管理的核心框架
说了这么多,我画个图帮你理清思路。这是我自己做风险管理时的核心框架:
这个框架我用了好几年,核心思想就是:曲面不是静态的,风险管理必须动态化。
17.4 实战中的几个坑
最后,分享几个我在实战中踩过的坑,希望能帮你少走弯路。
坑一:曲面参数太多,过拟合
我曾经用SVI模型拟合曲面,用了5个参数。结果VaR算出来特别不稳定,今天5%,明天3%。后来发现是参数太多,历史数据不够,过拟合了。建议:参数越少越好,3-4个参数足够。
坑二:忽略周末效应
VaR计算时,很多人直接用日历天数。但周末没有交易,波动率会累积。我习惯用交易天数算VaR,周末单独处理。不然周五算的VaR,周一开盘可能直接被打穿。
坑三:曲面外推太激进
深度虚值期权和超长期限的曲面数据很少,外推时很容易出错。我建议:对于外推区域,给一个保守的波动率上限。比如深度虚值期权的波动率,不超过平值期权的2倍。
好了,这一章的内容就到这里。曲面风险管理是个大话题,但核心就是两件事:算对希腊字母,算准VaR。把这两件事做好,你的风险管理水平已经超过90%的交易员了。
公众号:蓝海资料掘金营,微信deep3321