本文主要是介绍Delta对冲:一般形式及模拟实验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 期权Delta对冲
- 1. 对冲收益的一般形式
- 使用实际波动率进行对冲
- 使用隐含波动率进行对冲
- 收益波动与波动率选择
- 2. 对冲收益跟对冲波动率的关系
- 3. 代码实现
期权Delta对冲
参考文献:Ahmad, R., & Wilmott, P. (2005). Which free lunch would you like today, sir?: Delta hedging, volatility arbitrage and optimal portfolios. Wilmott, 64-79.
1. 对冲收益的一般形式
假定买入认购期权,标的资产价格为S,剩余到期时间为t,调整标的资产仓位进行对冲至到期,隐含波动率为 σ ~ \tilde{\sigma} σ~,实际波动率为 σ ~ \tilde{\sigma} σ~,用于对冲的波动率为 σ h \sigma_h σh。
V ( S , t ; σ h ) − V ( S , t ; σ ~ ) + 1 2 ( σ 2 − σ h 2 ) ∫ t 0 T e − r ( t − t 0 ) S 2 Γ h d t (1) V(S,t;\sigma_h)-V(S,t;\tilde{\sigma}) + \frac{1}{2}(\sigma^2 - \sigma^2_h) \int_{t_0}^{T} e^{-r(t-t_0)S^2} \Gamma^hdt \tag{1} V(S,t;σh)−V(S,t;σ~)+21(σ2−σh2)∫t0Te−r(t−t0)S2Γhdt(1)
每次对冲的收益为:
1 2 ( σ 2 − σ ~ 2 ) S 2 Γ i d t + ( Δ i − Δ h ) ( ( μ − r + D ) S d t + σ S d z ) (2) \frac{1}{2}(\sigma^2 - \tilde{\sigma}^2) S^2 \Gamma^i dt +(\Delta^i - \Delta^h)((\mu - r +D)Sdt +\sigma Sdz) \tag{2} 21(σ2−σ~2)S2Γidt+(Δi−Δh)((μ−r+D)Sdt+σSdz)(2)
标的资产价格服从几何布朗运动 d S = μ S d t + σ S d z dS = \mu Sdt + \sigma S dz dS=μSdt+σSdz,dz是维纳过程, μ \mu μ是标的资产期望收益率, σ \sigma σ是收益率的年化标准差。
其中, Γ i \Gamma^i Γi是基于隐含波动率计算出的期权Gamma值, Δ i , D e l t a h \Delta^i,Delta^h Δi,Deltah分别是基于隐含波动率和实际波动率计算出的期权的delta值。D是股票的分红(连续分红),r是无风险利率。
使用实际波动率进行对冲
上式可以简化为:
V ( S , t ; σ h ) − V ( S , t ; σ ~ ) (3) _ V(S,t;\sigma_h)-V(S,t;\tilde{\sigma}) \tag{3} V(S,t;σh)−V(S,t;σ~)(3)
使用隐含波动率进行对冲
上式可以简化为:
1 2 ( σ 2 − σ h 2 ) ∫ t 0 T e − r ( t − t 0 ) S 2 Γ h d t (4) \frac{1}{2} (\sigma^2 - \sigma^2_h) \int_{t_0}^{T} e^{-r(t-t_0)S^2} \Gamma^hdt \tag{4} 21(σ2−σh2)∫t0Te−r(t−t0)S2Γhdt(4)
收益波动与波动率选择
如果说期权是根据模型定价的(Mark to Model),而不是根据市场定价的(Mark to Market),那么自然应该选择使用实际波动率进行对冲。换句话说,就是定价的波动率其实是实际波动率,可参见2.1节的 σ = σ ~ \sigma = \tilde{\sigma} σ=σ~的对冲收益情景,这种情况下使用实际波动率进行对冲,最终的收益波动为0,且收益与最优期望收益相差较小。
如果期权是根据市场定价的,通常处于风险管理的需要,将基于期权市场价值汇报每天的损益(Profit and Loss),为了避免每天收益的波动率,在这种情况下通常会选择隐含波动率进行对冲。为什么要关心每天的PnL呢?因为如果标准差越大,风险越大,在某一天收益出现较大亏损的可能性就越大,被强行平仓的可能性就会越大,交易员或者投资者需要尽力避免这种极端情况的发生。
如公式(2)所示,每次收益的波动率是由 σ S ∣ Δ i − Δ h ∣ d z \sigma S |\Delta^i - \Delta^h|dz σS∣Δi−Δh∣dz项引起的,(2)式的标准差可以写为
σ S ∣ Δ i − Δ h ∣ d t (5) \sigma S |\Delta^i - \Delta^h|\sqrt{dt} \tag{5} σS∣Δi−Δh∣dt(5)
可以看出,每次对冲收益的标准差(风险)与隐含波动率,实际波动率和对冲波动率都有关,如果对冲的波动率越接近实际波动率,风险就会越小。
对于一个认购欧式期权,还有六个月到期,隐含波动率为20%,对冲波动率为30%,分别计算出的相应Delta值,其与标的资产价格的关系如如上图所示。当价格处于深虚值或者深实值(far in or out of money),两种波动率计算出的Delta值差距不大,而当价格越靠近平值(越靠近行权价时),Delta值的差距较为明显,局部的收益风险较大。
两条曲线相交于:
S = K e x p ( − T − t σ ~ − σ h ( σ ~ ( r − D + σ h 2 / 2 ) − σ h ( r − D + σ 2 / 2 ) ) S = K exp(-\frac{T-t}{\tilde{\sigma}-\sigma^h}(\tilde{\sigma}(r-D+\sigma^{h^2}/2)-\sigma^h(r-D+\sigma^2/2)) S=Kexp(−σ~−σhT−t(σ~(r−D+σh2/2)−σh(r−D+σ2/2))
2. 对冲收益跟对冲波动率的关系
假定买入欧式认购期权,一年到期,行权价 k k k为100,标的资产价格为 100 100 100,无风险利率 r r r=10%,分红D=0, μ \mu μ标的资产的价格期望收益为0。对于每种情况模拟了100次,并求收益的期望值、最大值、最小值和标准差。
2.1 实际波动率= 隐含波动率( σ = σ ~ = 20 % \sigma = \tilde{\sigma} = 20\% σ=σ~=20%)
当实际波动率等于隐含波动率时,无论采用哪个波动率来进行对冲,其期望的收益相对于期权的市场价格(13.3)来说都是比较小的。但是当使用实际波动率0.2进行对冲的时候,收益的标准差最小。最高收益曲线比最低收益曲线更加陡峭。所有的曲线相交于同一点(0.2,0)。
2.2 实际波动率>隐含波动率( σ = 40 % , σ ~ = 20 % \sigma =40\%, \tilde{\sigma} = 20\% σ=40%,σ~=20%)
当实际波动率大于隐含波动率的时候,如果对冲的波动率小于隐含波动率,或高于了0.75左右,很有可能会发生亏损(最低收益低于了0);如果对冲的波动率介于0.2到0.75左右,反而不会亏损。同时可以看出,期望收益对于对冲的波动率是不敏感的。
2.3 实际波动率<隐含波动率( σ = 20 % , σ ~ = 40 % \sigma =20\%, \tilde{\sigma} = 40\% σ=20%,σ~=40%)
当实际波动率小于隐含波动率的时候,如果对冲的波动率小于0.1左右,或高于隐含波动率,很有可能会发生亏损(最低收益低于了0);如果对冲的波动率介于0.1到0.4左右,反而不会亏损。同时可以看出,期望收益对于对冲的波动率是不敏感的。而最低收益曲线比最高收益曲线更加陡峭。
3. 代码实现
主要包括了PriceSimulator和OptionHedge两个类,前者是用来模拟期权的价格路径(基于隐含波动率)和标的资产的价格路径(基于实际波动率),后者则是基于对冲的波动率来计算对冲的delta,并多次进行模拟,得到期权对冲的收益及期望值、标准差、最大值、最小值等。参数设定及调用方式参见main函数。
# -*- coding: utf-8 -*-
"""
@time:2021/6/24 9:58@author: Hu Yue
@email: hhhuyue@gmail.com
@file: hedge.py
Note:
"""
from math import sqrt
from typing import Typeimport scipy.stats as si
import numpy as np
from matplotlib import pyplot as plt
from scipy.stats import normclass PriceSimulator:def __init__(self, S, K, T, rf, cp_type, IV, RV, simulation_steps, expected_return):self.simulation_steps = simulation_stepsself.RV = RVself.IV = IVself.cp_type = cp_typeself.rf = rfself.T = Tself.K = Kself.S = Sself.mu = expected_returndef get_option_price(self, S, K, T, sigma, rf, option_type):d1 = (np.log(S / K) + (rf + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))d2 = d1 - sigma * np.sqrt(T)if option_type == "Call":option_price = S * norm.cdf(d1) - K * np.exp(-rf * T) * norm.cdf(d2)else:option_price = K * np.exp(-rf * T) * norm.cdf(-d2) - S * norm.cdf(-d1)return option_pricedef simulate(self):random_seed = np.random.standard_normal((self.simulation_steps, 1))dt = self.T / self.simulation_steps# Monte carlo模拟 真实的波动率生成标的价格路径stock_price = self.S * np.exp(np.cumsum((self.mu - 0.5 * self.RV ** 2) * dt + self.RV * sqrt(dt) * random_seed, axis=0))option_price = np.zeros((self.simulation_steps, 1))expire_time = (np.ones((self.simulation_steps, 1)) * dt).cumsum()[::-1]# 期权价格路径基于隐含波动率生成,期权市场价格for step in range(self.simulation_steps):option_price[step] = self.get_option_price(stock_price[step], self.K, expire_time[step], self.IV,self.rf,self.cp_type)return stock_price, option_pricedef plot(self, price):# 制作模拟价格走势图表plt.plot(price[:, :], lw=1.5)plt.rcParams['font.sans-serif'] = ['SimHei']plt.xlabel('时间')plt.ylabel('价格')plt.title('模拟价格走势')plt.show()class OptionHedge:def __init__(self, S, K, T, rf, cp_type, IV, RV, expected_return):self.mu = expected_returnself.RV = RVself.IV = IVself.cp_type = cp_typeself.rf = rfself.T = Tself.K = Kself.S = Sself.simulation_steps = 1000self.dt = 1 / 1000def init_price_simulator(self, price_simulator: Type[PriceSimulator], simulation_steps):self.simulation_steps = simulation_stepsself.dt = self.T / simulation_stepsreturn price_simulator(self.S, self.K, self.T, self.rf, self.cp_type, self.IV, self.RV, simulation_steps,self.mu)def get_delta(self, S, K, T, sigma, rf, option_type):if option_type == "Call":n = 1else:n = -1d1 = (np.log(S / K) + (rf + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))delta = n * si.norm.cdf(n * d1)return deltadef hedge(self, hedge_volatility, price_simulator: PriceSimulator, simulation_times):pnl = np.zeros((self.simulation_steps - 1, simulation_times))for simulation in range(simulation_times):stock_price, option_price = price_simulator.simulate()# 基于对冲波动率计算的delta值expire_time = (np.ones((simulation_steps, 1)) * self.dt).cumsum()[::-1] # 倒序delta = np.zeros((simulation_steps, 1))for step in range(simulation_steps):delta[step] = self.get_delta(stock_price[step], self.K, expire_time[step], hedge_volatility,self.rf,self.cp_type)pnl_path = np.diff(option_price, axis=0) - delta[:-1] * np.diff(stock_price, axis=0) - \self.rf * self.dt * (option_price[:-1] - delta[:-1] * stock_price[:-1])pnl[:, simulation] = pnl_path.reshape(simulation_steps - 1)return pnldef plot(self, pnl):plt.plot(pnl.cumsum(axis=0)[:, :], lw=1.5)plt.rcParams['font.sans-serif'] = ['KaiTi', 'SimHei', 'FangSong']plt.rcParams['font.size'] = 12plt.rcParams['axes.unicode_minus'] = Falseplt.xlabel('时间')plt.ylabel('收益')plt.title('期权对冲累积收益图')plt.show()if __name__ == '__main__':# 参数设定,无分红risk_free_rate = 0.1expected_return = 0implied_volatility = 0.2actual_volatility = 0.2init_stock_price = 100strike_price = 100option_type = "Call"T = 1simulation_steps = 1000 # 每次模拟有1000步simulation_times = 100 # 模拟1000次# 初始化期权和标的option_hedge = OptionHedge(init_stock_price, strike_price, T, risk_free_rate, option_type, implied_volatility,actual_volatility, expected_return)# 期权价格和标的资产价格路径模拟器price_simulator = option_hedge.init_price_simulator(PriceSimulator, simulation_steps)# 多次模拟并进行对冲,对冲的波动率可自行选择# pnl = option_hedge.hedge(implied_volatility, price_simulator, simulation_times)# option_hedge.plot(pnl)# 分析不同波动率对对冲收益的影响volatility = np.arange(0, 1, 0.02)hedge_pnl = np.ones((len(volatility), 5))for i in range(1, len(volatility)):pnl = option_hedge.hedge(volatility[i], price_simulator, simulation_times).sum(axis=0)expected_profit = np.mean(pnl)standard_deviation_profit = np.std(pnl)max_profit = np.max(pnl)min_profit = np.min(pnl)print(volatility[i], expected_profit, standard_deviation_profit, min_profit, max_profit)hedge_pnl[i, :] = [volatility[i], expected_profit, standard_deviation_profit, min_profit, max_profit]plt.plot(hedge_pnl[1:, 0], hedge_pnl[1:, 1:], lw=1.5)plt.rcParams['font.sans-serif'] = ['KaiTi', 'SimHei', 'FangSong']plt.rcParams['font.size'] = 12plt.rcParams['axes.unicode_minus'] = False# plt.xticks(np.arange(0, 1, 0.1))plt.xlabel('波动率')plt.ylabel('收益')plt.title('期权对冲累积收益图')plt.legend(["expected profit", "Standard deviation of profit", "Minimum profit", "Maximum profit"], loc=9,fontsize=10)ax = plt.gca() # gca:get current axis得到当前轴ax.spines['right'].set_color('none')ax.spines['top'].set_color('none')ax.spines['bottom'].set_position(('data', 0))plt.show()
这篇关于Delta对冲:一般形式及模拟实验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!