finance c++ programming course [part 3] – Monte Carlo c++

Part 3

c++ finance course

Monte-Carlo c++

Objective

– generate random numbers
– Calculate Call option with Monte – Carlo
– intro to std::vector

here we’ll see how to use containers in C++

in many books on c++ you’ll see that people use c++ arrays ( for example double x[10]) for storing variables.It has quite many drawbacks for beginners , so here we’ll use std::vector to store real numbers.
std::vector is an object – it means you add dot “.” after the object name and you will see it has not only one value but many different “sub-variables” and “sub-functions”

Gaussian random number generation

To implement Monte-Carlo engine in C++ we’ll need standard gaussian numbers.
C++ has a built-in random number generators , but they are no good for financial engineering (function random()).

One of the most used pseudo – random generators with good characteristics is Mersenne Twister algorithm
It’s implemented in Boost. After we have uniform random numbers we can generate Gaussian number with a function.It’s also implemented in Boost.
here’s the code to generate 100 standard gaussians:

#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>



void main()
{

    boost::mt19937 mt; //create object of mersenne twister generator
    boost::normal_distribution<> distribution; // create distribution object
    boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>* normal(new boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>(mt,distribution)); //create variate generator which will generate gaussians
	
	for (int i=0;i<100;i++)
           std::cout<< (*normal)()<<std::endl; //  gaussian is retrieved with function   (*normal)()     asterisk * is because normal variable is a pointer 
	
    int dummy;std::cin>>dummy;
}

here we use a pointer to variable.
pointer is basically address of variable in memory.
to access variables by pointers one uses asterisk *
read more about pointers here

Storage of data in std::vector

to store these numbers we can use class std::vector
read more about this class here

here we’ll illustrate its common use:

#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>
#include <vector>


void main()
{

    boost::mt19937 mt; 
    boost::normal_distribution<> distribution;
    boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>* normal    (new boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>(mt,distribution));
	
    std::vector<double> v;

    for (int i=0;i<100;i++)
	v.push_back( (*normal)() ) ;
	
     for (int i=0;i<100;i++)
	std::cout<<v[i]<<std::endl;
	
int dummy;std::cin>>dummy;
}

now lets make a function to calculate the mean of elements of vector

#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>
#include <vector>


double mean(std::vector<double>& v) //here we use &  to indicate that we pass value of variable to function by address and not by creating new variable and copying data into it
{
	int N=v.size();
	double sum=0;
	for(int i=0;i<N;i++)
		sum+=v[i];
	return sum/N;

}

void main()
{

	boost::mt19937 mt; 
    boost::normal_distribution<> distribution;
    boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>* normal(new boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>(mt,distribution));
	
	std::vector<double> v;

	for (int i=0;i<100;i++)
		v.push_back( (*normal)() ) ;
	
	for (int i=0;i<100;i++)
		std::cout<<v[i]<<std::endl;
	
	std::cout<<"\nmean="<<mean(v);

	int dummy;std::cin>>dummy;
}

here we’ve shown how to to pass vectors as function parameters
most useful vector expressions are:

std::vector<double> v;//create empty vector
std::vector<double> v(10);//create vector of 10 elements  first element is v[0]
v[0]=4;//set value of first vector element;
v.resize(100);//resize vector to have 100 elements;
v.size();//returns number of elements

if you want to make simple operations on vectors there are chances that these operations are already implemented in STL or in boost.
for example our previous program to compute mean of array could be rewritten using STL algorithms as following:

sum =std::accumulate(v.begin(),v.end(),0.0); //need to #include <numeric>

so before writing a function to do simple things on vector google first somthing among the lines “std::vector sum of elements”

Exercise

– change previous program to calculate variance of random numbers

as we have random numbers now we are ready to implement call option price

Call option with monte carlo c++

suppose Black-Scholes dynamics with 0 interest rates, so
S_T=S_0 exp(-0.5 \sigma^2 T + \sigma \sqrt{T} x )
where x is standard gaussian

Monte-Carlo Call price is just average of payoffs  (S_T(x)-K)^+

#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>


double pp(double x) //positive part   x+   
{
if(x>0) return x;
return 0;
}

void main()
{

	boost::mt19937 mt; 
	boost::normal_distribution<> distribution;
	boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>* normal(new boost::variate_generator<boost::mt19937&,boost::normal_distribution<>>(mt,distribution));
	
	int numberSimulations=100000;

	double S0=100.0;
	double sigma=0.2;
	double T=1.0;
	double K=100.0;
	double sum=0;
	double payoff=0;

	for(int iSim=0;iSim<numberSimulations;iSim++)
	{
		double x=(*normal)();
		payoff=pp(S0*std::exp(-0.5*sigma*sigma*T+sigma*std::sqrt(T)*x)-K);
		sum+=payoff;
	}
	
	
	std::cout<<"\nCall="<<sum/numberSimulations<<std::endl;
	
	int dummy;std::cin>>dummy;
}


Exercises

– change program to include non-zero constant interest rate
– change program to calculate Put option price
– verify call put parity

Posted in quant finance coding course