蒙特卡洛模拟法对欧式期权定价
对于标的资产价格为S0,执行价格是X的欧式看涨期权,到期日T的价格为CT = max(0,ST-X),在风险中性世界里用无风险利率r贴现,则期权在t时刻的价格为CT = e-r(T-t)E[max(0,ST-X)],这也是BS公式的推导思路之一。由于CT只与ST有关,因此我们只需模拟ST的路径,重复n次,再对他们求平均就可以得到看涨期权的价格,即CT = e-r(T-t)Σ[max(0,ST-X)] /n,同理看跌期权价格PT = e-r(T-t)Σ[max(0,X-ST)] /n。注意蒙特卡洛模拟不能给美式期权定价。
关于标的资产价格ST的蒙特卡洛模拟,在(二十三)中已经介绍过,主要使用如下公式:
假设有一份期限为六个月的股票期权,标的资产股票价格为5.29元,期权执行价格为6元,年化无风险利率和年化波动率分别为4%和24%,用蒙特卡洛模拟法求看涨期权和看跌期权的价格(模拟1万次)。
import numpy as np
from numpy.random import standard_normal
def callMonteCarlo(S,X,r,sigma,t,n):
z=standard_normal(n)
St=S*np.exp((r-0.5*sigma**2)*t+sigma*z*np.sqrt(t))
return sum(np.maximum(0,St-X))*(np.exp(-r*t))/n
def putMonteCarlo(S,X,r,sigma,t,n):
z=standard_normal(n)
St=S*np.exp((r-0.5*sigma**2)*t+sigma*z*np.sqrt(t))
return sum(np.maximum(0,X-St))*(np.exp(-r*t))/n
c=callMonteCarlo(5.29,6,0.04,0.24,0.5,10000)
p=putMonteCarlo(5.29,6,0.04,0.24,0.5,10000)
print('蒙特卡洛模拟算出的看涨期权价格为{:.4f},看跌期权价格为{:.4f}'.format(c,p))
蒙特卡洛模拟算出的看涨期权价格为0.1520,看跌期权价格为0.7450
用BS公式算出来的看涨期权价格为0.1532,看跌期权价格为0.7443,结果非常接近。
蒙特卡洛模拟的精度与模拟次数成比,但是次数增加又会降低计算效率,因此通过方差减小技术可以提高稳定性,减少模拟次数。主要方差减小技术有对偶变量技术和控制变量技术。
对偶变量法蒙特卡洛模拟
对偶变量法的思路是生成n个随机数代入公式求得n个样本的平均价格,然后令另外n个随机数为这一组随机数的相反数再求n个样本的均价,最后将这两个价格求平均即可。因为如果有一组的z偏大导致价格偏大,那么另外一组z算出的价格一定会偏小,二者的平均值就会更加接近真实情况。还是以上述例子为例:
def call_dual(S,X,r,sigma,t,n):
z=standard_normal(n)
S1=S*np.exp((r-0.5*sigma**2)*t+sigma*z*np.sqrt(t))
S2=S*np.exp((r-0.5*sigma**2)*t+sigma*(-z)*np.sqrt(t))
c1=sum(np.maximum(0,S1-X))*(np.exp(-r*t))/n
c2=sum(np.maximum(0,S2-X))*(np.exp(-r*t))/n
return (c1+c2)/2
def put_dual(S,X,r,sigma,t,n):
z=standard_normal(n)
S1=S*np.exp((r-0.5*sigma**2)*t+sigma*z*np.sqrt(t))
S2=S*np.exp((r-0.5*sigma**2)*t+sigma*(-z)*np.sqrt(t))
c1=sum(np.maximum(0,X-S1))*(np.exp(-r*t))/n
c2=sum(np.maximum(0,X-S2))*(np.exp(-r*t))/n
return (c1+c2)/2
c=call_dual(5.29,6,0.04,0.24,0.5,5000)
p=put_dual(5.29,6,0.04,0.24,0.5,5000)
print('对偶蒙特卡洛法算出的看涨期权价格为{:.4f},看跌期权价格为{:.4f}'.format(c,p))
对偶蒙特卡洛法算出的看涨期权价格为0.1526,看跌期权价格为0.7438
可见在对偶蒙特卡洛模拟法下,仅模拟5000次的结果就与BS公式计算结果非常接近了。
控制变量法蒙特卡洛模拟
若衍生证券A与衍生证券B的价格高度相关,且B的价格已知或者容易估计,则用蒙特卡洛法对B进行估计以后,将误差加到A的蒙特卡洛估计值上即可。这种方法的缺点是需要找到与A相关性很高的B。具体代码可设计如下(其中期权B的价格为参数B,其标的资产价格为S2):
def call_con(S1,S2,X,r,sigma,t,B,n):
z1=standard_normal(n)
S1t=S1*np.exp((r-0.5*sigma**2)*t+sigma*z*np.sqrt(t))
C1=sum(np.maximum(0,S1t-X))*(np.exp(-r*t))/n
z2=standard_normal(n)
S2t=S2*np.exp((r-0.5*sigma**2)*t+sigma*z*np.sqrt(t))
C2=sum(np.maximum(0,S2t-X))*(np.exp(-r*t))/n
return C1+B-C2
综上所述,个人认为性价比最高的是对偶蒙特卡洛模拟法。
来源:CSDN
作者:小粉桥反手王
链接:https://blog.csdn.net/hzk427/article/details/104538974