金融数学课程论文
一、二叉树模型中的参数估计
1.1 二叉树参数估计算法原理
想要预测股价二叉树,在知道初始值的前提下,还需要知道模型中的的u 和d ,但对于一支只知道对应于日期的股票价格,我们应该进行怎样的数据处理呢?下面通过实证数据对二叉树模型中的参数进行估计。 原理:Hull-White 算法
令2
1
=
p ,并用如下公式计算u 和d: t d u ii t
d
u i ?=-?+=+σμ2)(12
)
( 我们假设:
k
k k S X S S X S 11011++==,
这里k X 是独立的伯努利随机变量,2
1
]/Pr[]/[Pr 11=====--d S S u S S k k k k 则我们可以得出t u ?和t ?2σ的合理估计值为:
∑∑=-=-=-=n
k k k n k k S S n X n U 1
11)1/(1)1(1
其中:
])1/([111
2212
∑=----=n
k k k U n S S n s
U 和2s 是来自实际市场数据n S S S S ,,、、Λ210的样本均值和样本方差,我们可以
得出u和σ的估计值为:
t
s
t
U
u
?
≈
?
≈
σ
则:
t
t
d
t
t
u
?
-
?
+
=
?
+
?
+
=
σ
μ
σ
μ
1
1
1.2举例应用
我选用中国农业银行2013年的股票价格,具体数据见附件1.
由表可知,001986
.0
1
001986
.1=
-
=
U,010568
.0
=
s,这个二叉树中所用的t?和与数据的t?相同,公式u和d可以简化成:
56
.
55
0.991418
1
1.012554
1
=
=
-
+
=
=
+
+
=
S
s
U
d
s
U
u
做4期二叉树图为:
这里的t?是一天,我们通过选择更大的时间间隔,令7
=
?t,即以一周为一个时间段,则有:
56
.
55
0.977293
)7
(
)7(
1
1.033215
)7
(
)7(
1
=
=
-
+
=
=
+
+
=
S
s
U
d
s
U
u
4期二叉树图变为:
再15=?t 令即以半个月为一个时间段,则有:
1.07072)15()15(1=++=s U u
988858.0)15()15(1=-+=s U d
56.550=S
4期二叉树图又变为:
由于该题的t ?可以改变,时间间隔越长,股价“分叉”得更快。
二、 几何布朗运动估计与模拟
2.1几何布朗运动参数估计原理
令)(t S 代表某股票在t 时刻的价格,由以下公式给出S 的模型。 SdB Sdt dS σμ+=
其中,σμ、是常量,B 服从布朗运动,而该方程的解就是几何布朗运动。 即:
])2/(ex p[20t B S S t t σμσ-+=
其中,t B 是均值为0,方差为t 的正态随机变量,由此得到的就是股价的几何布朗运动模型。我们将采用修正的股价模型对欧式看涨期权进行定价,在此之前,要对股价模型进行参数估计,即波动率σ和漂移率μ。
假设我们得到了在一段较长时间[0, T]内的股价数据记录,这段时间由n 个长度相等的子区间t ?组成,再假设我们知道每个子区间末的股价,将股价表示为:
S i :第i 个子区间末的股价 样本观测值为n+1个; 令U 表示均值,则:
∑=-=n
i i
U
n U 1
1
样本方差用S 2表示,则:
2
1
1
2)()
1(∑=---=n
i i
U U
n S
而U 的观测值的均值为t ?-)2/(2σμ,方差为t ?2σ。 即:
t U ?-=)2/(2σμ
t S ?=22σ 最后算的参数μ和σ为:
t
S U ?+=2
/2μ及t S ?=/σ
而对于t B ,则需要随机产生一系列标准正态分布,通过累加处理获得计算所需要的值。
也可运用对数正态分布模型,即:
2(/2)0T W T
T S S e
σμσ+-=
其中,T W 是一个均值为0,方差为T 的随机正态分布变量,T W 的获取与t B 相仿。
2.2举例应用
我选用中国农业银行2013年的股票价格,具体数据见附件2.
计算股价,先随机生成均值为0,方差为n t ?的正态分布随机数,而后进行处理生成预测值,结果如下:
而后将预测值与实际值进行比较,得到:
根据图可直观地看出,预测值的波动率比较大,整个曲线趋势很不平稳,因此需要进行修正;于是,再随机生成均值为0,方差为1的标准正态分布随机数,而后进行处理生成预测值,结果如下:
而后将预测值与实际值进行比较,得到:
由此可以看出,拟合程度还是很好的,可以用来预测未来几期的股票价格。预测未来两个月的股价,结果如下:
三、B-S 模型及多期二叉树的期权定价
3.1.B-S 期权定价公式:
假设有一股票现价为0S ,V 是看涨期权的价格,
无风险利率
股价漂移率股价波动率到期时间
执行价=====r X μσT
看涨期权V 值可表示为:)()(210d N Xe d N S V rT --= 其中:
2/2
2
1
()[]
2
x x
N x P Z x e dx
d
T
π
σ
-
-∞
=≤=
=
?
21
d d T
σ
=-
对于欧式看跌期权的价格P,可表示为:
012
()()
rT
P S N d Xe N d
-
=--+-;
3.2举例应用
我选用了2013年11月16日的执行价,而后通过运用BS公式及多期二叉树计算期权价格的方式,将实际值与两方法的预测值进行比较,而后进行分析,详细数据见附件3。
计算结果数据:
再将预测所得数据与实际值进行拟合比较,得到如下图:
从该图主观地看出,三种期权的价格的趋势基本上一致,拟合程度也比较高,
但对来说,BS 的拟合程度更好一点。这样相对来说主观了一点,接着对数据进行再一次的处理分析:
最后算的,多期二叉树的预测误差的方差为:0.162756979,而几何布朗运动的预测误差的方差为:0.15752995 ,由此也可以得出,几何布朗运动拟合程度更好一些。
四、对冲
4.1做题思路
计算对冲,即计算?值,1()N d ?=,而201d τσ
=
,对一
只股票,在一年的时间里,假设我们每周进行一次对冲,那每周相应的对冲值又该如何计算呢?
在解这个题目时,最重要的计算出0S 的值,在第一周时,0S 为初始价,但到了第二周,0S 有所变动,它的值为:20exp((/2))T T S S W T μμσ=+-,而对于τ,其值等于到期时间周数与总周期数的比值。对于T W ,先产生随机数,而后再将它转换为正态分布随机数。
4.2举例应用
对于附件2里的数据,T=0.51506849,S0=55.56,X=50,sigma=0.20203053, miu=0.724348005,r=0.04, 假设卖出1000股股票,在这样的情况下,实现对冲为:
课程小结:
对于金融数学这门课程,一个多星期的计算机操作,让我惊叹。突然间才发现,这是一门综合性特别强的学科,才明白自己在某些知识点的掌握上拿捏得不是很好,所以做起来还是有一定的挑战性的,可能在学习理论知识的时候,这样的缺陷不是暴露的特别明显。一开始决定编写C语言,是因为自己电脑上安装了这一软件,如果赶不上进度自己可以补一下,最后才发现自己这一举动是那么的正确,因为自己在C这方面学的不扎实,下课后,我还不得不窝在电脑前一次次修改程序,不过看到自己的程序可以完美实现的时候,真的真的特别开心,“废寝忘食”的程序员生活,稍稍体验了一把,才可以懂得他们为什么会有很大的情绪波动。在做这个课程设计的时候,最麻烦的是计算积分与产生正态分布随机变量,这个涉及到了数值计算方法和概率统计的知识,自然,C语言是基础,在计算积分的时候,我运用了复合梯形公式,但在n的取值上遇到了一点问题,不能很好地把握它的取值。在后面进行分析比较时,我运用了统计预测与决策的相关知识。总的来说,这一个星期真的过的特别充实,懂得了时间的概念。但是时间比较紧张,我们要做的内容又比较多,做的还是不够精细。
附录
源程序如下:
欧式看涨期权:
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define N 200
main()
{ int n,k,j;
float s0,i,X,u,d,r,q,p,t,w,v;
float a[N][N+1];
printf("请输入初始价s0:\n");
scanf("%f",&s0);
printf("请输入每期利率i:\n");
scanf("%f",&i);
printf("请输入增长因子u:\n");
scanf("%f",&u);
printf("请输入下降因子d:\n");
scanf("%f",&d);
printf("请输入执行价X:\n");
scanf("%f",&X);
printf("请输入期数n:\n");
scanf("%d",&n);
r=exp(-i);
q=(1/r-d)/(u-d);
p=1-q;
printf("股价二叉树为:\n");
for(k=0;k<=n;k++)
{
for(j=1;j<=k+1;j++)
{
w=pow(u,j-1);
v=pow(d,k-j+1);
a[k][j]=s0*w*v;
printf("%.6lf ",a[k][j]);
}
printf("\n");
}
printf("期权二叉树为:\n");
{
for(j=n+1;j>=1;j--)
{
w=pow(u,j-1);
v=pow(d,n-j+1);
a[k][j]=s0*w*v;
if(a[n][j]>X)
a[n][j]=a[n][j]-X;
else
a[n][j]=0;
printf("%f ",a[n][j]);
}
printf("\n");
for(k=n-1;k>=0;k--)
{
for(j=k+1;j>=1;j--)
{
a[k][j]=r*(p*a[k+1][j]+q*a[k+1][j+1]);
printf("%.6lf ",a[k][j]);
}
printf("\n");
}
printf("欧式看涨期权定价为: ");
printf("%f \n",a[0][1]);
}
}
欧式看跌期权:
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define N 200
main()
{ int n,k,j;
float s0,i,X,u,d,r,q,p,t, w,v;
float a[N][N+1];
printf("请输入初始价s0:\n");
scanf("%f",&s0);
printf("请输入每期利率i:\n");
scanf("%f",&i);
printf("请输入增长因子u:\n");
scanf("%f",&u);
printf("请输入下降因子d:\n");
scanf("%f",&d);
printf("请输入执行价X:\n");
scanf("%f",&X);
printf("请输入期数n:\n");
scanf("%d",&n);
r=exp(-i);
q=(1/r-d)/(u-d);
p=1-q;
printf("股价二叉树为:\n");
for(k=0;k<=n;k++)
{
for(j=1;j<=k+1;j++)
{
w=pow(u,j-1);
v=pow(d,k-j+1);
a[k][j]=s0*w*v;
printf("%f ",a[k][j]);
}
printf("\n");
}
printf("期权二叉树为:\n");
{
for(j=n+1;j>=1;j--)
{
w=pow(u,j-1);
v=pow(d,n-j+1);
a[k][j]=s0*w*v;
if(a[n][j] a[n][j]=X-a[n][j]; else a[n][j]=0; printf("%f ",a[n][j]); } printf("\n"); for(k=n-1;k>=0;k--) { for(j=k+1;j>=1;j--) { a[k][j]=r*(p*a[k+1][j]+q*a[k+1][j+1]); printf("%f ",a[k][j]); } printf("\n"); } printf("欧式看跌期权定价为: "); printf("%f \n",a[0][1]); } } 欧式向上敲出障碍看跌期权: #include "stdio.h" #include "stdlib.h" #include "math.h" #define N 200 main() { int n,k,j; float s0,i,X,u,d,r,q,p,t,w,v,Q; float a[N][N+1]; printf("请输入初始价s0:\n"); scanf("%f",&s0); printf("请输入每期利率i:\n"); scanf("%f",&i); printf("请输入增长因子u:\n"); scanf("%f",&u); printf("请输入下降因子d:\n"); scanf("%f",&d); printf("请输入执行价X:\n"); scanf("%f",&X); printf("请输入期数n:\n"); scanf("%d",&n); printf("请输入向上敲出障碍期权Q:\n"); scanf("%f",&Q); r=exp(-i); q=(1/r-d)/(u-d); p=1-q; printf("股价二叉树为:\n"); for(k=0;k<=n;k++) { for(j=1;j<=k+1;j++) { w=pow(u,j-1); v=pow(d,k-j+1); a[k][j]=s0*w*v; printf("%f ",a[k][j]); } printf("\n"); } printf("期权二叉树为:\n"); { for(j=n+1;j>=1;j--) { w=pow(u,j-1); v=pow(d,n-j+1); a[k][j]=s0*w*v; if(a[n][j] a[n][j]=X-a[n][j]; else a[n][j]=0; printf("%f ",a[n][j]); } printf("\n"); for(k=n-1;k>=0;k--) { for(j=k+1;j>=1;j--) { if(a[k][j] a[k][j]=r*(p*a[k+1][j]+q*a[k+1][j+1]); else a[k][j]=0; printf("%f ",a[k][j]); } printf("\n"); } printf("欧式向上敲出障碍看跌期权定价为: "); printf("%f \n",a[0][1]); } } 欧式向上敲出障碍看涨期权: #include "stdio.h" #include "stdlib.h" #include "math.h" #define N 200 main() { int n,k,j; float s0,i,X,u,d,r,q,p,t,w,v,Q; float a[N][N+1]; printf("请输入初始价s0:\n"); scanf("%f",&s0); printf("请输入每期利率i:\n"); scanf("%f",&i); printf("请输入增长因子u:\n"); scanf("%f",&u); printf("请输入下降因子d:\n"); scanf("%f",&d); printf("请输入执行价X:\n"); scanf("%f",&X); printf("请输入期数n:\n"); scanf("%d",&n); printf("请输入向上敲出障碍期权Q:\n"); scanf("%f",&Q); r=exp(-i); q=(1/r-d)/(u-d); p=1-q; printf("股价二叉树为:\n"); for(k=0;k<=n;k++) { for(j=1;j<=k+1;j++) { w=pow(u,j-1); v=pow(d,k-j+1); a[k][j]=s0*w*v; printf("%f ",a[k][j]); } printf("\n"); } printf("期权二叉树为:\n"); { for(j=n+1;j>=1;j--) { w=pow(u,j-1); v=pow(d,n-j+1); a[k][j]=s0*w*v; if(a[n][j]>X&&a[n][j] a[n][j]=a[n][j]-X; else a[n][j]=0; printf("%f ",a[n][j]); } printf("\n"); for(k=n-1;k>=0;k--) { for(j=k+1;j>=1;j--) { if(a[k][j] a[k][j]=r*(p*a[k+1][j]+q*a[k+1][j+1]); else a[k][j]=0; printf("%f ",a[k][j]); } printf("\n"); } printf("欧式向上敲出障碍看涨期权定价为: "); printf("%f \n",a[0][1]); } } 欧式向下敲出障碍看跌期权: #include "stdio.h" #include "stdlib.h" #include "math.h" #define N 200 main() { int n,k,j; float s0,i,X,u,d,r,q,p,t,w,v,Q; float a[N][N+1]; printf("请输入初始价s0:\n"); scanf("%f",&s0); printf("请输入每期利率i:\n"); scanf("%f",&i); printf("请输入增长因子u:\n"); scanf("%f",&u); printf("请输入下降因子d:\n"); scanf("%f",&d); printf("请输入执行价X:\n"); printf("请输入期数n:\n"); scanf("%d",&n); printf("请输入向下敲出障碍期权Q:\n"); scanf("%f",&Q); r=exp(-i); q=(1/r-d)/(u-d); p=1-q; printf("股价二叉树为:\n"); for(k=0;k<=n;k++) { for(j=1;j<=k+1;j++) { w=pow(u,j-1); v=pow(d,k-j+1); a[k][j]=s0*w*v; printf("%f ",a[k][j]); } printf("\n"); } printf("期权二叉树为:\n"); { for(j=n+1;j>=1;j--) { w=pow(u,j-1); v=pow(d,n-j+1); a[k][j]=s0*w*v; if(a[n][j] a[n][j]=X-a[n][j]; else a[n][j]=0; printf("%f ",a[n][j]); } printf("\n"); for(k=n-1;k>=0;k--) { for(j=k+1;j>=1;j--) { if(a[k][j]>Q) a[k][j]=r*(p*a[k+1][j]+q*a[k+1][j+1]); else a[k][j]=0; printf("%f ",a[k][j]); } } printf("欧式向下敲出障碍看跌期权定价为: "); printf("%f \n",a[0][1]); } } 欧式向下敲出障碍看涨期权: #include "stdio.h" #include "stdlib.h" #include "math.h" #define N 200 main() { int n,k,j; float s0,i,X,u,d,r,q,p,t,w,v,Q; float a[N][N+1]; printf("请输入初始价s0:\n"); scanf("%f",&s0); printf("请输入每期利率i:\n"); scanf("%f",&i); printf("请输入增长因子u:\n"); scanf("%f",&u); printf("请输入下降因子d:\n"); scanf("%f",&d); printf("请输入执行价X:\n"); scanf("%f",&X); printf("请输入期数n:\n"); scanf("%d",&n); printf("请输入向下敲出障碍期权Q:\n"); scanf("%f",&Q); r=exp(-i); q=(1/r-d)/(u-d); p=1-q; printf("股价二叉树为:\n"); for(k=0;k<=n;k++) { for(j=1;j<=k+1;j++) { w=pow(u,j-1); v=pow(d,k-j+1); a[k][j]=s0*w*v; printf("%f ",a[k][j]); } printf("\n"); } printf("期权二叉树为:\n"); { for(j=n+1;j>=1;j--) { w=pow(u,j-1); v=pow(d,n-j+1); a[k][j]=s0*w*v; if(a[n][j]>X&&a[n][j]>Q) a[n][j]=a[n][j]-X; else a[n][j]=0; printf("%f ",a[n][j]); } printf("\n"); for(k=n-1;k>=0;k--) { for(j=k+1;j>=1;j--) { if(a[k][j]>Q) a[k][j]=r*(p*a[k+1][j]+q*a[k+1][j+1]); else a[k][j]=0; printf("%f ",a[k][j]); } printf("\n"); } printf("欧式向下敲出障碍看涨期权定价为: "); printf("%f \n",a[0][1]); } } 美式看跌期权: #include "stdio.h" #include "stdlib.h" #include "math.h" #define N 100 main() { int n,k,j; float s0,i,X,u,d,r,q,p,t,w,v,T; float a[N][N+1]; printf("请输入初始价s0:\n"); scanf("%f",&s0); printf("请输入每期利率i:\n"); scanf("%f",&i); printf("请输入增长因子u:\n"); scanf("%f",&u); printf("请输入下降因子d:\n"); scanf("%f",&d); printf("请输入执行价X:\n"); scanf("%f",&X); printf("请输入期数n:\n"); scanf("%d",&n); r=exp(-i); q=(1/r-d)/(u-d); p=1-q; printf("股价二叉树为:\n"); for(k=0;k<=n;k++) { for(j=1;j<=k+1;j++) { w=pow(u,j-1); v=pow(d,k-j+1); a[k][j]=s0*w*v; printf("%f ",a[k][j]); } printf("\n"); } printf("期权二叉树为:\n"); { for(j=n+1;j>=1;j--) { w=pow(u,j-1); v=pow(d,n-j+1); a[k][j]=s0*w*v; if(a[n][j] a[n][j]=X-a[n][j]; else a[n][j]=0; printf("%f ",a[n][j]); } printf("\n"); for(k=n-1;k>=0;k--) { for(j=k+1;j>=1;j--) { T=X-a[k][j]; a[k][j]=r*(p*a[k+1][j]+q*a[k+1][j+1]);