期权定价数值方法之蒙特卡洛模拟【python量化】

期权定价数值方法之蒙特卡洛模拟

前言

蒙特卡洛模拟最重要的应用之一是对未定权益,如期权、衍生品、混合型工具的估值。在风险世界中,未定权益的价值是风险中立(鞅)测度下的折现后的预期收益。

一、蒙特卡洛模拟思路

蒙特卡洛模拟需要用到风险中立世界思想。其基本思路为:尽可能的模拟风险中性世界中标的资产价格的多种路径,计算每种路径下的期权回报均值,再贴现就可得期权价格。
①在风险中性世界里对S的随机路径进行抽样,这就给出了标的资产价格路径的一个实现。
②计算这条路径下的期权回报。
③重复计算步骤①、②,得到许多样本结果,即风险中性世界中的期权回报值。
④计算这些回报的均值,得到风险中性世界中的预期期权回报值。
⑤用无风险利率进行贴现,得到这个期权的估计价值。
在这里插入图片描述

二、随机过程

前文说到,蒙特卡洛模拟方法需要模拟标的资产的价格路径,而价格路径的变化是随机的,可以通过数学上的随机过程进行模型。因此本部分将介绍集中主流的随机过程。

粗略地讲,随机过程是一个随机变量序列。但是随机数的选取一般不是独立的,而是依赖于前几次选取的结果。不过,金融学中使用的随机过程通常表现出马尔科夫特性 ——主要的含义是:明天的过程值只依赖于今天的过程状态,而不依赖其他任何“历史”状态,甚至不依赖整个路径历史。这种过程也被称做“无记忆过程 ”

1.几何布朗运动

根据Black-Scholes模型,在风险中性世界中,标的资产价格变量遵循几何布朗运动,几何布朗运动的数学公式为:
在这里插入图片描述
式中的Zt 是标准布朗运动,SDE被称作几何布朗运动。St 的值呈对数正态分布。

几何布朗运动的代码实现如下所示:

# 随机过程
# 几何布朗运动
S0=100
r=0.05
sigma=0.25
T=2
I=10000
M=50
dt=T/M
S=np.zeros((M+1,I))
S[0]=S0
for t in range(1,M+1):
    S[t]=S[t-1]*np.exp((r-0.5*sigma**2)*dt+sigma*np.sqrt(dt)*npr.standard_normal(I))
plt.figure(figsize=(10,8))
plt.hist(S[-1],bins=50)
plt.xlabel('到期日时几何布朗运动模拟的股票价格')
plt.ylabel('频率')

plt.figure(figsize=(10,8))
plt.plot(S[:100],lw=1.5)
plt.xlabel('时间')
plt.ylabel('股票价格')
plt.title('几何布朗运动下的股票价格路径')

这里假设标的资产的初始价格为100,利率r为0.05,波动率为0.25。从图中可以看出,几何布朗运动模拟标的资产价格路径呈现对数正态分布,且价格路径的分析多集中在初始价格100左右,这说明模拟结果出现极端数值的概率比较小。
期权定价数值方法之蒙特卡洛模拟【python量化】_第1张图片
期权定价数值方法之蒙特卡洛模拟【python量化】_第2张图片

2.Heston随机波动率

在Black-Scholes模型中,最重要的简化假设之一便是波动率恒定不变。而在市场中,波动率不是恒定不变的,而是随着时间的变化而变化,是具有随机性的。因此随机波动率过程的提出对之前的几何布朗运动进行了改进。
期权定价数值方法之蒙特卡洛模拟【python量化】_第3张图片
Heston模型的代码实现如下所示:

# heston随机波动率
S0=100
r=0.05
v0=0.1
kappa=3
theta=0.25
sigma=0.1
rho=0.6
T=1
corr_mat=np.zeros((2,2))
corr_mat[0,:]=[1,rho]
corr_mat[1,:]=[rho,1]
cho_mat=np.linalg.cholesky(corr_mat)
cho_mat

M=50
I=10000
dt=T/M
ran_num=npr.standard_normal((2,M+1,I))
v=np.zeros_like(ran_num[0])
vh=np.zeros_like(v)
v[0]=v0
vh[0]=v0
for t in range(1,M+1):
    ran=np.dot(cho_mat,ran_num[:,t,:])
    vh[t]=(vh[t-1]+kappa*(theta-np.maximum(vh[t-1],0))*dt+sigma*np.sqrt(np.maximum(vh[t-1],0))*np.sqrt(dt)*ran[1])
v=np.maximum(vh,0)
S=np.zeros_like(ran_num[0])
S[0]=S0
for t in range(1,M+1):
    ran=np.dot(cho_mat,ran_num[:,t,:])
    S[t]=S[t-1]*np.exp((r-0.5*v[t])*dt+np.sqrt(v[t])*ran[0]*np.sqrt(dt))
fig,(ax1,ax2)=plt.subplots(1,2,figsize=(10,6))
ax1.hist(S[-1],bins=50)
ax1.set_xlabel('股票价格')

ax2.hist(v[-1],bins=50)
ax2.set_xlabel('波动率')

fig,(ax1,ax2)=plt.subplots(2,1,sharex=True,
                          figsize=(10,6))
ax1.plot(S[:,:100],lw=1.5)
ax1.set_ylabel('股票价格')
ax2.plot(v[:,:100],lw=1.5)
ax2.set_ylabel('波动率')

从图中可以看出,Heston随机波动率模型对价格路径的模型情况相比于几何布朗运动而言,呈现出明显的波动性特征,且波动率过程的平均飘移值收敛于0.25(θ数值)。

期权定价数值方法之蒙特卡洛模拟【python量化】_第4张图片
期权定价数值方法之蒙特卡洛模拟【python量化】_第5张图片

3.Merton跳跃-扩散

随机波动率和杠杆效应是许多市场中的典型现象。在市场交易中,标的资产价格往往会因为突发事件而发生突然的跳跃。
1976年,Merton提出了跳跃-扩散模型来模拟标的资产价格的路径。

Merton 模型假设标的资产价格的变化路径服从跳跃扩散过程。其中,标的资产的价格变化过程中的跳跃部分属于可分散风险,具有系统性风险的标的资产价格变化用几何布朗运动描述,非系统性风险的标的资产价格跳跃用泊松跳跃过程描述,跳跃的幅度则用正态分布表示。
期权定价数值方法之蒙特卡洛模拟【python量化】_第6张图片
Merton跳跃-扩散模型的代码实现为:

# 跳跃扩散
S0=100
r=0.05
sigma=0.2
lamb=0.75
mu=-0.6
delta=0.25
rj=lamb*(math.exp(mu+0.5*delta**2)-1)
T=1
M=50
I=10000
dt=T/M
S=np.zeros((M+1,I))
S[0]=S0
sn1=npr.standard_normal((M+1,I))
sn2=npr.standard_normal((M+1,I))
poi=npr.poisson(lamb*dt,(M+1,I))
for t in range(1,M+1,1):
    S[t]=S[t-1]*(np.exp((r-rj-0.5*sigma**2)*dt+sigma*np.sqrt(dt)*sn1[t])+(np.exp(mu+delta*sn2[t])-1)*poi[t])
    S[t]=np.maximum(S[t],0)
plt.figure(figsize=(10,6))
plt.hist(S[-1],bins=100)
plt.ylabel('频率')
plt.xlabel('股票价格')

从图中可以看出,Merton模型对价格路径的模型呈现出明显的跳跃特征,这表明在价格方程中加入跳跃因子以后,对价格的模拟更加贴合实际市场。

期权定价数值方法之蒙特卡洛模拟【python量化】_第7张图片
期权定价数值方法之蒙特卡洛模拟【python量化】_第8张图片

三、三种随机过程下的蒙特卡洛模拟

金融期权表示在规定(行权期)日期(欧式期权 )或者规定时期(美式期权)内,以规定价格(所谓行权价 )购买(看涨期权 )或者出售(看跌期权 )指定金融工具。这里,我们考虑估值较为简单的情况——欧式期权。

基于某种指数的欧式看涨期权到期日收益通过公式h (ST )≡max(ST -K ,0)得出,其中ST 是到期日T 的指数水平,K 是行权价格。

给定相关随机过程(例如几何布朗运动、Heston随机波动率模型、Merton跳跃-扩散模型等)的风险中立测度,或者在一个完备市场中,这种权证的价格为:
期权定价数值方法之蒙特卡洛模拟【python量化】_第9张图片

1.几何布朗运动下的蒙特卡洛模拟

在前文中讲到,蒙特卡洛模拟需要使用随机过程来模拟标的资产价格的变化路径,首先采用几何布朗运动来模拟价格路径,代码实现在前文中已给出。

几何布朗运动的蒙特卡洛模拟实现过程如下所示:

# 几何布朗运动的随机过程下的蒙特卡洛模拟
S0=100
r=0.05
sigma=0.25
T=1
I=50000
M=50
def gbm_mcs_dyna(K,T,S0,option='call'):
    dt=T/M
    S=np.zeros((M+1,I))
    S[0]=S0
    sn=gen_sn(M,I)
    for t in range(1,M+1):
        S[t]=S[t-1]*np.exp((r-0.5*sigma**2)*dt+sigma*math.sqrt(dt)*sn[t])
    if option=='call':
        hT=np.maximum(S[-1]-K,0)
    else:
        hT=np.maximum(K-S[-1],0)
    C0=math.exp(-r*T)*np.mean(hT)
    return C0

和期权定价的数值方法之二叉树模型一样,本文的数据采用沪深300期权。
【 期权定价的数值方法之二项式期权定价模型【附pyrhon代码】_xiaowu1997的博客-CSDN博客 https://blog.csdn.net/xiaowu1997/article/details/121730380】
数据一览
期权定价数值方法之蒙特卡洛模拟【python量化】_第10张图片
期权定价数值方法之蒙特卡洛模拟【python量化】_第11张图片

2.Heston随机波动率模型下的蒙特卡洛模拟

# heston随机波动率下的蒙特卡洛模拟
S0=100
r=0.015
v0=0.001
kappa=1.5
theta=0.25
sigma=0.25
rho=0.05
T=1
corr_mat=np.zeros((2,2))
corr_mat[0,:]=[1,rho]
corr_mat[1,:]=[rho,1]
cho_mat=np.linalg.cholesky(corr_mat)
cho_mat


M=50
I=50000
def heston_mcs_dyna(K,T,S0,option='call'):
    dt=T/M
    ran_num=npr.standard_normal((2,M+1,I))
    v=np.zeros_like(ran_num[0])
    vh=np.zeros_like(v)
    v[0]=v0
    vh[0]=v0
    for t in range(1,M+1):
        ran=np.dot(cho_mat,ran_num[:,t,:])
        vh[t]=(vh[t-1]+kappa*(theta-np.maximum(vh[t-1],0))*dt+sigma*np.sqrt(np.maximum(vh[t-1],0))*np.sqrt(dt)*ran[1])
    v=np.maximum(vh,0)
    S=np.zeros_like(ran_num[0])
    S[0]=S0
    for t in range(1,M+1):
        ran=np.dot(cho_mat,ran_num[:,t,:])
        S[t]=S[t-1]*np.exp((r-0.5*v[t])*dt+np.sqrt(v[t])*ran[0]*np.sqrt(dt))
    if option=='call':
        hT=np.maximum(S[-1]-K,0)
    else:
        hT=np.maximum(K-S[-1],0)
    C0=math.exp(-r*T)*np.mean(hT)
    return C0

结果如下所示
期权定价数值方法之蒙特卡洛模拟【python量化】_第12张图片

3.Merton跳跃-扩散模型下的蒙特卡洛模拟

# 跳跃扩散下的蒙特卡洛模拟
S0=100
r=0.015
sigma=0.15
lamb=0.25
mu=-0.45
delta=0.35
rj=lamb*(math.exp(mu+0.5*delta**2)-1)
T=1
def merton_mcs_dyna(K,T,S0,option='call'):
    M=50
    I=10000
    dt=T/M
    S=np.zeros((M+1,I))
    S[0]=S0
    sn1=npr.standard_normal((M+1,I))
    sn2=npr.standard_normal((M+1,I))
    poi=npr.poisson(lamb*dt,(M+1,I))
    for t in range(1,M+1,1):
        S[t]=S[t-1]*(np.exp((r-rj-0.5*sigma**2)*dt+sigma*np.sqrt(dt)*sn1[t])+(np.exp(mu+delta*sn2[t])-1)*poi[t])
        S[t]=np.maximum(S[t],0)
    if option=='call':
        hT=np.maximum(S[-1]-K,0)
    else:
        hT=np.maximum(K-S[-1],0)
    C0=math.exp(-r*T)*np.mean(hT)
    return C0

结果如下所示
期权定价数值方法之蒙特卡洛模拟【python量化】_第13张图片
将三种随机过程下的蒙特卡洛模拟定价结果进行汇总可得
期权定价数值方法之蒙特卡洛模拟【python量化】_第14张图片
从图中可以看出,Heston随机波动率模型下的蒙特卡洛模拟结果与期权真实数值偏离较大,这是由于Heston模型的五个参数设置引起的,实际上,这五个参数的设置对模型的结果影响甚大,因此,在使用Heston随机波动率、Merton跳跃-扩散模型时,模型的参数校准是很重要的,参数设置如何直接影响到模型定价效果。

最后,将三种随机过程下的蒙特卡洛模拟结果进行误差分析,分析指标如下:
期权定价数值方法之蒙特卡洛模拟【python量化】_第15张图片

# mape
mape=np.mean(np.abs((pred-label)/label))
# rmse
rmse=np.sqrt(np.mean(np.square(pred-label)))
# mae
mae=np.mean(np.abs(pred-label))

#MSE
mse=np.sum((label-pred)**2)/len(pred)

MCS模型测试集的mape: 0.24558352558988158  rmse: 0.02772822093999324  mae: 0.020338912894752575 MSE: 0.0007688542364970798

MCS_heston模型测试集的mape: 0.5694931305822826  rmse: 0.0683480757390468  mae: 0.048791757486744324 MSE: 0.0046714594572304785

MCS_merton模型测试集的mape: 0.47548594626983554  rmse: 0.040602865373948735  mae: 0.034560276796007636 MSE: 0.001648592676575005

从指标中可以看出,几何布朗运动下的蒙特卡洛模拟结果比heston随机波动率模型与merton跳跃扩散模型下的蒙特卡洛模拟结果要更加准确,这也说明了对于heston模型与merton模型而言,参数校准的重要性。

后续也会出一期关于heston模型与merton模型参数校准的博文。

总结

本章对蒙特卡洛模拟定价方法进行了简要的介绍,并且对比了在三种不同的随机过程下的蒙特卡洛模拟定价结果。

如果对期权和期权定价有兴趣的话,可以访问我写的期权机理与python量化的系统文章。
【期权机理与python实践】_xiaowu1997的博客-CSDN博客 https://blog.csdn.net/xiaowu1997/article/details/121478671

你可能感兴趣的:(期权量化,python,几何学,开发语言)