If we consider option as a whole, the basic components are expiration and payoff. We want to define a Vanilla Option class which has as data members a PayOff object and a double to represent expiry. However, we cannot directly hold a payoff object, because payoff class is an abstract class, and we do not want to hold a particular type of payoff in option class, because we want to achievepolymorphism. In plain words, we do not want the option class to know the exact type of payoff it is going to use in the future code. Similar to the monte carlo simulation function case, we have two solutions, one is hold a reference of payoff class in option class,
#ifndef VANILLAOPTION_HPP_INCLUDED
#define VANILLAOPTION_HPP_INCLUDED
class VanillaOption{
public:
VanillaOption(PayOff& payoff_, double expiry_):payoff(payoff_), expiry(expiry_){}
double GetExpiry() const{ return expiry; }
double OptionPayOff(double spot) const {
return payoff(spot);
}
private:
double expiry;
PayOff& payoff;
};
#endif // VANILLAOPTION_HPP_INCLUDED
Holding reference of PayOff class in VanillaOption class has several drawbacks. The most serious problem is that our vanilla option will not exists as independent object in its own right but will instead always
be dependent on the payoff object constructed outside the class. The user of the VanillaOption will not expect changes to the PayOff object to have such an effect If the PayOff object somehow is deleted before the use the VanillaOption object, the program
could crash. Therefore, we want to hold a PayOff class pointer in VanillaOption class. The blueprint could be
#ifndef VANILLAOPTION_HPP_INCLUDED
#define VANILLAOPTION_HPP_INCLUDED
class VanillaOption{
public:
VanillaOption(PayOff& payoff_, double expiry_);
VanillaOption(const VanillaOption& original);
VanillaOption& operator=(const VanillaOption& original);
virtual ~VanillaOption();
double GetExpiry() const;
double OptionPayOff(double spot) const;
private:
double expiry;
PayOff* payoff;
};
#endif // VANILLAOPTION_HPP_INCLUDED
Note that this time, we have copy constructor, destructor, operator= overload, following "rule of three", since we have a pointer as data member. We also need to modify the payoff classes.
#ifndef PAYOFF_HPP_INCLUDED
#define PAYOFF_HPP_INCLUDED
class PayOff{
public:
PayOff(){};
virtual double operator()(double spot) const = 0;
virtual PayOff* clone() const = 0;
virtual ~PayOff(){}
};
class PayOffCall : public PayOff{
public:
PayOffCall(double strike_):strike(strike_){}
virtual double operator()(double spot) const{
double value = spot - strike;
return (value > 0 ? value : 0);
}
virtual PayOff* clone() const {
return new PayOffCall(*this);
}
virtual ~PayOffCall(){}
private:
double strike;
};
class PayoffPut : public PayOff{
public:
PayOffPut(double strike_):strike(strike_){}
virtual double operator()(double spot) const {
double value = strike - spot;
return (value > 0 ? value : 0);
}
virtual PayOff* clone() const {
return new PayOffPut(*this);
}
virtual ~PayOffPut(){}
private:
double strike;
};
#endif // PAYOFF_HPP_INCLUDED
Use the new payoff class, we have the VanillaOption class
#ifndef VANILLAOPTION_HPP_INCLUDED
#define VANILLAOPTION_HPP_INCLUDED
#include<./payoff.hpp>
class VanillaOption{
public:
VanillaOption(PayOff& payoff_, double expiry_):expiry(expiry_){
payoff = payoff_.clone();
}
VanillaOption(const VanillaOption& original){
expiry = original.expiry;
payoff = original.payoff->clone();
}
VanillaOption& operator=(const VanillaOption& original){
if (this != &original){
expiry = original.expiry;
delete payoff;
payoff = original.payoff->clone();
}
return *this;
}
virtual ~VanillaOption(){ delete payoff; }
double GetExpiry() const { return expiry; }
double OptionPayOff(double spot) const { return (*payoff)(spot); }
private:
double expiry;
PayOff* payoff;
};
#endif // VANILLAOPTION_HPP_INCLUDED
The simple monte carlo rounte becomes #ifndef MONTECARLO_HPP_INCLUDED
#define MONTECARLO_HPP_INCLUDED
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
double SimpleMonteCarlo2(VanillaOption& option, double Expiry, double Spot, double Vol, double r, unsigned long NumberOfPaths){
const gsl_rng_type * T;
gsl_rng * rnd;
gsl_rng_env_setup();
T = gsl_rng_default;
rnd = gsl_rng_alloc (T);
double variance = Vol*Vol*Expiry;
double rootVariance = sqrt(variance);
double itoCorrection = -0.5*variance;
double movedSpot = Spot*exp(r*Expiry+itoCorrection);
double thisSpot;
double runningSum=0;
for (unsigned long i=0; i < NumberOfPaths; i++){
double thisGaussian = gsl_ran_gaussian(rnd, 1.0);
thisSpot = movedSpot*exp(rootVariance*thisGaussian);
double thisPayOff = option.OptionPayOff(thisSpot);
runningSum += thisPayOff;
}
double mean = runningSum / NumberOfPaths;
mean *= exp(-r*Expiry);
gsl_rng_free (rnd);
return mean;
}
#endif // MONTECARLO_HPP_INCLUDED