N 个价格路径在 N 次迭代中不变的平均估计值

Mean estimates of the N price paths not changing over N-iterations

本文关键字:路径 迭代      更新时间:2023-10-16

我对C++相对较新,所以如果标题不够,我深表歉意。我正在尝试做的是使用 N 个价格路径获得 40 个期权价格的估计值。从本质上讲,我想得到 N 个价格路径的 40 个不同的平均估计值。但我一定做错了什么,因为我每次都得到相同的平均价格。这是我的代码:

// Generate 40 estimates for the option price, using N paths
int m = 40;
MatrixXd SS(N,n+1);
VectorXd S(m);
for(int k = 0; k < m; k++){
MatrixXd Z = generateGaussianNoise(N,n);
for(int i = 0; i < N; i++){
SS(i,0) = S0;
for(int j = 1; j <= n; j++){
SS(i,j) = SS(i,j-1)*exp((double) (r - pow(sigma,2.0))*dt + sigma*sqrt(dt)*(double)Z(i,j-1));
}
}
S(k) = SS.mean();
}
cout << S << endl;
}

这也是我的整个代码:

#include <iostream>
#include <cmath>
#include <math.h>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <random>
#include <time.h>
using namespace Eigen;
using namespace std;
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n);
VectorXd time_vector(double min, double max, int n);
int main(){
int N = 100;
double K = 100;
double r = 0.2;
double S0 = 100;
double sigma = 0.4;
double T = 0.1;
int n = 10;
crudeMonteCarlo(N,K,r,S0,sigma,T,n);
return 0;
}
VectorXd time_vector(double min, double max, int n){
VectorXd m(n + 1);
double delta = (max-min)/n;
for(int i = 0; i <= n; i++){
m(i) = min + i*delta;
}
return m;
}
MatrixXd generateGaussianNoise(int M, int N){
MatrixXd Z(M,N);
random_device rd;
mt19937 e2(rd());
normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
Z(i,j) = dist(e2);
}
}
return Z;
}
/*VectorXd Stock_process_Lognormal(double T, double S0, double K, double r, double sigma, int N, int n , int m){
VectorXd S(m);
}*/
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n){
// Create time vector
VectorXd tt = time_vector(0.0,T,n);
VectorXd t(n);
double dt = T/n;
for(int i = 0; i < n; i++){
t(i) = tt(i+1);
}
// Generate standard normal Z matrix
MatrixXd Z = generateGaussianNoise(N,n);
// Generate 40 estimates for the option price, using N paths
int m = 40;
MatrixXd SS(N,n+1);
VectorXd S(m);
for(int k = 0; k < m; k++){
for(int i = 0; i < N; i++){
SS(i,0) = S0;
for(int j = 1; j <= n; j++){
SS(i,j) = SS(i,j-1)*exp((double) (r - pow(sigma,2.0))*dt + sigma*sqrt(dt)*(double)Z(i,j-1));
}
}
S(k) = SS.mean();
}
cout << S << endl;


}

我将generateGaussian函数更改为种子rd()尽管我仍然保持相同的输出(40 个期权价格估计值)。它们应该不同,因为我想运行 for 循环 40 次,每次都得到矩阵的平均值。这是我得到 40 次的 40 个估计值的输出:

99.422

您在40 次迭代k循环之前调用generateGaussianNoise,并且该循环中的任何内容都不会更改由随机生成的数据填充的Z数组中的数据。 因此,每次您都会获得相同的数据。

解决此问题的一种方法是将generateGaussianNoise拆分为两个函数,一个为随机生成器播种(在k循环之前调用),另一个填充Z数组(从k循环中调用)。

或者,您可以在循环外部生成一个种子值,然后将其传递到generateGaussianNoise(从k循环中调用),同时以某种方式在每次迭代中更改值。 由于每次迭代都独立于以前的迭代,因此如果需要性能,这将允许多线程模拟。 还可以使用seed_seq向随机数生成器提供多个种子值(例如,基于时间的种子值,序列中第二个值具有基于迭代的值)。

使用示例实现进行编辑

例如,第一种方法的一种实现可能是更改generateGaussianNoise以将随机数引擎作为参数:

MatrixXd generateGaussianNoise(int M, int N, mt19937 &e2){
MatrixXd Z(M,N);
normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
Z(i,j) = dist(e2);
}
}
return Z;
}

然后在crudeMonteCarlo中,您当前声明Z的地方,将其替换为

mt19937 e2(random_device());

这将创建并初始化要使用的随机数引擎。 在k循环中,在i循环之前,声明Z并调用generateGaussianNoise,传入e2

MatrixXd Z = generateGaussianNoise(N,n,e2);