You are on page 1of 8

【基本无害】代码分享-几何布朗运动的数值模拟 | 两种不同思


Original seaswallow 量化金融科技前沿 Today

Ad
基本无害的量化金融学(专硕教材)
作者:余颖丰
当当

Ad
Python金融数据挖掘
作者:主编:钟雪灵 侯?P 张红霞 副主编: 陈
当当

如果没有几何布朗运动(Geometric Brownian Motion)就不会有布莱克-斯


科尔斯-莫顿(BSM)欧式期权定价公式。
因此,金融数学(或者金融工程学或者量化金融学)的基础知识点之一就是要
求学生熟练掌握几何布朗运动的所有性质。
在BSM欧式期权定价公式中,标的物--也就是股票价格是用几何布朗运动来描
述的,这也就是为何我们说如果没有几何布朗运动就不会有布莱克-斯科尔斯-莫
顿(BSM)欧式期权定价公式。
几何布朗运动较好的刻画了股票的以下特性:
◾ 几何布朗运动刻画的股票价格都是正数,不会出现负数的情形,这和现实中
的股票价格的属性一致
◾ 几何布朗运动的走势有时会出现“疯涨”或者“疯跌”情形,这种特性和现实中
的股票价格的特性相符合
◾ 将股票价格设定为几何布朗运动,并将股票价格作为衍生品的标的物,进而
研究衍生品的定价,如此处理,较容易计算出衍生品的价格
当然,用几何布朗运动来刻画股票价格也是有明显的缺陷,比如:
◾ 几何布朗运动假设波动率(volatility)是一个常数,而在现实世界中,股
票价格的波动率并非常数。【这也就是为何后来2003年诺贝尔经济学奖得
主恩格尔教授一直倡导的ARCH模型的原因,ARCH家族模型一直将波动率
作为一个动态变化过程来研究,具体可见:现代金融学的开端要从诺奖得主
恩格尔说起】
◾ 股票价格市场有跳跃(jump)现象,而几何布朗运动无法刻画。
今天我们来演示一下几何布朗运动的数值表达式和计算机模拟实现,我们给出
了Matlab、R和Python的代码实现。

一般而言我们有两种方法,第一种方法是利用的 积分结果,即

(公式-1)。
第二种方法是直接利用随机微分方程

。但我们不能直接用,我们都要做一些简单处理。
先说第一种方法,我们不妨假设

于是公式-1可以写为:

,因为我们知道

,于是利用迭代方法可以得到 的结果。

下面说说第二种方法,我们不妨假设

于是

,其中
下面我们首先演示一下Malab代码的实现

clear
close all
tic
S0=10; %Initial Stock price
T=10;
N_time=10e3;
dt=T/N_time;
N_sim=10e2;
t=[0.0:dt:T];
mu=0.05;
vol=0.25;
S=zeros(N_sim,N_time+1);
S(:,1)=S0*ones(N_sim,1);

subplot(1,2,1)
hold on

for j=1:N_sim
for i=1:N_time
         z=randn(1,1);
        S(j,i+1)=S(j,i)*exp((mu-0.5*(vol^2))*dt+...
         vol*sqrt(dt)*z);
end
plot(t,S(j, );
 end
mu_s=S0*exp(mu*t);
vol_s=S0*exp(mu*t).*sqrt(exp((vol^2)*t)-1);
plot(t,mu_s,’k’);
plot(t,mu_s+vol_s,’.k’);
plot(t,mu_s-vol_s,’.k’);
xlabel(‘time’)
ylabel(‘S_{t}’)
title(‘Simulated geometric Brownian Montion’)
grid on

nBins=100;
subplot(1,2,2)
hold on
grid on
histfit(S(:,end),nBins, ‘lognormal’);
set(gca, ‘xdir’, ‘reverse’)
camroll(270)
xlabel(‘S_{T}’)
ylabel(‘frquencies’)
title(‘The histogram of S_{T} with LogNomral fit’)
figure
sample_mean_S=mean(S(:,1:end));
sample_std_S=std(S(:,1:end));

plot(t,sample_mean_S,’.k’);
hold on
plot(t,mu_s);

plot(t,sample_mean_S+sample_std_S,’+r’);
plot(t,sample_mean_S-sample_std_S,’+r’);

plot(t,mu_s+vol_s,’.-k’);
plot(t,mu_s-vol_s,’.-k’);

grid on
xlabel(‘Time’)
ylabel(‘S_{t}’)
legend(‘Simluated sample mean of S_{t}^{i}’,...
    ‘Theoretical mean of S_{t}’,...
    ‘Simulated sample +std’,’Simulated sample -std’,...
    ‘Theoretical +std’, ‘Theoretical -std’)
title(‘Simulated sample moments vs theoretical momnets’)
toc

【图1几何布朗运动的模拟轨迹图与其对应的直方图分布】

图1模拟了1000次几何布朗运动从零时刻到T=10

的走势轨迹图,我们取时间间隔 ,在左图中,我们还分别绘制了几

何布朗运动的理论均值 和正负一个理论标准差,几何布朗运动的一个

理论标准差为 。右图绘制了模拟1000次路径后,

样本 的直方图,因为我们知道
满足对数正态分布,使用了Matlab自带的“histfit”命令,让其将样本分布拟合对数正态分
布,我们得到了一条非常完美的拟合曲线,从可视化角度我们认可验证,确实满足对数
正态分布。
为了进一步验证我们模拟的结果和理论结果一致,我们比较了样本矩和理论矩的关系,
具体见图2。我们首先画出了样本随时间变化的均值,然后让其和理论均值结果比较,我
们可以发现,二者结果非常接近几乎重合。然后我们绘制了样本的一个正负标准差,
用“+”表示,我们让其和它们的理论结果进行比较,即图上的两条光滑曲线,我们从图上
直观的可以看出,样本标准差几乎和理论结果相差无几,由此印证了我们的结论,即:
样本矩和理论矩结果一致。

【图2几何布朗运动的样本和理论矩结果比较】

下面我们讨论第二种方法,我们用R语言同时实现了第一种和第二种方法,并比较了结
果。可以发现,结果完全一致。

下面我们给出一种方法的R语言的代码

mu<-0.3
sigma<-0.9
T0 <- 1
set.seed (123)

nn <-252
simulations.total <- 400
maturity <- T0

dt <- maturity/(nn+1)
timeline <- seq(0,maturity, dt)

f <- matrix(r0,(nn+2),simulations.total)

for(i in 2:(nn+2)){
  for(j in 1:simulations.total){
       f[i,j]<-  f[i -1,j]*exp((mu-0.5*sigma^2)*dt + sigma*rnorm(1)*sqrt(dt))
    }
}

plot(timeline,f[,1], ylim=range(f,thetaQ), type="l", col="mediumorchid2")
for(j in 2:simulations.total){
          lines(timeline,f[,j], col=colors()[floor(runif(1,1,657))] )
}

title(main="Simulation of GMB", col.main="red", font.main=4)

下面我们给出第二种方法的代码

mu<-0.3
sigma<-0.9
T0 <- 1
set.seed (123)

nn <-252
simulations.total <- 400
maturity <- T0

dt <- maturity/(nn+1)
timeline <- seq(0,maturity, dt)

f <- matrix(r0,(nn+2),simulations.total)

for(i in 2:(nn+2)){
  for(j in 1:simulations.total){
          f[i,j]<-  f[i -1,j]*(1+mu*dt + sigma*rnorm(1)*sqrt(dt))
    }
}

plot(timeline,f[,1], ylim=range(f,thetaQ), type="l", col="mediumorchid2")
for(j in 2:simulations.total){
           lines(timeline,f[,j], col=colors()[floor(runif(1,1,657))] )
}
title(main="Simulation of GMB", col.main="red", font.main=4)

【图3 两种模拟方法的显示结果】
最后我们还给出Python代码的实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

mu=1
n=50
dt=0.1
x0=100
x=pd.DataFrame()
np.random.seed(1)

for sigma in np.arange(0.8,2,0.2):


step=np.exp((mu-sigma**2/2)*dt)*np.exp(sigma*np.random.nor-
mal(0,np.sqrt(dt),(1,n)))
temp=pd.DataFrame(x0*step.cumprod())
x=pd.concat([x,temp],axis=1)

x.columns=np.arange(0.8,2,0.2)
plt.plot(x)
plt.legend(x.columns)
plt.xlabel('t')
plt.ylabel('X')
plt.title('Realizations of Geometric Brownian Motion with different vari-
ances\n mu=1')
plt.show()
喜欢此内容的人还喜欢

2020对冲基金亿万富翁榜单出炉!老爷子又是第一
2020对冲基金亿万富翁榜单出炉!老爷子又是第一
量化投资与机器学习

见字如面!34家量化私募『牛』年寄语
见字如面!34家量化私募『牛』年寄语
量化投资与机器学习

CFETS DATA|新版债券估值手册、利率互换估值手册抢“鲜”看
CFETS DATA|新版债券估值手册、利率互换估值手册抢“鲜
CfetsOnline发布

You might also like