random
模块中的random.random()
,它可以产生一个在[0, 1]之间的均匀分布的浮点随机数,或者numpy
里的random
类中包括的均匀分布、正态分布等几种常用随机数产生器。import numpy as np
import math
class Monte_Carlo_European_option:
def __init__(self, r, sigma, S_0, K, T, N, M):
self.r = r
self.sigma = sigma
self.S_0 = S_0
self.K = K
self.T = T
self.N = N
self.M = M
self.call_price = None
self.put_price = None
def MC_simulation(self):
self.call_price = 0
self.put_price = 0
dt = self.T/self.N
# 抽样 M 次股价变化过程。
for i in range(self.M):
S = self.S_0
# 股价变化过程由 N 次对正态分布抽样构成。
for j in range(self.N):
S = S*(1+self.r*dt+self.sigma*dt**0.5*np.random.normal())
# 另一种离散化表示:
# S = S*math.e**((self.r-0.5*self.sigma*self.sigma)*dt+self.sigma*dt**0.5*np.random.normal())
self.call_price += max(0, S-self.K)/self.M
self.put_price += max(0, self.K-S)/self.M
self.call_price *= math.e**(-self.r*self.T)
self.put_price *= math.e**(-self.r*self.T)
return
考虑当无风险利率为0.05,股价波动率为0.2,初始股价为90,执行价格为100,执行时间为1年后的欧式期权。取 N = 400 , Δ t = 0.0025 N=400,\, \Delta t= 0.0025 N=400,Δt=0.0025, 进行 M = 40000 M=40000 M=40000次蒙卡模拟股价变化过程,并计算期权价格。
MC_obj = Monte_Carlo_European_option(0.05, 0.2, 90, 100, 1, 400, 40000)
MC_obj.MC_simulation()
print("欧式看涨期权价格:{0:.5f}".format(MC_obj.call_price))
print("欧式看跌期权价格:{0:.5f}".format(MC_obj.put_price))
# 解析解:“欧式看涨期权价格为:5.0912, 欧式看跌期权价格为:10.214” 。
欧式看涨期权价格:5.03626
欧式看跌期权价格:10.13694
上面我们使用的股价变化的离散化表示为:
S ( t + Δ t ) = S ( t ) ( 1 + r Δ t + σ ε Δ t ) . S(t+\Delta t) = S(t)(1+r\Delta t+\sigma\varepsilon \sqrt{\Delta t}) . S(t+Δt)=S(t)(1+rΔt+σεΔt).
但如果我们认为股价变化的“真实”过程为连续的几何布朗运动,则由
d ln S ( t ) = ( r − 1 2 σ 2 ) d t + σ d z , ln S ( t + Δ t ) − ln S ( t ) = ( r − 1 2 σ 2 ) Δ t + σ ε Δ t . d\ln{S(t)} = (r-\frac{1}{2}\sigma^2)dt+\sigma dz, \\ \ln{S(t+\Delta t)}-\ln{S(t)} = (r-\frac{1}{2}\sigma^2)\Delta t +\sigma\varepsilon \sqrt{\Delta t} . dlnS(t)=(r−21σ2)dt+σdz,lnS(t+Δt)−lnS(t)=(r−21σ2)Δt+σεΔt.
股价变化过程应该为:
S ( t + Δ t ) = S ( t ) e ( r − 1 2 σ 2 ) Δ t + σ ε Δ t . S(t+\Delta t) = S(t)e^{(r-\frac{1}{2}\sigma^2)\Delta t+\sigma\varepsilon\sqrt{\Delta t}}. S(t+Δt)=S(t)e(r−21σ2)Δt+σεΔt.
不过我们会看到当 N → ∞ , Δ t → 0 N\to \infty, \, \Delta t \to 0 N→∞,Δt→0时,按这两种离散化方式计算得出 S ( T ) 1 S(T)_1 S(T)1和 S ( T ) 2 S(T)_2 S(T)2满足同样的分布。
记
S ( T ) 1 = S 0 ∏ i = 1 N ( 1 + r Δ t + σ ε i Δ t ) , S ( T ) 2 = S 0 e ( r − 1 2 σ 2 ) Δ t N + σ Δ t ∑ i = 1 N ε i . S(T)_1 = S_0\prod_{i=1}^N(1+r\Delta t+\sigma\varepsilon_i\sqrt{\Delta t}),\\ S(T)_2 = S_0e^{(r-\frac{1}{2}\sigma^2)\Delta tN+\sigma\sqrt{\Delta t}\sum_{i=1}^N\varepsilon_i} . S(T)1=S0i=1∏N(1+rΔt+σεiΔt),S(T)2=S0e(r−21σ2)ΔtN+σΔt∑i=1Nεi.
考虑取对数后,
ln S ( T ) 1 = ln S 0 + ∑ i = 1 N ln ( 1 + r Δ t + σ ε i Δ t ) , ln S ( T ) 2 = ln S 0 + ( r − 1 2 σ 2 ) Δ t N + σ Δ t ∑ i = 1 N ε i . \ln{S(T)_1} = \ln{S_0}+\sum_{i=1}^N\ln{(1+r\Delta t+\sigma\varepsilon_i\sqrt{\Delta t})}, \\ \ln{S(T)_2} = \ln{S_0}+(r-\frac{1}{2}\sigma^2)\Delta t N+\sigma \sqrt{\Delta t}\sum_{i=1}^N\varepsilon_i . lnS(T)1=lnS0+i=1∑Nln(1+rΔt+σεiΔt),lnS(T)2=lnS0+(r−21σ2)ΔtN+σΔti=1∑Nεi.
将 ln S ( T ) 1 \ln{S(T)_1} lnS(T)1中对数部分展开,
ln S ( T ) 1 = ln S 0 + ∑ i = 1 N ( r Δ t + σ ε i ) Δ t − 1 2 ∑ i = 1 N ( r Δ t + σ ε i ) 2 Δ t + 1 3 ∑ i = 1 N ( r Δ t + σ ε i ) 3 ( Δ t ) 3 2 + . . . \ln{S(T)_1} = \ln{S_0}+\sum_{i=1}^N(r\sqrt{\Delta t}+\sigma\varepsilon_i)\sqrt{\Delta t}-\frac{1}{2}\sum_{i=1}^N (r\sqrt{\Delta t}+\sigma\varepsilon_i)^2\Delta t+\frac{1}{3}\sum_{i=1}^N(r\sqrt{\Delta t}+\sigma \varepsilon_i)^3(\Delta t)^{\frac{3}{2}}+ ... lnS(T)1=lnS0+i=1∑N(rΔt+σεi)Δt−21i=1∑N(rΔt+σεi)2Δt+31i=1∑N(rΔt+σεi)3(Δt)23+...
由于 r r r和 σ \sigma σ不变,忽略 Δ t 3 2 \Delta t^{\frac{3}{2}} Δt23项(当 N → ∞ N\to \infty N→∞时为0)后,
ln S ( T ) 1 = ln S 0 + r Δ t N + σ Δ t ∑ i = 1 N ε i − 1 2 σ 2 Δ t ∑ i = 1 N ε i 2 . \ln{S(T)_1} = \ln{S_0}+r\Delta tN+\sigma\sqrt{\Delta t}\sum_{i=1}^N\varepsilon_i-\frac{1}{2}\sigma^2\Delta t\sum_{i=1}^N \varepsilon_i^2 . lnS(T)1=lnS0+rΔtN+σΔti=1∑Nεi−21σ2Δti=1∑Nεi2.
当 N → ∞ , N Δ t = T N\to \infty,\; N\Delta t = T N→∞,NΔt=T, 1 N ∑ i = 1 N ε i 2 = 1 , ∑ i = 1 N ε i ∼ N ε \frac{1}{N}\sum_{i=1}^N\varepsilon_i^2 = 1,\; \sum_{i=1}^{N}\varepsilon_i\sim \sqrt{N}\varepsilon N1∑i=1Nεi2=1,∑i=1Nεi∼Nε,所以
ln S ( T ) 1 ∼ ln S 0 + ( r − 1 2 σ 2 ) T + σ T ε , ln S ( T ) 1 ∼ N ( ln S 0 + ( r − 1 2 σ 2 ) T , σ T ) . \ln{S(T)_1} \sim \ln{S_0}+(r-\frac{1}{2}\sigma^2)T+\sigma\sqrt{T}\varepsilon ,\\ \ln{S(T)_1} \sim \mathcal N(\ln{S_0}+(r-\frac{1}{2}\sigma^2)T, \; \sigma\sqrt{T}) . lnS(T)1∼lnS0+(r−21σ2)T+σTε,lnS(T)1∼N(lnS0+(r−21σ2)T,σT).
而且易见 ln S ( T ) 2 ∼ N ( ln S 0 + ( r − 1 2 σ 2 ) T , σ T ) \ln{S(T)_2} \sim \mathcal N(\ln{S_0}+(r-\frac{1}{2}\sigma^2)T, \; \sigma\sqrt{T}) lnS(T)2∼N(lnS0+(r−21σ2)T,σT)。
所以当 N N N趋于无穷大时,两种离散化方式抽样所得的 S ( T ) S(T) S(T)的分布是相同的,而且就为股价服从连续的几何布朗运动时的 S ( T ) S(T) S(T)分布。
蒙卡模拟计算的期权价格为 M M M次股价变化过程抽样结果对应期权价格的平均值并贴现。如果每一次股价抽样所得的期权价格的标准差为 ω \omega ω,则 M M M次蒙卡模拟计算的期权价格的标准差为:
ω M . \frac{\omega}{\sqrt{M}}. Mω.
以欧式看涨期权为例,
ω 2 = ∫ 0 + ∞ f ( S T ) e − 2 r T [ max ( S T − K , 0 ) ] 2 d S T − c 2 . \omega^2 = \int_{0}^{+\infty}f(S_T)e^{-2rT}[\max{(S_T-K, 0)}]^2 dS_T - c^2 . ω2=∫0+∞f(ST)e−2rT[max(ST−K,0)]2dST−c2.
其中 f ( S T ) f(S_T) f(ST)为执行时刻股价分布的概率密度函数, K K K为期权执行价格, c c c为欧式看涨期权的价格。下面略去计算过程,我们有
c = S 0 N ( d 1 ) − K e − r T N ( d 2 ) , d 1 = ln S 0 K + ( r + 1 2 σ 2 ) T σ T , d 2 = d 1 − σ T , f ( S T ) = 1 S T 1 2 π σ 0 e − ( ln S T − μ 0 ) 2 2 σ 0 2 , σ 0 = σ T , μ 0 = ln S 0 + ( r − 1 2 σ 2 ) T . c = S_0N(d_1)-Ke^{-rT}N(d_2), \;\; d_1 = \frac{\ln{\frac{S_0}{K}}+(r+\frac{1}{2}\sigma^2)T}{\sigma\sqrt{T}}, \;\; d_2 = d_1-\sigma\sqrt{T},\\ f(S_T) = \frac{1}{S_T}\frac{1}{\sqrt{2\pi}\sigma_0}e^{-\frac{(\ln{S_T}-\mu_0)^2}{2\sigma_0^2}}, \;\;\sigma_0 = \sigma\sqrt{T},\;\;\mu_0 = \ln{S_0}+(r-\frac{1}{2}\sigma^2)T. c=S0N(d1)−Ke−rTN(d2),d1=σTlnKS0+(r+21σ2)T,d2=d1−σT,f(ST)=ST12πσ01e−2σ02(lnST−μ0)2,σ0=σT,μ0=lnS0+(r−21σ2)T.
代入 ω 2 \omega^2 ω2的表达式,计算得:
ω 2 = K 2 e − 2 r T N ( d 2 ) − 2 K S 0 e − r T N ( d 1 ) + S 0 2 e σ 2 T N ( ln S 0 K + ( r + 3 2 σ 2 ) T σ T ) − [ S 0 N ( d 1 ) − K e − r T N ( d 2 ) ] 2 . \omega^2 = K^2e^{-2rT}N(d_2)-2KS_0e^{-rT}N(d_1)+S_0^2e^{\sigma^2T}N(\frac{\ln{\frac{S_0}{K}}+(r+\frac{3}{2}\sigma^2)T}{\sigma\sqrt{T}})-[S_0N(d_1)-Ke^{-rT}N(d_2)]^2 . ω2=K2e−2rTN(d2)−2KS0e−rTN(d1)+S02eσ2TN(σTlnKS0+(r+23σ2)T)−[S0N(d1)−Ke−rTN(d2)]2.
考虑上面计算示例中,无风险利率为0.05,股价波动率为0.2,初始股价为90,执行价格为100,执行时间为1年后的欧式看涨期权。代入相关参数,得
ω = 10.162. \omega = 10.162 . ω=10.162.
我们抽样股价路径 M = 40000 M=40000 M=40000次后,计算出的欧式看涨期权价格的标准差为
ω M = 10.162 200 = 0.05081. \frac{\omega}{\sqrt{M}} = \frac{10.162}{200} = 0.05081 . Mω=20010.162=0.05081.
进行蒙特卡罗模拟抽样计算期权价格时,误差的来源有两方面。一方面是上面我们计算的和股价变化路径抽样数量 M M M相关的误差,另一方面是我们在对股票价格变化过程离散化时产生的误差(相对于连续变化时股价最终分布的差别)。由6.5.1中讨论知当离散化点数 N N N趋于无穷大时,我们对股价变化过程的抽样模拟将和股价按连续几何布朗运动的结果相同。
下面我们定量地测试选取不同 N N N时,期权价格计算结果会如何变化。这里我们使用和示例中一样的参数,但是取 M M M为36万,这样会使得 ω / M ≈ 0.02 \omega/\sqrt{M} \approx 0.02 ω/M≈0.02,即使与抽样股价路径数量相关的误差很小。得下图,
其中每个数值点为按上述蒙卡抽样计算期权价格25次后的平均值,数值点上的置信区间为 [ − σ , σ ] [-\sigma, \sigma] [−σ,σ]。由于我们可以使用欧式看涨期权解析解计算得期权价格应该为5.0912,通过上图可见,当我们选取 N > 50 N>50 N>50之后,蒙卡模拟计算所得期权价格已经比较接近解析解结果了。
# Appendix.
# Calculate call prices vs Ns.
k = 25
Ns = []
prices = []
for N in [5, 10, 20, 50, 100]:
for _ in range(k):
Ns.append(N)
MC_obj = Monte_Carlo_European_option(0.05, 0.2, 90, 100, 1, N, 360000)
MC_obj.MC_simulation()
prices.append(MC_obj.call_price)
# Make plot.
import matplotlib.pyplot as plt
import matplotlib.lines as lines
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
k = 25
X = [5, 10, 20, 50, 100]
Y = []
errors = []
for i in range(5):
Y.append(np.average(prices[k*i:k*(i+1)]))
errors.append(np.std(prices[k*i:k*(i+1)]))
ax1.plot(X, Y, color="yellow", marker="s", linewidth=0.9, ms=5, mfc="blue", mec="black")
ax1.errorbar(X, Y, errors, ecolor="red", capsize=4, capthick=0.8, elinewidth=0.8)
# line1 = lines.Line2D([5, 100], [5.0912, 5.0912], lw=1, color="black", transform=ax1.transAxes)
# ax1.lines.append(line1)
ax1.axis((0, 110, 4.9, 5.15))
ax1.set_xlabel("stock price change steps")
ax1.set_ylabel("European call option price")
ax1.set_title("European Call Option Prices VS Dissection Steps")
ax1.grid(True)
fig.savefig("6_1.png", dpi=400)
fig.show()
参考资料: