作者:依然-狠幸福 | 来源:互联网 | 2023-09-16 19:16
文章目录期权Delta对冲:模拟实验1.模拟参数设定2.MonteCarlo模拟标的价格路径3.利用BS计算delta和期权理论价值4.结果呈现4.1使用实际波动率进
文章目录
- 期权Delta对冲:模拟实验
- 1. 模拟参数设定
- 2. Monte Carlo模拟标的价格路径
- 3. 利用BS计算delta和期权理论价值
- 4. 结果呈现
- 4.1 使用实际波动率进行对冲
- 4.2 使用隐含波动率进行对冲
- 5. 完整代码
期权Delta对冲:模拟实验
1. 模拟参数设定
假定买入一个欧式平值认购期权,一年后到期,行权价为100,隐含波动率为20%,实际波动率为30%,无风险利率为5%。本文将对冲1000次,根据不同的价格路径模拟标准delta对冲过程十次。本实验基于BS公式与其假设条件(波动率是固定不变的)。
2. Monte Carlo模拟标的价格路径
假设标的资产价格服从几何布朗运动:
dS=μSdt+σSdz,dz=ϵdtdS = \mu S dt +\sigma S dz, dz = \epsilon \sqrt{dt}dS=μSdt+σSdz,dz=ϵdt
由于风险中性的假设存在,其中μ=r\mu = rμ=r,μ\muμ是标的资产价格收益的均值,σ\sigmaσ是标的资产价格收益的年化标准差,ϵ\epsilonϵ服从N(0,1)N(0,1)N(0,1)的正态分布。
根据伊藤引理:
有伊藤过程dx=a(t,x)dt+b(t,x)dzdx = a(t,x)dt+b(t,x)dzdx=a(t,x)dt+b(t,x)dz,其中dz服从维纳过程
G(x,t)服从以下过程 :
dG=(∂G∂xa+∂G∂t+12∂2G∂x2b2)dt+∂G∂zbdzdG = (\frac{\partial G}{\partial x}a +\frac{\partial G}{\partial t} +\frac{1}{2} \frac{\partial^2 G}{\partial x^2}b^2)dt+\frac{\partial G}{\partial z}bdzdG=(∂x∂Ga+∂t∂G+21∂x2∂2Gb2)dt+∂z∂Gbdz
若G=lnSG=\ln SG=lnS,则∂G∂x=1S,∂2G∂x2=−1S2,∂G∂t=0\frac{\partial G}{\partial x} =\frac{1}{S}, \frac{\partial^2 G}{\partial x^2}=-\frac{1}{S^2}, \frac{\partial G}{\partial t}=0∂x∂G=S1,∂x2∂2G=−S21,∂t∂G=0,可以推出:
dG=d(lnS)=(μ−σ22)dt+σdzST=S0exp((μ−σ22)T+σϵT)dG =d(\ln S)=(\mu - \frac{\sigma^2}{2})dt + \sigma dz \\ S_T = S_0 exp((\mu - \frac{\sigma^2}{2})T + \sigma \epsilon \sqrt{T}) dG=d(lnS)=(μ−2σ2)dt+σdzST=S0exp((μ−2σ2)T+σϵT)
模拟标的价格的代码如下:
stock_price_paths = init_stock_price * np.exp(np.cumsum((risk_free_rate - 0.5 * actual_volatility ** 2) * dt + actual_volatility * sqrt(dt) * random_seed,axis=0))
3. 利用BS计算delta和期权理论价值
Black-sholes公式如下所示:
def get_delta(S, T, K, 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 get_option_price(S, T, K, 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_price
4. 结果呈现
4.1 使用实际波动率进行对冲
使用实际波动率进行对冲,最终的收益是确定的,即V(S,t,σ)−V(S,t,σ~)V(S,t,\sigma) - V(S,t,\tilde{\sigma})V(S,t,σ)−V(S,t,σ~),其中S代表标的资产的价格,t代表剩余到期时间,σ\sigmaσ代表实际波动率,σ~\tilde{\sigma}σ~代表隐含波动率。对冲收益取决于隐含波动率和实际波动率的差。
此外,可以看出每次对冲的收益是不确定的,具有较大的波动性。
4.2 使用隐含波动率进行对冲
使用隐含波动率进行对冲,最终的收益是不确定的,总收益为12(σ2−σ~2)∫t0Te−r(t−t0)S2Γidt\frac{1}{2}(\sigma^2 - \tilde{\sigma}^2) \int_{t_0}^{T} e^{-r(t-t_0)} S^2 \Gamma^i dt21(σ2−σ~2)∫t0Te−r(t−t0)S2Γidt, 在本次实验中的实际波动率为30%,高于隐含波动率20%,且期权的Gamma值一定为正,对冲的收益一定为正,但收益的值是不确定的。
但是每次对冲的收益是确定的,没有较大的波动。每次对冲的收益为12(σ2−σ~2)S2Γidt\frac{1}{2}(\sigma^2 - \tilde{\sigma}^2) S^2 \Gamma^i dt21(σ2−σ~2)S2Γidt
5. 完整代码
"""
@time:2021/6/24 9:58@author: Hu Yue
@email: hhhuyue@gmail.com
@file: hedge.py
Note:
"""
from math import sqrt
import scipy.stats as si
import numpy as np
from matplotlib import pyplot as plt
from scipy.stats import norm
risk_free_rate = 0.05
implied_volatility = 0.2
actual_volatility = 0.3init_stock_price = 100
strike_price = 100strike_style = "European"
option_type = "Call"T = 1
simulation_steps = 1000
simulation_times = 10
dt = 1 / 1000
random_seed = np.random.standard_normal((simulation_steps, simulation_times))
stock_price_paths = init_stock_price * np.exp(np.cumsum((risk_free_rate - 0.5 * actual_volatility ** 2) * dt + actual_volatility * sqrt(dt) * random_seed,axis=0))
def get_delta(S, T, K, 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 get_option_price(S, T, K, 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_price
expire_time = (np.ones((simulation_steps, 1)) * dt).cumsum()[::-1]
pnl = np.zeros((simulation_steps - 1, simulation_times))
for simulation in range(simulation_times):stock_price = stock_price_paths[:, simulation].reshape((simulation_steps, 1))delta = np.zeros((simulation_steps, 1))option_price = np.zeros((simulation_steps, 1))for step in range(simulation_steps):delta[step] = get_delta(stock_price[step], expire_time[step], strike_price, actual_volatility, risk_free_rate,option_type)option_price[step] = get_option_price(stock_price[step], expire_time[step], strike_price, implied_volatility,risk_free_rate,option_type)pnl_path = np.diff(option_price, axis=0) - delta[:-1] * np.diff(stock_price, axis=0) - \risk_free_rate * dt * (option_price[:-1] - delta[:-1] * stock_price[:-1])pnl[:, simulation] = pnl_path.reshape(simulation_steps - 1)
cum_pnl = pnl.cumsum(axis=0)plt.plot(cum_pnl[:, :], lw=1.5)
plt.rcParams['font.sans-serif'] = ['KaiTi', 'SimHei', 'FangSong']
plt.rcParams['font.size'] = 12
plt.rcParams['axes.unicode_minus'] = False
plt.xlabel('时间')
plt.ylabel('收益')
plt.title('期权对冲累积收益图')
plt.show()