几何布朗运动;股票价格模拟

时间:2017-10-23 17:43:49

标签: c++ algorithm montecarlo

我在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

2 个答案:

答案 0 :(得分:1)

根据常量后面的注释,您希望使用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] )

因为T时间GBM的值仅取决于W(T)N(0,T)sqrt(T)*N(0,1)

答案 1 :(得分:1)

功能GBM每次都应该模拟1条路径。所以不需要提供M.并且路径长度在您的代码中由N而不是M定义。

如果实施此更改,GBM将返回整个模拟路径。 然后你需要调用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;
}