几何布朗运动;股价模拟
Geometric Brownian Motion; Simulation of Stock Price
我用 C++ 编写了一个 GBM 函数,我相信当我以 100 的初始价格开始时,我得到的股票价格范围太多,输出可能来自 [50,400]。我不确定我的代码做错了什么,我猜我播种随机标准正态数的方式有问题。请看一下函数,如果有什么需要修改或更改的,请告诉我。
函数如下:
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0){
double dt = T/N;
std::vector<double> Z;
std::vector<double> S;
S.push_back(S0);
std::mt19937 e2(time(0));
std::normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
Z.push_back(dist(e2));
}
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < M; i++){
S.push_back(S[i-1] * drift * exp(vol*Z[i]));
}
return S;
}
这里是 main.cpp 使用上述功能的文件:
#include <iostream>
#include "LSM.h"
#include <cmath>
#include <ctime>
#include <Eigen/Core>
#include <Eigen/SVD>
#include <iostream>
#include <vector>
#include <random>
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0);
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double K = 100.0; // Strike price
const double S0 = 100.0; // Initial stock price
const int M = 10000; // Number of paths
const int R = 2; // Choice of basis for Laguerre polynomial
//LSM Option_value(r,q,sigma,T,N,K,S0,M,R);
std::vector<double> s = GBM(M,N,T,r,q,sigma,S0);
for(int i = 0; i < M; i++){
std::cout << s[i] << std::endl;
}
return 0;
}
初始股价为 100 的典型输出如下:
153.5093
132.0190
96.2550
106.5196
58.8447
135.3935
107.1194
101.2022
134.2812
82.2146
87.9162
74.9333
88.9137
207.5150
123.7893
95.8526
120.0831
96.3990
103.3806
113.8258
100.6409
92.0724
81.1704
121.9925
114.3798
117.8366
86.1070
74.4885
82.6013
78.0202
97.0586
119.7626
89.0520
72.2328
92.1998
84.7180
138.9160
91.0091
105.2096
91.3323
79.0289
115.9377
75.4887
123.2049
101.1904
95.9454
82.4181
108.8314
123.0198
76.8494
94.8827
149.5911
95.6969
143.3498
87.0939
77.3033
105.8185
122.3455
79.8208
112.9913
120.1649
131.3052
136.8246
96.5455
109.0187
87.1363
103.1835
106.3896
143.9496
119.1357
99.9114
111.1409
79.0563
147.1506
105.7851
99.7089
117.8770
99.7602
73.1796
125.8698
109.4367
135.5020
88.1979
129.8502
121.1233
76.7520
86.5296
118.6721
83.2511
116.3950
99.8795
70.6895
64.9578
111.4750
102.6343
82.8765
90.3479
106.8873
106.3850
119.3399
根据常量后面的注释,您想使用 1000 个细分步长(即步长为 0.001)模拟从 0 到 1 的 10000 条积分路径。
你正在做的是整合一条超过 10000 步的路径,步长为 0.001,即从 0 到 10。
如果操作正确,结果应该类似于
S0 * exp( ((r-q)-0.5*sigma*sigma)*T + sigma*sqrt(T)*Z[i] )
因为 GBM 在时间 T
的值仅取决于 W(T)
分布为 N(0,T)
或 sqrt(T)*N(0,1)
.
函数GBM每次应该模拟1条路径。因此无需提供 M。路径长度在您的代码中由 N 而不是 M 定义。
如果实施此更改,GBM return 整个模拟路径。
然后你需要调用GBM M次才能计算出所有的模拟。
也不需要存储所有生成的随机数。
根据你的样本,是这样的:
#include <iostream>
#include <vector>
#include <random>
// Random generator initialize (only once).
static std::mt19937 rng(time(0));
std::vector<double> GBM(const int N, const double T, const double r,
const double q, const double sigma, const double S0)
{
double dt = T/N;
std::vector<double> S;
S.push_back(S0);
std::normal_distribution<double> dist(0.0, 1.0);
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < N; i++){
double Z = dist(rng);
S.push_back(S[i-1] * drift * exp(vol*Z));
}
return S;
}
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double S0 = 100.0; // Initial stock price
const int M = 100; // Number of paths
for (int sindx = 0; sindx < M; sindx++)
{
std::vector<double> s = GBM(N,T,r,q,sigma,S0);
std::cout << "Simulation " << sindx << ": "
<< s[0] << ", " << s[1] << " ... " << s[N-2] << ", " << s[N-1]
<< std::endl;
}
return 0;
}
我用 C++ 编写了一个 GBM 函数,我相信当我以 100 的初始价格开始时,我得到的股票价格范围太多,输出可能来自 [50,400]。我不确定我的代码做错了什么,我猜我播种随机标准正态数的方式有问题。请看一下函数,如果有什么需要修改或更改的,请告诉我。
函数如下:
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0){
double dt = T/N;
std::vector<double> Z;
std::vector<double> S;
S.push_back(S0);
std::mt19937 e2(time(0));
std::normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
Z.push_back(dist(e2));
}
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < M; i++){
S.push_back(S[i-1] * drift * exp(vol*Z[i]));
}
return S;
}
这里是 main.cpp 使用上述功能的文件:
#include <iostream>
#include "LSM.h"
#include <cmath>
#include <ctime>
#include <Eigen/Core>
#include <Eigen/SVD>
#include <iostream>
#include <vector>
#include <random>
std::vector<double> GBM(const int M, const int N, const double T, const double r, const double q, const double sigma, const double S0);
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double K = 100.0; // Strike price
const double S0 = 100.0; // Initial stock price
const int M = 10000; // Number of paths
const int R = 2; // Choice of basis for Laguerre polynomial
//LSM Option_value(r,q,sigma,T,N,K,S0,M,R);
std::vector<double> s = GBM(M,N,T,r,q,sigma,S0);
for(int i = 0; i < M; i++){
std::cout << s[i] << std::endl;
}
return 0;
}
初始股价为 100 的典型输出如下:
153.5093
132.0190
96.2550
106.5196
58.8447
135.3935
107.1194
101.2022
134.2812
82.2146
87.9162
74.9333
88.9137
207.5150
123.7893
95.8526
120.0831
96.3990
103.3806
113.8258
100.6409
92.0724
81.1704
121.9925
114.3798
117.8366
86.1070
74.4885
82.6013
78.0202
97.0586
119.7626
89.0520
72.2328
92.1998
84.7180
138.9160
91.0091
105.2096
91.3323
79.0289
115.9377
75.4887
123.2049
101.1904
95.9454
82.4181
108.8314
123.0198
76.8494
94.8827
149.5911
95.6969
143.3498
87.0939
77.3033
105.8185
122.3455
79.8208
112.9913
120.1649
131.3052
136.8246
96.5455
109.0187
87.1363
103.1835
106.3896
143.9496
119.1357
99.9114
111.1409
79.0563
147.1506
105.7851
99.7089
117.8770
99.7602
73.1796
125.8698
109.4367
135.5020
88.1979
129.8502
121.1233
76.7520
86.5296
118.6721
83.2511
116.3950
99.8795
70.6895
64.9578
111.4750
102.6343
82.8765
90.3479
106.8873
106.3850
119.3399
根据常量后面的注释,您想使用 1000 个细分步长(即步长为 0.001)模拟从 0 到 1 的 10000 条积分路径。
你正在做的是整合一条超过 10000 步的路径,步长为 0.001,即从 0 到 10。
如果操作正确,结果应该类似于
S0 * exp( ((r-q)-0.5*sigma*sigma)*T + sigma*sqrt(T)*Z[i] )
因为 GBM 在时间 T
的值仅取决于 W(T)
分布为 N(0,T)
或 sqrt(T)*N(0,1)
.
函数GBM每次应该模拟1条路径。因此无需提供 M。路径长度在您的代码中由 N 而不是 M 定义。
如果实施此更改,GBM return 整个模拟路径。 然后你需要调用GBM M次才能计算出所有的模拟。
也不需要存储所有生成的随机数。
根据你的样本,是这样的:
#include <iostream>
#include <vector>
#include <random>
// Random generator initialize (only once).
static std::mt19937 rng(time(0));
std::vector<double> GBM(const int N, const double T, const double r,
const double q, const double sigma, const double S0)
{
double dt = T/N;
std::vector<double> S;
S.push_back(S0);
std::normal_distribution<double> dist(0.0, 1.0);
double drift = exp(dt*((r - q)-0.5*sigma*sigma));
double vol = sqrt(sigma*sigma*dt);
for(int i = 1; i < N; i++){
double Z = dist(rng);
S.push_back(S[i-1] * drift * exp(vol*Z));
}
return S;
}
int main(){
const double r = 0.04; // Riskless interest rate
const double q = 0.0; // Divident yield
const double sigma = 0.20; // Volatility of stock
const double T = 1; // Time (expiry)
const int N = 1000; // Number of time steps
const double S0 = 100.0; // Initial stock price
const int M = 100; // Number of paths
for (int sindx = 0; sindx < M; sindx++)
{
std::vector<double> s = GBM(N,T,r,q,sigma,S0);
std::cout << "Simulation " << sindx << ": "
<< s[0] << ", " << s[1] << " ... " << s[N-2] << ", " << s[N-1]
<< std::endl;
}
return 0;
}