通过蒙特卡洛方法用 C++ 进行双重数字期权定价蒙特卡洛方法用 C++ 进行双重数字期权定价
双数字选项
C++ 实现
继我们通过蒙特卡洛定价数字期权的方法之后,我们现在将修改该文章中提供的代码以处理双数字期权。由于我们不区分看涨期权和看跌期权,因此我们只需编写一个支付函数。Heaviside 函数已被删除并替换为函数payoff_double_digital
。请注意,它需要三个参数:两个执行价值和到期时标的资产的现货价格。我还替换了payoff_sum
蒙特卡洛函数中的行以使用此支付函数。以下是完整列表:
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
double gaussian_box_muller() {
double x = 0.0;
double y = 0.0;
double euclid_sq = 0.0;
do {
x = 2.0 * rand() / static_cast<double>(RAND_MAX)-1;
y = 2.0 * rand() / static_cast<double>(RAND_MAX)-1;
euclid_sq = x*x + y*y;
} while (euclid_sq >= 1.0);
return x*sqrt(-2*log(euclid_sq)/euclid_sq);
}
double payoff_double_digital(const double& K_L, const double& K_U, const double& x) {
if (x >= K_L && x <= K_U) {
return 1.0;
} else {
return 0.0;
}
}
double monte_carlo_double_digital_price(const int& num_sims, const double& S, const double& K_L, const double& K_U, const double& r, const double& v, const double& T) {
double S_adjust = S * exp(T*(r-0.5*v*v));
double S_cur = 0.0;
double payoff_sum = 0.0;
for (int i=0; i<num_sims; i++) {
double gauss_bm = gaussian_box_muller();
S_cur = S_adjust * exp(sqrt(v*v*T)*gauss_bm);
payoff_sum += payoff_double_digital(K_L, K_U, S_cur);
}
return (payoff_sum / static_cast<double>(num_sims)) * exp(-r*T);
}
int main(int argc, char **argv) {
// First we create the parameter list
int num_sims = 10000000; // Number of simulated asset paths
double S = 100.0; // Option price
double K_L = 100.0; // Lower strike price
double K_U = 120.0; // Upper strike price
double r = 0.05; // Risk-free rate (5%)
double v = 0.2; // Volatility of the underlying (20%)
double T = 1.0; // One year until expiry
// Then we calculate the double digital values
double dd = monte_carlo_double_digital_price(num_sims, S, K_L, K_U, r, v, T);
// Finally we output the parameters and prices
std::cout << "Number of Paths: " << num_sims << std::endl;
std::cout << "Underlying: " << S << std::endl;
std::cout << "Lower Strike: " << K_L << std::endl;
std::cout << "Upper Strike: " << K_U << std::endl;
std::cout << "Risk-Free Rate: " << r << std::endl;
std::cout << "Volatility: " << v << std::endl;
std::cout << "Maturity: " << T << std::endl;
std::cout << "Options Price: " << dd << std::endl;
return 0;
}
与之前一样,我们可以看到 Box-Muller 函数以及通过蒙特卡洛方法对双数字期权定价所需的收益函数。
// The pay-off function for the double digital. It takes two strike values
// as well as the spot price of the underlying at expiry. It simply returns
// unity if the spot is within the strikes (inclusive) and zero otherwise.
double payoff_double_digital(const double& K_L, const double& K_U, const double& x) {
if (x >= K_L && x <= K_U) {
return 1.0;
} else {
return 0.0;
}
}
对 monte_carlo_double_digital_price 的修改如下:
..
payoff_sum += payoff_double_digital(K_L, K_U, S_cur);
..
该程序的输出如下:
Number of Paths: 10000000
Underlying: 100
Lower Strike: 100
Upper Strike: 120
Risk-Free Rate: 0.05
Volatility: 0.2
Maturity: 1
Options Price: 0.32009
再次强调,我们将继续在这些文章中重复代码,这不是生产部署的最佳实践!但是,通过提供上面的完整列表,您可以立即开始为双数字选项定价 - 如果这是您的目标。请注意,在未来的文章中,我们将使用继承和多态性创建支付层次结构,这将使我们能够解决这些可维护性和重复性问题。
使用蒙特卡罗方法对数字看涨期权(和看跌期权)进行定价。我们已经了解了如何对普通看涨期权和看跌期权进行定价。我们将修改上一篇文章中的代码以处理数字期权的支付函数,该函数利用了 Heaviside 函数。
数字选项
C++ 实现
鉴于我们已经在有关使用蒙特卡罗为欧式普通看涨期权和看跌期权定价的文章中考虑了基本的蒙特卡罗方法,我将仅讨论对代码的修改。但是,我仍然提供了完整的清单,它将为您提供实现基本数字期权定价器所需的一切。
#include <cmath>
#include <iostream>
// A simple implementation of the Box-Muller algorithm, used to generate
// gaussian random numbers - necessary for the Monte Carlo method below
// Note that C++11 actually provides std::normal_distribution<> in
// the <random> library, which can be used instead of this function
double gaussian_box_muller() {
double x = 0.0;
double y = 0.0;
double euclid_sq = 0.0;
// Continue generating two uniform random variables
// until the square of their "euclidean distance"
// is less than unity
do {
x = 2.0 * rand() / static_cast<double>(RAND_MAX)-1;
y = 2.0 * rand() / static_cast<double>(RAND_MAX)-1;
euclid_sq = x*x + y*y;
} while (euclid_sq >= 1.0);
return x*sqrt(-2*log(euclid_sq)/euclid_sq);
}
// This is the Heaviside step function, named after English
// mathematician Oliver Heaviside. It returns unity when val
// is greater than or equal to zero and returns zero otherwise
double heaviside(const double& val) {
if (val >= 0) {
return 1.0;
} else {
return 0.0;
}
}
// Pricing a digital call option with a Monte Carlo method
double monte_carlo_digital_call_price(const int& num_sims, const double& S, const double& K, const double& r, const double& v, const double& T) {
double S_adjust = S * exp(T*(r-0.5*v*v));
double S_cur = 0.0;
double payoff_sum = 0.0;
for (int i=0; i<num_sims; i++) {
double gauss_bm = gaussian_box_muller();
S_cur = S_adjust * exp(sqrt(v*v*T)*gauss_bm);
payoff_sum += heaviside(S_cur - K);
}
return (payoff_sum / static_cast<double>(num_sims)) * exp(-r*T);
}
// Pricing a digital put option with a Monte Carlo method
double monte_carlo_digital_put_price(const int& num_sims, const double& S, const double& K, const double& r, const double& v, const double& T) {
double S_adjust = S * exp(T*(r-0.5*v*v));
double S_cur = 0.0;
double payoff_sum = 0.0;
for (int i=0; i<num_sims; i++) {
double gauss_bm = gaussian_box_muller();
S_cur = S_adjust * exp(sqrt(v*v*T)*gauss_bm);
payoff_sum += heaviside(K - S_cur);
}
return (payoff_sum / static_cast<double>(num_sims)) * exp(-r*T);
}
int main(int argc, char **argv) {
// First we create the parameter list
int num_sims = 10000000; // Number of simulated asset paths
double S = 100.0; // Option price
double K = 100.0; // Strike price
double r = 0.05; // Risk-free rate (5%)
double v = 0.2; // Volatility of the underlying (20%)
double T = 1.0; // One year until expiry
// Then we calculate the call/put values via Monte Carlo
double call = monte_carlo_digital_call_price(num_sims, S, K, r, v, T);
double put = monte_carlo_digital_put_price(num_sims, S, K, r, v, T);
// Finally we output the parameters and prices
std::cout << "Number of Paths: " << num_sims << std::endl;
std::cout << "Underlying: " << S << std::endl;
std::cout << "Strike: " << K << std::endl;
std::cout << "Risk-Free Rate: " << r << std::endl;
std::cout << "Volatility: " << v << std::endl;
std::cout << "Maturity: " << T << std::endl;
std::cout << "Call Price: " << call << std::endl;
std::cout << "Put Price: " << put << std::endl;
return 0;
}
和以前一样,我们可以看到 Box-Muller 函数以及通过蒙特卡罗方法为期权定价的函数。但是,我添加了 Heaviside 函数,这是数字期权支付所必需的。此外,我<algorithm>
从包含列表中删除了库,因为我们不需要max
这些支付的函数。最后的修改改变了payoff_sum
使用 Heaviside 函数的行。
// This is the Heaviside step function, named after English
// mathematician Oliver Heaviside. It returns unity when val
// is greater than or equal to zero and returns zero otherwise
double heaviside(const double& val) {
if (val >= 0) {
return 1.0;
} else {
return 0.0;
}
}
对 monte_carlo_digital_call_price 的修改如下:
..
payoff_sum += heaviside(S_cur - K);
..
该程序的输出如下:
Number of Paths: 10000000
Underlying: 100
Strike: 100
Risk-Free Rate: 0.05
Volatility: 0.2
Maturity: 1
Call Price: 0.532424
Put Price: 0.418726.
um += heaviside(S_cur - K);
我在此重申,本文与普通看涨期权和看跌期权的文章之间存在大量代码重复。对于那些尚未阅读过之前文章的人来说,我想为您提供数字期权的完整列表(并将为所有进一步的期权变体提供相同的列表)!稍后我们将通过为不同的期权收益创建自己的对象来考虑解决代码重复问题。