几何布朗运动;股价模拟

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;
}