LIUKK的工作站
LiuKK
Jun 25, 2016
阅读本文需要 18 分钟

这里的公式显示有问题,请移步我在优矿上的帖子:期权定价的几种方法

1.Black-Scholes期权定价公式的推导

保罗萨缪尔森在1965年提出来的股价模型:

其中\(\mu\,\sigma\)是常数,\(B\)是布朗运动。
上述微分方程的解为:

对于欧式看涨期权,最终支付为\(\left(S_{T}-X \right)^{+}\),所以有:

我们用②的模型:

由于\(B_{T}\)是服从均值为0,方差为T的正态分布,所以考虑用\(\sqrt{T} Z\)代替\(B_{T}\),Z是标准正态分布:

则有:

解方程\(S_{0} e x p \left [ \sigma \sqrt{T} a+ \left(r- \frac{ \sigma^{2}}{2} \right) T \right ]-x=0\)

得到:

接下来将⑦分为两部分求解,第二部分:

第一部分:

它等于:

因此:

这时之前求得的a值就有用了:

令 \(-a=d_{2}\) and \(a- \sigma \sqrt{T}=d_{1}\),则有:

以上求解均假设没有分红,交易费用等。
对于欧式期权,BS公式有精确的定价公式,但对于美式期权,BS公式不可能求出解的表达式。

2.二叉树期权定价

二叉树也称为二项式定价模型,二项期权定价模型由考克斯(J.C.Cox)、罗斯(S.A.Ross)、鲁宾斯坦(M.Rubinstein)和夏普(Sharpe)等人提出的一种期权定价模型,主要用于计算美式期权的价值。其优点在于比较直观简单,不需要太多数学知识就可以加以应用。

image

在很小的一段时间内假设股价会向上运动到\(S_{0}u\),也可能向下运动到\(S_{0}d\)。
为了确定u,d,p,我们假设市场为风险中性,即股票预期收益率等于无风险利率,接着我们构造资产组合:
Portfolio:买\(\Delta\)单位的标的资产,卖出1单位的衍生品(期权)。
上涨情形:资产组合的价值为:

下跌情形:资产组合的价值为:

复制无风险资产,上述两式相等,可以解出:

再根据

求出

将\(\Delta\)代入得到

其中:

根据风险中性的假设,我们有如下方程组(均值和方差):

再假设u=1/d,那么便可以解出p,u,d:

以下是在matlab中实现的欧式期权二叉树定价,假设没有红利支付。可以用N来调节需要的二叉树的期数。

function [c1,p1]=bt(N)
%s0: stock price
%k: strik price
%sigma: volatility of stock
%r:riskfree rate
%T:expiration date

s0=99.62;
k=100;
sigma=0.4782;
r=0.0185;
T=0.2322;
dt=T/N;

u=exp(sigma*sqrt(dt));
d=1/u;

pu=(exp(r*dt)-d)/(u-d);
pd=(u-exp(r*dt))/(u-d);


c=0;
p=0;
for i =0:N
    s=s0*u^i*d^(N-i);
    c=c+max((s-k),0)*pu^i*nchoosek(N,i)*pd^(N-i);
    p=p+max((k-s),0)*pu^i*nchoosek(N,i)*pd^(N-i);
end

c1=c*exp(-r*T);
p1=p*exp(-r*T);

二叉树和BS公式定价的比较

可以证明,随着期数的增加,二叉树的结果收敛于BS公式的结果。

image

当然,二叉树也可以为美式期权定价,方法与欧式期权类似,只不过需要算出每个节点的价格,代码就不贴了,有兴趣可以自己实现以下。

3.蒙特卡洛模拟美式看跌期权定价——Regression-Based Methods

蒙特卡洛模拟可以轻松实现路径依赖期权(障碍期权、亚式齐全)的定价。近年来,由Longstaff和Schwartz提出的最小二乘蒙特卡洛(LSM)模拟方法, 该方法已成为目前使用蒙特卡洛模拟美式期权定价的标准方法。LSM有这样一些假定:不支付交易费和税收、无套利机会、不支付红利、无风险利率是常数、标的资产价格演化遵循几何布朗运动。

基本思想: max里第一项是现在执行获得的payoff,第二项是选择等待所能获得的payoff的期望,这个期望用多项式回归的方法获得,即建立当期股价与下期payoff的模型。

import numpy as np
def regressionP(K,M=1000,N=50):
#lam: poisson分布的均值
#S:模拟的股价矩阵
#f:立即执行的payoff矩阵
#M:模拟的路径数量
#N:模拟的期数
    r=0.0173
    sigma=0.24722
    S0=96.10
    #K=97.50
    T=117.0/360 #单位是年
    lam=4
    dt=T/N
    S=np.zeros((M,N+1))
    S[:,0]=S0
    f=np.zeros\_like(S)
    f[:,0]=0

    #这里模拟股价矩阵用到了跳跃扩散过程,也可以试一下其它的
    X=np.random.poisson(lam*dt,(M,N))
    for i in range(M):
        for j in range(1,N+1):
            Y=1.1+0.2*np.random.rand(X[i,j-1])
            m=Y.prod()
            S[i,j]=S[i,j-1]*np.exp((r-0.5*sigma**2)*dt+sigma*dt**0.5*np.random.randn())*m
            f[i,j]=max(K-S[i,j],0)
    
    P=0 #期权价格
    y=np.zeros((M,N)) #最小二乘拟合的payoff
    d=np.zeros((M,1)) #用于计数,之后判断f矩阵中的值是不是每行第一个大于0的
    for i in range(1,N):
        a=f[:,i+1] #a,b是临时储存向量的变量(想不出什么好名字。。)
        b=S[:,i]
        
        W=a[f[:,i]>0]*np.exp(-r*dt)
        s=b[f[:,i]>0]
        #W是回归模型的因变量
        #s是回归模拟的自变量
        if s.size==0:
            pass
        else:
            z=np.polyfit(s,W,2) #这里建立的是二次多项式模型,试了下更高次的,结果区别不大
            p=np.poly1d(z)
            y[:,i]=p(b)
        
            f[:,i]=f[:,i]*((f[:,i]>y[:,i])*1)
        
        
            d=d+((f[:,i]>0)*1).reshape(M,1)
            q=f[:,i].reshape(M,1)
            P=P+sum(q[d==1])*np.exp(-r*dt*i)
            #这个地方的reshape折腾的死去活来。。
    
    #由于最后一列的f没有在上述循环里面,需要单独写出来
    d=d+((f[:,N]>0)*1).reshape(M,1)
    q=f[:,N].reshape(M,1)
    P=(P+sum(q[d==1])*np.exp(-r*T))/M
    return P
import warnings
warnings.filterwarnings("ignore")
p=[]
for i in np.arange(80,100,2.5):
    c=regressionP(i)
    p.append(c)
for i in np.arange(100,130,5):
    c=regressionP(i)
    p.append(c)
real=[1.01,1.23,1.65,2.18,2.58,3.67,4.70,6,7.5,11.47,15.65,19.30,24.15,29.60]
l1=np.arange(80,100,2.5)
l2=np.arange(100,130,5)
x=np.concatenate((l1,l2))


import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
plt.figure()
plt.plot(x,p,'k-',label='LSM method')
plt.plot(x,real,'k--',label='real price')
plt.ylabel('put option price')
plt.xlabel('strike price')
plt.legend(loc='best')
plt.show()

image

这里我选择苹果公司的股票和期权来进行定价。一般来讲,做模拟的话,深度实值或者深度虚值期权定价与实际价格的差距较大,越接近平值越准确。可是上图却好像是相反的,这是怎么回事,我也还没有想清楚,还请大神赐教。

4.有限差分

B-S partial differential equation

先来看一下BS偏微分方程(这个东西很让人头大啊。。):

之前提过,股票的价格遵循几何布朗运动:

\(\mu\)和\(\sigma\)表示股票价格的预期收益率和波动率。

\(V \left(S , t \right)\)表示某股票期权的价格,我们对它做泰勒展开(直接省略了大于2阶的项):

将①代入②中,并只保留\(dt\)的一阶项:

用\(\sqrt{T} Z\)代替\(dB\),Z是标准正态分布,还是只保留一阶项:

为了简化上式,用\(Z^{2}\)的期望值代替它,\(E \left(Z^{2} \right)=V a r \left(Z \right)=1\),进一步得到:

接下来考虑①式和③式离散的形式:

为了消除\(\Delta B\),我们构建一个包含一单位衍生证券空头和\( \frac{ \partial V}{ \partial S}\),单位标的证券多头的投资组合,令\(\Pi\)为该组合的价值,则:

在经过\(\Delta t\)时间后,该资产组合的价值变化量为:

将\(Delta S\)和\(\Delta V\)代入⑤式:

⑥式中不含\(\Delta B\),因此在时间间隔\(\Delta t\)后该组合的价值必定无风险,其在\(\Delta t\)后的瞬时收益率一定等于无风险收益率,所以就有:\( \Delta \Pi =r \Pi \Delta t\),与⑥式联立整理后得到:

这就是著名的BS偏微分方程,可以应用于价格取决于标的资产价格S的所有衍生证券定价。

用差分估计参数

终于搞定了PDE,现在就是要估计\(\frac{ \partial V}{ \partial t}\),\(\frac{ \partial V}{ \partial S}\) ,和\(\frac{ \partial^{2} V}{ \partial S^{2}}\),于是就要用到差分的方法了:

image

  • 对于一阶项:

forward approximation: \( \frac{ \partial V}{ \partial S} \cong \frac{V_{ \imath , j+1}-V_{ \imath , j}}{ \Delta S}\),\( \frac{ \partial V}{ \partial t} \cong \frac{V_{ \imath +1 , j}-V_{ \imath , j}}{ \Delta t}\)

backward approximation:\( \frac{ \partial V}{ \partial S} \cong \frac{V_{ \imath , j}-V_{ \imath , j-1}}{ \Delta S}\),\( \frac{ \partial V}{ \partial t} \cong \frac{V_{ \imath , j}-V_{ \imath -1 , j}}{ \Delta t}\)

center approximation: \( \frac{ \partial V}{ \partial S} \cong \frac{V_{ \imath , j+1}-V_{ \imath , j-1}}{2 \Delta S}\),\( \frac{ \partial V}{ \partial t} \cong \frac{V_{ \imath +1 , j}-V_{ \imath -1 , j}}{2 \Delta t}\)

  • 二阶项:

隐性差分

有了以上3个式子,再加上PDE,就可以得到下面的:

可以得到\(a_{j}\),\(b_{j}\),\(c_{j}\)的通式(其中\( \frac{S}{ \Delta S}=j\)):

image

回想上面的网格图,以欧式看跌期权为例,算法如下:
1.初始化一些值,\(f_{ \imath , 0}=K , f_{ \imath , M}=0 , f_{N , j}=m a x \left(K-j \Delta S , 0 \right)\),还有\(a_{j}\),\(b_{j}\),\(c_{j}\)。

2.for i =N:0,解方程组:

3.找到离S0最近的点,输出期权价格。

import numpy as np
from mpl\_toolkits.mplot3d import Axes3D
import seaborn as sns
import matplotlib.pyplot as plt

SMAX=150
dS=1
T=1
dT=0.1
K=50
r=0.1
sigma=0.5

N=T/dT
M=SMAX/dS

f=np.zeros((M+1,N+1))

f[0,:]=K
f[M,:]=0

f[:,N]=[max(K-j*dS,0) for j in range(M+1)]
a=[0.5*dT*(-sigma**2*j**2+r*j) for j in range(M-1)]
b=[1+dT*(sigma**2*j**2+r) for j in range(M-1)]
c=[-0.5*dT*(sigma**2*j**2+r*j) for j in range(M-1)]

x=np.zeros((M-1,M+1))
j=0
for i in range(M-1):
    x[i,j]=a[i]
    x[i,j+1]=b[i]
    x[i,j+2]=c[i]
    j+=1
x=x[:,1:M]
for i in np.arange(N,0,-1):
    y=f[:,i][1:M]
    f[:,i-1][1:M]=np.linalg.solve(x,y)


fig = plt.figure()
ax = fig.gca(projection='3d')
X,Y=np.meshgrid(np.arange(0,11,1),np.arange(0,151,1))
surf = ax.plot\_surface(X,Y,f, cmap='summer', cstride=2, rstride=2)
ax.set\_xlabel("Time")
ax.set\_ylabel("Stock price")
ax.set\_zlabel("Option price")

png


>