8 int n_paths,
int steps,
double T,
double spot,
bool antithetic) {
9 std::random_device rd{};
10 std::mt19937 gen(rd());
12 std::vector<std::vector<double>> paths;
13 std::normal_distribution<double> Normal(0, 1);
14 double dt = T / steps;
15 double sqdt = sqrt(dt) * sigma;
16 double r_sigma_dt = (this->r - 0.5 * sigma * sigma) * dt;
19 for (
int i = 0; i < n_paths; ++i) {
20 std::vector<double> path1;
21 std::vector<double> path2;
25 for (
int j = 1; j <= steps; ++j) {
26 double sigma_dw = sqdt * Normal(gen);
27 path1.push_back(path1[j - 1] + r_sigma_dt + sigma_dw);
28 path1[j - 1] = spot * exp(path1[j - 1]);
30 path2.push_back(path2[j - 1] + r_sigma_dt - sigma_dw);
31 path2[j - 1] = spot * exp(path2[j - 1]);
33 path1[path1.size() - 1] = spot * exp(path1[path1.size() - 1]);
34 path2[path2.size() - 1] = spot * exp(path2[path2.size() - 1]);
38 paths.push_back(path1);
39 paths.push_back(path2);
42 for (
int i = 0; i < n_paths; ++i) {
43 std::vector<double> path1;
46 for (
int j = 1; j <= steps; ++j) {
47 double sigma_dw = sqdt * Normal(gen);
48 path1.push_back(path1[j - 1] + r_sigma_dt + sigma_dw);
49 path1[j - 1] = spot * exp(path1[j - 1]);
51 path1[path1.size() - 1] = spot * exp(path1[path1.size() - 1]);
53 paths.push_back(path1);
62 int N = stock_prices.size();
63 for (
auto stock_price : stock_prices)
64 mean += (stock_price / N);
65 for (
auto stock_price : stock_prices)
66 std += (stock_price - mean) * (stock_price - mean) / (N - 1);
68 this->sigma = sqrt(std);
72 double r,
double sigma,
double T, std::function<
double(
double)> payoff,
73 double S_max,
double S_min,
int M,
int N) {
74 double h = (S_max - S_min) / N;
76 std::vector<std::vector<double>> u;
77 u.resize(M + 1, std::vector<double>(N + 1));
79 for (
int j = 0; j < N + 1; j++) {
80 u[0][j] = payoff(S_min + j * h);
84 tau * (pow(sigma, 2) * pow(S_min + h, 2) *
85 (u[0][2] - 2 * u[0][1] + u[0][0]) / 4 / pow(h, 2) +
86 r * (S_min + h) * (u[0][2] - u[0][0]) / 2 / h - r * u[0][1]);
89 tau * (pow(sigma, 2) * pow(S_min + (N - 1) * h, 2) *
90 (u[0][N] - 2 * u[0][N - 1] + u[0][N - 2]) / 4 / pow(h, 2) +
91 r * (S_min + (N - 1) * h) * (u[0][N] - u[0][N - 2]) / 2 / h -
93 std::vector<double> a;
95 std::vector<double> b;
97 std::vector<double> c;
99 std::vector<double> f;
104 for (
int j = 2; j <= N - 2; j++) {
105 b[j] = a[j] = tau * pow(sigma, 2) * pow(S_min + j * h, 2) / 4 / pow(h, 2);
106 c[j] = 1 + tau * pow(sigma, 2) * pow(S_min + j * h, 2) / 2 / pow(h, 2);
108 (pow(sigma, 2) * pow(S_min + j * h, 2) / 4 / pow(h, 2) -
109 r * (S_min + j * h) / 2 / h) *
111 tau * (pow(sigma, 2) * pow(S_min + j * h, 2) / 2 / pow(h, 2) + r) *
115 (pow(sigma, 2) * pow(S_min + j * h, 2) / 4 / pow(h, 2) +
116 r * (S_min + j * h) / 2 / h) *
121 f[N - 1] = u[1][N - 1];
123 u[1][0] = 2 * u[1][1] - u[1][2];
124 u[1][N] = 2 * u[1][N - 1] - u[1][N - 2];
126 for (
int k = 2; k <= M; k++) {
127 u[k][1] = u[k - 1][1] +
128 tau * (r * (S_min + h) * (u[k - 1][2] - u[k - 1][0]) / 2 / h -
131 u[k - 1][N - 1] + tau * (r * (S_min + (N - 1) * h) *
132 (u[k - 1][N] - u[k - 1][N - 2]) / 2 / h -
133 r * u[k - 1][N - 1]);
137 for (
int j = 2; j <= N - 2; j++) {
138 b[j] = a[j] = tau * pow(sigma, 2) * pow(S_min + j * h, 2) / 4 / pow(h, 2);
139 c[j] = 1 + tau * pow(sigma, 2) * pow(S_min + j * h, 2) / 2 / pow(h, 2);
141 (pow(sigma, 2) * pow(S_min + j * h, 2) / 4 / pow(h, 2) -
142 r * (S_min + j * h) / 2 / h) *
144 tau * (pow(sigma, 2) * pow(S_min + j * h, 2) / 2 / pow(h, 2) + r) *
148 (pow(sigma, 2) * pow(S_min + j * h, 2) / 4 / pow(h, 2) +
149 r * (S_min + j * h) / 2 / h) *
154 f[N - 1] = u[k][N - 1];
156 u[k][0] = 2 * u[k][1] - u[k][2];
157 u[k][N] = 2 * u[k][N - 1] - u[k][N - 2];
160 std::reverse(u.begin(), u.end());
162 for (
int k = 0; k <= M; k += 100) {
163 for (
int j = 0; j <= N; j++) {
164 if (u[k][j] < 0.00001)
Contains the definition of the Black-Sholes model.
void thomas_algorithm(std::vector< double > &v, std::vector< double > &a, std::vector< double > &b, std::vector< double > &c, std::vector< double > &f)
Implementation of Thomas algorithm for tridiagonal matrices.
std::vector< std::vector< double > > pde_pricer(double r, double sigma, double T, std::function< double(double)> payoff, double S_max, double S_min, int M, int N)
std::vector< std::vector< double > > generate_paths(int n_paths, int steps, double T, double spot, bool antithetic=true)
void calibrate(std::vector< double > &stock_prices)