Usually, tree is used to calculate American style options. We define our American style options as follows
#ifndef TREEPRODUCT_HPP_INCLUDED
#define TREEPRODUCT_HPP_INCLUDED
class TreeProducts {
public:
TreeProducts(double FinalTime_):FinalTime(FinalTime_){}
virtual ~TreeProducts(){}
virtual TreeProducts* clone() const = 0;
virtual double FinalPayOff(double spot) const = 0;
virtual double PreFinalValue(double spot, double time, double discountval) const = 0;
private:
double FinalTime;
};
class TreeAmerican : public TreeProduct {
public:
TreeAmerican(double FinalTime_, const PayOffBridge& payoff_):TreeProducts(FinalTime_), payoff(payoff_){}
virtual ~TreeAmerican(){}
virtual TreeProducts* clone() const { return new TreeAmerican(*this); }
virtual double FinalPayOff(double spot) const { return payoff(spot); }
virtual double PreFinalValue(double spot, double time, double discountval) const {
return (payoff(spot)>discountval ? payoff(spot) : discountval);
}
private:
PayOffBridge payoff;
};
class TreeEuropean : public TreeProduct {
public:
TreeEuropean(double FinalTime_, const PayOffBridge& payoff_):TreeProducts(FinalTime_), payoff(payoff_){}
virtual ~TreeEuropean(){}
virtual TreeProducts* clone() const { return new TreeEuropean(*this); }
virtual double FinalPayOff(double spot) const { return payoff(spot); }
virtual double PreFinalValue(double spot, double time, double discountval) const {
return discountval;
}
private:
PayOffBridge payoff;
};
#endif // TREEPRODUCT_HPP_INCLUDED
In order to calculate American style option, we need to calculate its payoff at final time, and at previous time points. Therefore, TreeProducts has a data member called FinalTime, and two virtual function, FinalPayOff() and PreFinalValue().
We have a seperate class for binominal tree
#ifndef SIMPLEBINOMIALTREE_HPP_INCLUDED
#define SIMPLEBINOMIALTREE_HPP_INCLUDED
using namespace std;
class SimpleBinomialTree {
public:
SimpleBinomialTree(double spot_, double r_, double d_, double vol_, int step_, double expiry_):
spot(spot_), r(r_), d(d_), vol(vol_), step(step_), expiry(expiry_){
discounts.resize(step_);
TreeBuilt = false;
}
double getPrice(const TreeProducts& product);
vector<vector<pair<double, double>>> getTree(){
return tree;
}
protected:
void BuildTree();
private:
double spot; // current stock price
double r; // risk-free interest rate
double d; // dividend yield
double vol; // volatility
int step; // number of tree steps
double expiry; // time-to-maurity
bool TreeBuilt; // whether the tree is built
vector<double> discounts;
vector<vector<pair<double, double>>> tree;
};
void SimpleBinomialTree::BuildTree(){
int i, j, k;
double thistime, movedlogspot, sd;
TreeBuilt = true;
tree.resize(step+1);
double inilogspot = log(spot);
for (i=0; i<=step; i++){
tree[i].resize(i+1);
thistime = (i*expiry)/step;
movedlogspot = inilogspot + (r-d-0.5*vol*vol)*thistime;
sd = vol*sqrt(expiry/step);
for(j=-i, k=0; j<=i; j=j+2,k++){
tree[i][k].first = exp(movedlogspot+j*sd);
}
}
for (i=0; i<step; i++){
discounts[i] = exp(-r*expiry/step);
}
}
double SimpleBinomialTree::getPrice(const TreeProducts& product){
int i, j, k, index;
double thistime, spot, futurediscountedvalue;
if (!TreeBuilt) BuildTree();
if (product.getFinalTime() != expiry) throw("Mismatching product!");
for (j=-step, k=0; j<=step; j=j+2,k++){
tree[step][k].second = product.FinalPayOff(tree[step][k].first);
}
for (i=1; i<=step; i++){
index = step - i;
thistime = index*expiry/step;
for(j=-index,k=0; j<=index; j=j+2,k++){
spot = tree[index][k].first;
futurediscountedvalue = 0.5*discounts[index]*(tree[index+1][k].second+tree[index+1][k+1].second);
tree[index][k].second = product.PreFinalValue(spot, thistime, futurediscountedvalue);
}
}
return tree[0][0].second;
}
#endif // SIMPLEBINOMIALTREE_HPP_INCLUDED
The main function is
#include <iostream>
#include <cmath>
#include <./payoff.hpp>
#include <./statisticsmc.hpp>
#include <./wrapper.hpp>
#include <./treeproduct.hpp>
#include <./simplebinomialtree.hpp>
#include <./payoffbridge.hpp>
int main(){
// set parameters
double spot = 15.0;
double expiry = 1.0;
double strike = 15.0;
double volatility = 0.4;
double r = 0.01;
double d = 0.0;
int step = 10;
PayOffCall payoffcall(strike);
TreeAmerican AOption(expiry, payoffcall);
SimpleBinomialTree bt(spot, r, d, volatility, step, expiry);
double price = bt.getPrice(AOption);
// print results
std::cout << "Option Price: " << std::endl;
std::cout << price << std::endl;
// print the tree
vector<vector<std::pair<double, double>>> tree = bt.getTree();
std::cout << "Print Tree Structure: " << std::endl;
for (unsigned long i=0; i<tree.size(); i++){
for (unsigned long j=0; j<tree[i].size(); j++){
std::cout << tree[i][j].first << "|" << tree[i][j].second << std::endl;
}
}
return 0;
}