Uploaded by Denis Wolf

Monte carlo and variance reduction for option pricing in C++ RISQUOPHOBY

advertisement
RISQUOPHOBY
Bibliography
Notes
Tools
Webography
About
Monte carlo and variance reduction for
option pricing in C++
Jan 1, 2018
Monte Carlo method (Implementation in C++)
Monte Carlo method : Definition
“Monte Carlo methods (or Monte Carlo experiments) are a broad class of computational algorithms that
rely on repeated random sampling to obtain numerical results. Their essential idea is using randomness
to solve problems that might be deterministic in principle. They are often used in physical and
mathematical problems and are most useful when it is difficult or impossible to use other approaches.
Monte Carlo methods are mainly used in three distinct problem classes:[1] optimization, numerical
integration, and generating draws from a probability distribution.” :
https://en.wikipedia.org/wiki/Monte_Carlo_method
Monte Carlo method and variance reduction
Monte carlo method execution can be very long in computation time, so there are some methods called
variance reduction method that help reduce computation time then accelerate the convergence of the
method and reduce the confidence intervall.
Call pricing with monte carlo
The price or premium of a call is his probable payoff discounted. So knowing the payoff of a call, the
premium is : C all t = max(S − K , 0) × e−r(T −t)
At t, it is impossible to know exactly what will be the payoff at T the maturity of the Call, because of the
price of a underliying follow a stochastic process, So the payoff is expected. Then :
C all t = e
−r(T −t)
+
× E((S − K )
)
To compute the call price by monte carlo
C++ Code
The code below is c++ code that compute the premium of a call using monte carlo method and then
use variance reduction method to
#include <random>
#include <iostream>
#include <cmath>
#include <algorithm>
// fonctions declarations
double alea_uniform_dist();
double alea_normal_dist(const double& stddev);
double alea_normal_dist(const double& moydev, const double& stddev);
// fonction de calcul de moyenne
template<typename T, typename S>
T moyenne(S tab[], int& taille){
T somme(0);
for (int i(0);i<taille;i++){
somme = somme + tab[i];
}
return somme/taille;
}
// fonction de calcul de variance sans biais
template<typename T, typename S>
T variance( S tab[], int& taille){
T variance_quad(0);
for (int i(0);i<taille;i++){
variance_quad = variance_quad + (tab[i]-moyenne<T,S>(tab, taille))*(tab[i]-moyen
}
return variance_quad/(taille-1);
}
//*************************************************************************************
//************************************************MAIN*********************************
int main()
{
// Print Application title
std::cout << "EUROPEAN CALL OPTION PRICING WITH THE MONTE CARLO METHOD"<<std::endl;
std::cout << "********************************************************"<<std::endl;
// 1 PARAMETERS INITIALISATION
// Parameters of the call option that we want to price
double S0(100); // actual price of the underlying
double K(100); // the strike of the call option
double r(0.05); // risk free rate
double T(1.0); // the maturity of the option
double sigma(0.10); // the volatility of the underlying, for simplification we take
int N(252); // number of period per year
int M(100000); // number of simulation;1000-1,18sec-4.3802 10000-11,649sec-4.37739;
double S[N+1]; S[0] = S0;// the path of the underlying, the fist element is the actu
double dt(T/N); // time step of the underlying simulation
double payoffs[M]; //
double premium(0);
double stddev(1.0);
// print Input parameters
std::cout << "THE CALL PARAMETERS :"<<std::endl;
std::cout << "S0 = " << S0 <<std::endl;
std::cout << "K = " << K <<std::endl;
std::cout << "r = " << r <<std::endl;
std::cout << "T = " << T <<std::endl;
std::cout << "sigma = " << sigma <<std::endl;
std::cout << "Monte carlo number of simulations = " << M <<std::endl;
std::cout << "********************************************************"<<std::endl;
std::cout << "REAL CALL PREMIUM COMPUTE WITH B&S: 6,80495 " <<std::endl;
std::cout << "********************************************************"<<std::endl;
// 2 Payoffs simulations loop
for(int j(0);j<M;j++){
// 3 path simulation loop
for(int i(0);i<N+1;i++){
S[i+1] = S[i]*exp((r-(0.5*sigma*sigma))*dt+sigma*sqrt(dt)*alea_normal_dist(0.0,
}
// 4 compute the sum of payoffs of the simulations
payoffs[j] = std::max(S[N] - K,0.0);
}
// 5 Dicounted expected premium computation
double moypayoff(moyenne<double,double>(payoffs,M)); // simulated payoff mean estima
premium = exp(-r*T)*(moypayoff); // Actualise la moyenne des payoff pour fournir le
// estimation precisions details
double pay_stddev(0); // standard deviation of the payoffs simulated
pay_stddev = sqrt(variance<double,double>(payoffs,M)); // standard deviation of the
// print the premium value
std::cout << "********************************************************"<<std::endl;
std::cout << "THE SIMULATION DETAILS : "<<std::endl;
std::cout << "The payoffs mean: "<< moypayoff << std::endl;
std::cout << "The premium of the call option is : "<<premium << std::endl;
//std::cout << "The payoffs std_deviation : "<< pay_stddev << std::endl;
std::cout << "confidence interval of the mean estimation: [" << premium-2*(pay_stdde
std::cout << "The confidence interval size: "<< (premium+2*(pay_stddev/sqrt(M))) -
// ********************************************************************************
// *************************************************** REDUCTION DE VARIANCE ******
// ***************************************************** 1 VARIABLE ANTITETHIC ****
// 2 Payoffs simulations loop
// In this loop we replace half of the payoff already simulated with the antithetic
for(int j(0);j<M;j++){
// 3 path simulation loop
for(int i(0);i<N+1;i++){
S[i+1] = S[i]*exp((r-(0.5*sigma*sigma))*dt+sigma*sqrt(dt)*-alea_normal_dist(0.0
}
// 4 compute the sum of payoffs of the simulations
payoffs[j] = (payoffs[j] + std::max(S[N] - K,0.0))/2;
}
//double moypayoff_ant(moyenne<double,double>(payoffs,M)); // simulated payoff mean
double moypayoff_rant((moyenne<double,double>(payoffs,M))); // moyenne des payoffs o
premium = exp(-r*T)*(moypayoff_rant); // Actualise la moyenne des payoff pour fourni
double pay_stddev_ant(0); // standard deviation of the payoffs simulated with antith
pay_stddev_ant = sqrt(variance<double,double>(payoffs,M)); // standard deviation of
// print the premium value
std::cout << "********************************************************"<<std::endl;
std::cout << "THE ANTITHETIC VARIATE OPTIMISATION SIMULATION DETAILS : "<<std::endl
std::cout << "The payoffs mean: "<< moypayoff_rant << std::endl;
std::cout << "The premium of the call option is : "<<premium << std::endl;
//std::cout << "The payoffs std_deviation : "<< pay_stddev_ant << std::endl;
std::cout << "confidence interval of the mean estimation: [" << premium-2*(pay_stdde
std::cout << "The confidence interval size: "<< (premium+2*(pay_stddev_ant/sqrt(M))
// ********************************************************************************
// ******************************************************** 2 CONTROL VARIATE TECHNI
// Simulation of put payoffs to valuate the call
for(int j(0);j<M;j++){
// 3 path simulation loop
for(int i(0);i<N+1;i++){
S[i+1] = S[i]*exp((r-(0.5*sigma*sigma))*dt+sigma*sqrt(dt)*alea_normal_dist(0.0,
}
// 4 compute the sum of payoffs of the simulations
payoffs[j] = exp(r*T)*S0 - K + std::max(K - S[N] ,0.0); // PUT PAYOFF
}
double callpayoff(0);
callpayoff = moyenne<double,double>(payoffs,M); // CALL VALUE DEDUCES FROM CALL-PUT
premium = exp(-r*T)*(callpayoff); // Actualise la moyenne des payoff pour fournir le
double pay_stddev_varcontr(0); // standard deviation of the payoffs simulated with a
pay_stddev_varcontr = sqrt(variance<double,double>(payoffs,M)); // standard deviatio
std::cout << "********************************************************"<<std::endl;
std::cout << "THE CONTROL VARIATE OPTIMISATION DETAILS : "<<std::endl;
std::cout << "The payoffs mean: "<< callpayoff << std::endl;
std::cout << "The premium of the call option is : "<< premium << std::endl;
//std::cout << "The payoffs std_deviation : "<< pay_stddev_varcontr << std::endl;
std::cout << "confidence interval of the mean estimation: [" << premium-2*(pay_stdde
std::cout << "The confidence interval size: "<< (premium+2*(pay_stddev_varcontr/sqrt
// ********************************************************************************
// ******************************************************** 3 FONCTION D'IMPORTANCE
// Simulation of put payoffs to valuate the call *
// CALL TRES DEHORS DE LA MONNAIE
for(int j(0);j<M;j++){
// 3 path simulation loop
for(int i(0);i<N+1;i++){
S[i+1] = S[i]*exp((r-(0.5*sigma*sigma))*dt+sigma*sqrt(dt)*alea_normal_dist(-0.01
}
// 4 compute the sum of payoffs of the simulations
payoffs[j] = std::max(S[N] - K,0.0);
}
// 5 Dicounted expected premium computation
moypayoff = moyenne<double,double>(payoffs,M); // simulated payoff mean estimation
premium = exp(-r*T)*(moypayoff); // Actualise la moyenne des payoff pour fournir le
// estimation precisions details
pay_stddev = sqrt(variance<double,double>(payoffs,M)); // standard deviation of the
// print the premium value
std::cout << "********************************************************"<<std::endl;
std::cout << "THE IMPORTANCE FUNCTION OPTIMISATION : "<<std::endl;
std::cout << "The payoffs mean: "<< moypayoff << std::endl;
std::cout << "The premium of the call option is : "<<premium << std::endl;
//std::cout << "The payoffs std_deviation : "<< pay_stddev << std::endl;
std::cout << "confidence interval of the mean estimation: [" << premium-2*(pay_stdde
std::cout << "The confidence interval size: "<< (premium+2*(pay_stddev/sqrt(M))) //verifying that the program finish
return 0; //verifying that the program finish
}
// fonctions code
// Generate a number with follow a uniform distribution
// : http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution
double alea_uniform_dist(){
// generate random uniform numbers by c++11
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_real_distribution<> dis(0.0, 1.0);
//Use dis to transform the random unsigned int generated by gen into a double in [0,
return dis(gen); //Each call to dis(gen) generates a new random double
}
// Generate a number with follow a gaussian distribution
// : http://en.cppreference.com/w/cpp/numeric/random/normal_distribution
double alea_normal_dist(const double& stddev){
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::normal_distribution<> dis(0.0, stddev);
return dis(gen);
}
double alea_normal_dist(const double& moydev, const double& stddev){
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::normal_distribution<> dis(moydev, stddev);
return dis(gen);
}
Here is below the result of the execution of tje above c++ code.
So the code implement a monte carlo method for call pricing. The datails of the call are listed below.
Using the call formula of black and scholes i get the exact price of the call and then i perform a monte
carlo method to try to find the same price as the call formula. I perform a classic monte carlo method,
the three methods of varaiance reduction that are :
Antithetic variate
Control variate
Importance funtion
for each implementation i also compute the confidence intervall of the approximation of the call
premium. That confidence intervall uses the central limit theorem to show the convergence’s speed of
the method and the error intervall. So less the confidence intervall is large better the convergence’s
speed is. It is also important that the exact premium value be in the confidence intervall.
For the test, i compute a call value of 6,80495 obtain with B&S, then i implement monte carlo and
variance reduction method on the same call caracteristics to compare accuracy. In order from the less
precise to the more precise :
IMPORTANCE FUNCTION < ANTITHETIC VARIATE < CLASSIC MONTE CARLO < CONTROL VARIABLE
The importance funtion variance reduction method is a method specialy adapted for “in the money”
and “out the money” Call option.
EUROPEAN CALL OPTION PRICING WITH THE MONTE CARLO METHOD
********************************************************
THE CALL PARAMETERS :
S0 = 100
K = 100
r = 0.05
T = 1
sigma = 0.1
Monte carlo number of simulations = 100000
********************************************************
REAL CALL PREMIUM COMPUTE WITH B&S: 6,80495
********************************************************
********************************************************
THE SIMULATION DETAILS :
The payoffs mean: 7.13361
The premium of the call option is : 6.7857
confidence interval of the mean estimation: [6.73429 ; 6.83711]
The confidence interval size: 0.102827
********************************************************
THE ANTITHETIC VARIABLE OPTIMISATION SIMULATION DETAILS :
The payoffs mean: 7.12914
The premium of the call option is : 6.78145
confidence interval of the mean estimation: [6.74515 ; 6.81774]
The confidence interval size: 0.0725883
********************************************************
THE CONTROL VARIABLE OPTIMISATION DETAILS :
The payoffs mean: 7.15181
The premium of the call option is : 6.80301
confidence interval of the mean estimation: [6.77777 ; 6.82825]
The confidence interval size: 0.050481
********************************************************
THE IMPORTANCE FUNCTION OPTIMISATION :
The payoffs mean: 6.01899
The premium of the call option is : 5.72544
confidence interval of the mean estimation: [5.67772 ; 5.77316]
The confidence interval size: 0.0954378
Process returned 0 (0x0)
Press ENTER to continue.
References
execution time : 567.752 s
Advanced quantitative finance with c++
Wikipedia
and some master degree lectures that i found on internet, thanks google.
RISQUOPHOBY
RISQUOPHOBY
kevinbamouni
kevin-cedricbamouni
I Read, Code then Test.
Download