The implementation, in c++, of Black-Scholes pricer can be as followed:

Files
4 Header file
3 cpp file

Header file 1: BinModel02.h

#pragma once

class BinModel {
private:
	double S0, U, D, R;
public:
	double RiskNeutProb();
	double S(int n, int i);
	double GetR();
	double GetS0();
	double GetU();
	double GetD();
	BinModel(double S0_, double U_, double D_, double R_) 
	{
		S0 = S0_; U = U_; D = D_; R = R_;
	}
};

Header file 2: BinLattice02.h

#pragma once

#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;

template<typename Type> class BinLattice {
private:
	int N;
	vector< vector<Type> > Lattice;
public:
	void SetN(int N_) {
		N = N_;
		Lattice.resize(N + 1);
		for (int n = 0; n <= N; n++) Lattice[n].resize(n + 1);
	}

	void SetNode(int n, int i, Type x) { Lattice[n][i] = x; }

	Type GetNode(int n, int i) { return Lattice[n][i]; }

	void Display(ostream& stream) {
		stream << setiosflags(ios::fixed) << setprecision(6);
		for (int n = 0; n <= N; n++) {
			for (int i = 0; i <= n; i++)
				stream << setw(15) << GetNode(n, i);
			stream << endl;
		}
		stream << endl;
	}
};



Header file 3: Options09.h

#pragma once
#include "BinLattice02.h"
#include "BinModel02.h"

class Option {
private:
	int N; //steps to expiry
public:
	void SetN(int N_) { N = N_; }
	int GetN() { return N; }
	virtual double Payoff(double z) = 0;
};

class EurOption : public virtual Option {
public:
	//pricing European option
	double PriceByCRR(BinModel Model);
};

class AmOption : public virtual Option {
public:
	//pricing American option
	double PriceBySnell(BinModel Model, BinLattice<double>& PriceTree, BinLattice<bool>& StoppingTree);
};

class Call : public EurOption, public AmOption {
private:
	double K; //strike price
public:
	Call(int N_, double K_) { SetN(N_); K = K_; }
	double Payoff(double z);
};

class Put : public EurOption, public AmOption {
private:
	double K; //strike price
public:
	Put(int N_, double K_) { SetN(N_); K = K_; }
	double Payoff(double z);
};


Header file 4: Blackschole.h

#pragma once

#include <cmath>
#include "BinModel02.h"
using namespace std;

class Blackschole {
private:
	double S0, r, sigma;
public:
	Blackschole(double S0_, double r_, double sigma_)
	{
		S0 = S0_; r = r_; sigma = sigma_;
	}
	BinModel ApproxBinModel(double h) 
	{
		double U = exp( sigma * sqrt(h)) - 1;
		double D = (1 / (1 + U)) - 1;
		double R = exp(r * h) - 1;
		
		BinModel ApproxModel(S0, U, D, R);
		return ApproxModel;
	}
};

Cpp file 1: BinModel02.cpp

#include "BinModel02.h"
#include <iostream>
#include <cmath>
using namespace std;

double BinModel::RiskNeutProb() {return (R - D) / (U - D);}

double BinModel::S(int n, int i) {return S0 * pow(1 + U, i) * pow(1 + D, n - i);}

double BinModel::GetR() {return R;}

double BinModel::GetS0() {return S0;}

double BinModel::GetU() {return U;}

double BinModel::GetD() {return D;}

Cpp file 2 : Options09.cpp

#include "Options09.h"
#include "BinModel02.h"
#include "BinLattice02.h"
#include <iostream>
#include <cmath>
using namespace std;

double EurOption::PriceByCRR(BinModel Model) {
	double q = Model.RiskNeutProb();
	int N = GetN();
	vector<double> Price(N + 1);
	for (int i = 0; i <= N; i++)
		Price[i] = Payoff(Model.S(N, i));
	for (int n = N - 1; n >= 0; n--) {
		for (int i = 0; i <= n; i++)
			Price[i] = (q * Price[i + 1] + (1 - q) * Price[i]) / (1 + Model.GetR());
	}
	return Price[0];
}



double AmOption::PriceBySnell(BinModel Model, BinLattice<double>& PriceTree, BinLattice<bool>& StoppingTree) {
	double q = Model.RiskNeutProb();
	int N = GetN();
	PriceTree.SetN(N);
	StoppingTree.SetN(N);
	double ContVal;
	for (int i = 0; i <= N; i++) {
		PriceTree.SetNode(N, i, Payoff(Model.S(N, i)));
		StoppingTree.SetNode(N, i, 1);
	}
	for (int n = N - 1; n >= 0; n--) {
		for (int i = 0; i <= n; i++) {
			ContVal = (q * PriceTree.GetNode(n + 1, i + 1) + (1 - q) * PriceTree.GetNode(n + 1, i)) / (1 + Model.GetR());
			PriceTree.SetNode(n, i, Payoff(Model.S(n, i)));
			StoppingTree.SetNode(n, i, 1);
			if (ContVal > PriceTree.GetNode(n, i)) {
				PriceTree.SetNode(n, i, ContVal);
				StoppingTree.SetNode(n, i, 0);
			}
			else if (PriceTree.GetNode(n, i) == 0.0) {
				StoppingTree.SetNode(n, i, 0);
			}
		}
	}
	return PriceTree.GetNode(0, 0);
}

double Call::Payoff(double z) {
	if (z > K) return z - K;
	return 0.0;
}

double Put::Payoff(double z) {
	if (z < K) return K - z;
	return 0.0;
}

Cpp file 3 : main.cpp

#include <iostream>
#include "BinModel02.h"
#include "Options09.h"
#include "Blackschole.h"
using namespace std;

int main() {
	double S0 = 106.0;
	double r = 0.058;
	double sigma = 0.46;
	double T = (double)9 / 12;
	double K = 100.0;
	int N = 8;

	cout << setiosflags(ios::fixed) << setprecision(5);

	cout << "S0 = " << S0 << endl;

	cout << "r = " << r << endl;

	cout << "sigma = " << sigma << endl;

	cout << "T = " << T << endl;

	cout << "K = " << K << endl;

	cout << "N = " << N << endl;

	cout << endl;


	Blackschole Model(S0, r, sigma);
	double h = T / N;
	BinModel ApproxModel = Model.ApproxBinModel(h);

	cout << "U = " << ApproxModel.GetU() << endl;
	
	cout << "D = " << ApproxModel.GetD() << endl;
	
	cout << "R = " << ApproxModel.GetR() << endl;

	Call Option(N, K);
	BinLattice<double> PriceTree;
	BinLattice<bool> StoppingTree;

	Option.PriceBySnell(ApproxModel, PriceTree, StoppingTree);
	cout << "American call option price = "
		<< PriceTree.GetNode(0, 0)
		<< endl << endl;

	return 0;
}


/*

S0 = 106.00000
r = 0.05800
sigma = 0.46000
T = 0.75000
K = 100.00000
N = 8

U = 0.15125
D = -0.13138
R = 0.00545
American call option price = 21.68171



*/

Leave a comment

Trending