C++ 几何布朗运动的模拟

C++ 几何布朗运动的模拟,c++,montecarlo,C++,Montecarlo,背景信息: 考虑伪代码: 问题: 我似乎对算法1伪代码的S上标j部分有问题,我的教授说,由于N=10000和N=10,我计算的是10。以下是我的代码中有问题的部分: double Z[n][N]; for(int j = 0; j < N; j++){ for(int i = 0; i < n/2; i++){ Z[2*i][j] = Box_MullerX(n,N,shifted_hs[i],shifted_hs[i+1]);

背景信息:

考虑伪代码:

问题:

我似乎对算法1伪代码的S上标j部分有问题,我的教授说,由于N=10000和N=10,我计算的是10。以下是我的代码中有问题的部分:

double Z[n][N];
    for(int j = 0; j < N; j++){
        for(int i = 0; i < n/2; i++){
            Z[2*i][j] = Box_MullerX(n,N,shifted_hs[i],shifted_hs[i+1]);
            Z[2*i+1][j] = Box_MullerY(n,N,shifted_hs[i],shifted_hs[i+1]);
        }
    }

    /*for(int j = 0; j < N; j++){
        for(int i = 0; i < n; i++){
            cout << Z[j][i] << " ";
        }
        cout << endl;
    }*/

    double S[N][n];
    S[0][0] = S0;
    double t[n+1];
    for(int i = 0; i <= n; i++){
        t[i] = (double)i*T/(n-1);
    }
    for(int j = 1; j <= N; j++){
        for(int i = 1; i <= n; i++){
            S[j][i] = S[j-1][i-1]*exp((mu - sigma/2)*(t[i] - t[i-1]) + sqrt(sigma)*sqrt(t[i] - t[i-1])*Z[j][i]);
        }
    }
double Z[n][n];
对于(int j=0;j请解释你期望得到什么和得到什么。这有助于理解可能的变异

我注意到你在代码中混合了整数值和双数值,这不是好的做法。 另外-标记Setchell右-检查你的sigma值。我认为它应该是平方。并尝试正确设置
S
的初始值

我试图以我理解的方式修复代码中的错误。由于编译器版本较旧,代码发生了一些变化

#include <iostream>
#include <cmath>
#include <math.h>
#include <random>

using namespace std;

const double M_PI = 3.1415926535897932384626433832795;
const double M_SQRT1_2 = 0.70710678118654752440084436210485;

double phi(long double x);
double Black_Scholes(double T, double K, double S0, double r, double sigma);
double Halton_Seq(int index, double base);
double Box_MullerX(double u_1, double u_2);
double Box_MullerY(double u_1, double u_2);
double Random_Shift_Halton(int n,int N,double mu, double sigma, double T, double S0);


double erfc(double v) {
    double y = 1.0 / ( 1.0 + 0.3275911 * (v >= 0 ? v : -v));
    y = 1 - (((((
        + 1.061405429  * y
        - 1.453152027) * y
        + 1.421413741) * y
        - 0.284496736) * y
        + 0.254829592) * y)
        * exp (-v * v);
    return (v >= 0 ? y : -y);
}

double phi(double x){
    return 0.5 * erfc(-x * M_SQRT1_2);
}

double Black_Scholes(double T, double K, double S0, double r, double sigma){
    double d_1 = (log(S0/K) + (r+sigma*sigma/2.)*(T))/(sigma*sqrt(T));
    double d_2 = (log(S0/K) + (r-sigma*sigma/2.)*(T))/(sigma*sqrt(T));
    double C = S0*phi(d_1) - phi(d_2)*K*exp(-r*T);
    return C;
}

double Halton_Seq(int index, double base){
    double f = 1.0, r = 0.0;
    double indice = (double)index;
    while(indice >= base){
        f = f/base;
        r = r + f*(fmod(indice,base));
        indice = ceil(indice/base);
    }
    return r;
}

double Box_MullerX(double u_1, double u_2){
    double R = -2.0*log(u_1);
    double theta = 2.0*M_PI*u_2;
    double X = sqrt(R)*cos(theta);

    return X;
}

double Box_MullerY(double u_1, double u_2){
    double R = -2.0*log(u_1);
    double theta = 2.0*M_PI*u_2;
    double Y = sqrt(R)*sin(theta);

    return Y;
}

double Random_Shift_Halton(int n,int N,double mu, double sigma, double T, double S0){
    //  Generate the Halton_Sequence
    double* hs = new double[N+1];
    for(int i = 0; i <= N; i++){
        hs[i] = Halton_Seq(i,2.0);
    }
    // Generate two random numbers from U(0,1)
    double* u = new double[N+1];
    random_device rd;
    mt19937 e2(rd());
    uniform_real_distribution<double> dist(0.0, 1.0);
    for(int i = 0; i <= N; i++){
        u[i] = dist(e2);
    }
    // Add the vector u to each vector hs and take fraction part of the sum
    double* shifted_hs = new double[N+1];
    for(int i = 0; i <= N; i++){
        shifted_hs[i] = hs[i] + u[i];
        if(shifted_hs[i] > 1){
            shifted_hs[i] = shifted_hs[i] - 1.0;
        }
    }

    // Use Geometric Brownian Motion
    double** Z = new double*[N];    
    for(int i = 0; i < N; ++i)
       Z[i] = new double[n];
    for(int j = 0; j < N; j++){
        for(int i = 0; i < n/2; i++){
            Z[j][2*i] = Box_MullerX(shifted_hs[j],shifted_hs[j+1]);
            Z[j][2*i+1] = Box_MullerY(shifted_hs[j],shifted_hs[j+1]);
        }
    }

    double** S = new double*[N+1];  
    for(int i = 0; i <= N; ++i) 
       S[i] = new double[n+1];
    for (int i = 0; i <= N; i++) S[i][0] = S0;
    for (int j = 0; j <= n; j++) S[0][j] = S0;
    double* t = new double[n+1];
    for(int i = 0; i <= n; i++){
        t[i] = (double)i*T/(double)(n-1);
    }
    for(int j = 1; j <= N; j++){
        for(int i = 1; i <= n; i++){
            S[j][i] = S[j-1][i-1]*exp((mu - sigma/2.0)*(t[i] - t[i-1]) + sqrt(sigma)*sqrt(t[i] - t[i-1])*Z[j-1][i-1]);
        }
    }

    // Use random-shift halton sequence to obtain 40 independent estimates for the price of the option
    //....

    delete(hs);
    delete(u);
    delete(shifted_hs);
    for(int i = 0; i < N; ++i) {
       delete(Z[i]);
    }
    for(int i = 0; i <= N; ++i) delete(S[i]);
    delete(S);
    delete(Z);
    delete(t);

    return 0.0;
}

int main()
{
    int n = 10;
    int N = 10000;

    // Calculate BS
    double T = 1.0;
    double K = 50.0;
    double r = 0.1;
    double sigma = 0.3;
    sigma *= sigma;
    double S0 = 50.0;
    double price = Black_Scholes(T,K,S0,r,sigma);
    //cout << price << endl;

    // Random-shift Halton Sequence
    Random_Shift_Halton(n,N,r,sigma,T, S0);
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
常数双M_PI=3.1415926535897932384626433832795;
常数双平方米=0.70710678118654752440084436210485;
双φ(长双x);
双Black_Scholes(双T、双K、双S0、双r、双西格玛);
双Halton_Seq(整数指数,双基);
双箱磨浆机(双箱磨浆机1,双箱磨浆机2);
双盒磨粉机(双盒磨粉机1、双盒磨粉机2);
双随机移位(int n,int n,双μ,双西格玛,双T,双S0);
双电流变电容器(双v){
双y=1.0/(1.0+0.3275911*(v>=0?v:-v));
y=1-(((((
+1.061405429*y
-1.453152027)*y
+1.421413741)*y
-0.284496736)*y
+0.254829592)*y)
*exp(-v*v);
返回值(v>=0?y:-y);
}
双φ(双x){
返回0.5*erfc(-x*M_SQRT1_2);
}
双Black_Scholes(双T、双K、双S0、双r、双西格玛){
双d_1=(对数(S0/K)+(r+sigma*sigma/2.)*(T))/(sigma*sqrt(T));
双d_2=(对数(S0/K)+(r-sigma*sigma/2.)*(T))/(sigma*sqrt(T));
双C=S0*phi(d_1)-phi(d_2)*K*exp(-r*T);
返回C;
}
双Halton_Seq(整数指数,双基){
双f=1.0,r=0.0;
双指数=(双)指数;
while(标记>=基){
f=f/基;
r=r+f*(fmod(标记,基础));
籼=细胞(籼/基);
}
返回r;
}
双箱磨浆机(双箱磨浆机1、双箱磨浆机2){
双R=-2.0*log(u_1);
双θ=2.0*M_π*u_2;
双X=sqrt(R)*cos(θ);
返回X;
}
双箱研磨机(双u 1,双u 2){
双R=-2.0*log(u_1);
双θ=2.0*M_π*u_2;
双Y=sqrt(R)*sin(θ);
返回Y;
}
双随机移位Halton(整数n,整数n,双mu,双西格玛,双T,双S0){
//生成Halton_序列
双精度*hs=新双精度[N+1];

对于(int i=0;i)你似乎有
mu signa/2
而不是
mu sigmaSQUARED/2
我将sigma定义为sigma squared,这就是为什么我在需要时将sigma设置为
0.09
而不是
0.3
,如果它真的是sigma squared?
#include <iostream>
#include <cmath>
#include <math.h>
#include <random>

using namespace std;

const double M_PI = 3.1415926535897932384626433832795;
const double M_SQRT1_2 = 0.70710678118654752440084436210485;

double phi(long double x);
double Black_Scholes(double T, double K, double S0, double r, double sigma);
double Halton_Seq(int index, double base);
double Box_MullerX(double u_1, double u_2);
double Box_MullerY(double u_1, double u_2);
double Random_Shift_Halton(int n,int N,double mu, double sigma, double T, double S0);


double erfc(double v) {
    double y = 1.0 / ( 1.0 + 0.3275911 * (v >= 0 ? v : -v));
    y = 1 - (((((
        + 1.061405429  * y
        - 1.453152027) * y
        + 1.421413741) * y
        - 0.284496736) * y
        + 0.254829592) * y)
        * exp (-v * v);
    return (v >= 0 ? y : -y);
}

double phi(double x){
    return 0.5 * erfc(-x * M_SQRT1_2);
}

double Black_Scholes(double T, double K, double S0, double r, double sigma){
    double d_1 = (log(S0/K) + (r+sigma*sigma/2.)*(T))/(sigma*sqrt(T));
    double d_2 = (log(S0/K) + (r-sigma*sigma/2.)*(T))/(sigma*sqrt(T));
    double C = S0*phi(d_1) - phi(d_2)*K*exp(-r*T);
    return C;
}

double Halton_Seq(int index, double base){
    double f = 1.0, r = 0.0;
    double indice = (double)index;
    while(indice >= base){
        f = f/base;
        r = r + f*(fmod(indice,base));
        indice = ceil(indice/base);
    }
    return r;
}

double Box_MullerX(double u_1, double u_2){
    double R = -2.0*log(u_1);
    double theta = 2.0*M_PI*u_2;
    double X = sqrt(R)*cos(theta);

    return X;
}

double Box_MullerY(double u_1, double u_2){
    double R = -2.0*log(u_1);
    double theta = 2.0*M_PI*u_2;
    double Y = sqrt(R)*sin(theta);

    return Y;
}

double Random_Shift_Halton(int n,int N,double mu, double sigma, double T, double S0){
    //  Generate the Halton_Sequence
    double* hs = new double[N+1];
    for(int i = 0; i <= N; i++){
        hs[i] = Halton_Seq(i,2.0);
    }
    // Generate two random numbers from U(0,1)
    double* u = new double[N+1];
    random_device rd;
    mt19937 e2(rd());
    uniform_real_distribution<double> dist(0.0, 1.0);
    for(int i = 0; i <= N; i++){
        u[i] = dist(e2);
    }
    // Add the vector u to each vector hs and take fraction part of the sum
    double* shifted_hs = new double[N+1];
    for(int i = 0; i <= N; i++){
        shifted_hs[i] = hs[i] + u[i];
        if(shifted_hs[i] > 1){
            shifted_hs[i] = shifted_hs[i] - 1.0;
        }
    }

    // Use Geometric Brownian Motion
    double** Z = new double*[N];    
    for(int i = 0; i < N; ++i)
       Z[i] = new double[n];
    for(int j = 0; j < N; j++){
        for(int i = 0; i < n/2; i++){
            Z[j][2*i] = Box_MullerX(shifted_hs[j],shifted_hs[j+1]);
            Z[j][2*i+1] = Box_MullerY(shifted_hs[j],shifted_hs[j+1]);
        }
    }

    double** S = new double*[N+1];  
    for(int i = 0; i <= N; ++i) 
       S[i] = new double[n+1];
    for (int i = 0; i <= N; i++) S[i][0] = S0;
    for (int j = 0; j <= n; j++) S[0][j] = S0;
    double* t = new double[n+1];
    for(int i = 0; i <= n; i++){
        t[i] = (double)i*T/(double)(n-1);
    }
    for(int j = 1; j <= N; j++){
        for(int i = 1; i <= n; i++){
            S[j][i] = S[j-1][i-1]*exp((mu - sigma/2.0)*(t[i] - t[i-1]) + sqrt(sigma)*sqrt(t[i] - t[i-1])*Z[j-1][i-1]);
        }
    }

    // Use random-shift halton sequence to obtain 40 independent estimates for the price of the option
    //....

    delete(hs);
    delete(u);
    delete(shifted_hs);
    for(int i = 0; i < N; ++i) {
       delete(Z[i]);
    }
    for(int i = 0; i <= N; ++i) delete(S[i]);
    delete(S);
    delete(Z);
    delete(t);

    return 0.0;
}

int main()
{
    int n = 10;
    int N = 10000;

    // Calculate BS
    double T = 1.0;
    double K = 50.0;
    double r = 0.1;
    double sigma = 0.3;
    sigma *= sigma;
    double S0 = 50.0;
    double price = Black_Scholes(T,K,S0,r,sigma);
    //cout << price << endl;

    // Random-shift Halton Sequence
    Random_Shift_Halton(n,N,r,sigma,T, S0);
    return 0;
}