파일
binomial.h
main.cpp
binomial.cpp
a.out
//binomial.h
#ifndef _BINOMIAL_H_
#define _BINOMIAL_H_
#pragma once
#include <math.h>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
void put_call_parity(double put, double call, double k, double r, double t, double S0);
enum class Types{ //Option Types
EuropeanCall,
EuropeanPut,
AmericanCall,
AmericanPut
};
class Tree {
private:
double t, S0, r, sigma, k;
int n;
double delta_t, u, d, p, q;
double** stockTree; //underlying stock tree
public:
Tree(double t_, int n_, double S0_, double r_, double sigma_, double k_);
void PrintTree();
double** getStockTree(); //return Stock Tree
double** EuropeanCall(); //return European Call Payoff Tree
double** EuropeanPut(); //return European Put Payoff Tree
double** AmericanCall(); //return American Call Payoff Tree
double** AmericanPut(); //return American Put Payoff Tree
~Tree();
};
// Payoff Tree to calculate Greeks
class Greeks {
private:
double t, S0, r, sigma, k;
int n;
double delta_t, u, d, p, q;
double** stockTree; //underlying stock tree
double** payoffTree; //payoff tree
public:
Greeks(double t_, int n_, double S0_, double r_, double sigma_, double k_, double** stockTree_, double** payoffTree_);
void PrintTree(); //Print Payoff Tree
//Greek
double delta();
double gamma();
double theta();
double vega(Types type);
~Greeks();
};
#endif
//binomial.cpp
#include "binomial.h"
void put_call_parity(double put, double call, double k, double r, double t, double S0){
cout << "call - put = " << call-put << endl;
cout << "S - PV(K) = " << S0 - k*exp(-r*t) << endl;
}
Tree::Tree(double t_, int n_, double S0_, double r_, double sigma_, double k_) { // Constructor
this->t = t_;
this->n = n_;
this->S0 = S0_;
this->r = r_;
this->sigma = sigma_;
this->k = k_;
// etc variable
this->delta_t = t/(n-1); //간격의 개수 = 시점 수 -1
this->u = exp(sigma*sqrt(delta_t)); //u: using Cox, Ross, and Rubinstein
this->d = 1/u;
this->p = (exp(r*delta_t) - d) / (u-d); //p: probability of upward
this->q = 1-p; //q: probability of downward
// 2-dimension array
// row: time, tree가 증가하면서 column 1개씩 증가
this->stockTree = new double*[n];
for(int i=0; i<n; i++) {
this->stockTree[i] = new double[i+1];
if(i==0) {this->stockTree[0][0] = S0;}
for(int j=0; j<i; j++){
this->stockTree[i][j] = this->stockTree[i-1][j] * this->u;
this->stockTree[i][j+1] = this->stockTree[i-1][j] * this->d;
}
}
}
void Tree::PrintTree(){ //트리 정보 출력
cout << "Stock Tree" << endl;
int n = this->n;
for(int i=0; i<n; i++) {
for(int j=0; j<=i; j++) {
cout << this->stockTree[i][j] <<"\n";
}
cout << endl;
}
}
double** Tree::getStockTree() { //구성한 기초자산 트리 return
return this->stockTree;
}
double** Tree::EuropeanCall() { // 아메리칸 콜 Tree
int n = this->n;
double** payoff = new double*[n]; //payoff tree (return)
for (int i=n-1; i>=0; i--) {
if ( i == n-1 ){ // 만기 일 때
payoff[i] = new double[i+1];
for ( int j = 0; j < n; j++ ) {
payoff[n-1][j] = this->stockTree[n-1][j] - k; //s-k
if ( payoff[n-1][j] < 0 ) {payoff[n-1][j] = 0;} //max(s-k, 0)
}
}
else { //만기가 아닐 때
payoff[i] = new double[i+1];
for (int j=0 ; j <=i; j++) {
payoff[i][j] = (p*payoff[i+1][j] + q*payoff[i+1][j+1]) * exp(-r * delta_t);
}
}
}
return payoff; //return payoff tree
}
double** Tree::EuropeanPut(){ // 아메리칸 풋 Tree
int n = this->n;
double** payoff = new double*[n]; //payoff tree
for (int i=n-1; i>=0; i--) {
if ( i == n-1 ){ // 만기 일 때
payoff[i] = new double[i+1];
for ( int j = 0; j < n; j++ ) {
payoff[n-1][j] = k - this->stockTree[n-1][j]; //k-s
if ( payoff[n-1][j] < 0 ) {payoff[n-1][j] = 0;} //max(k-s, 0)
}
}
else { //만기가 아닐 때
payoff[i] = new double[i+1];
for (int j=0 ; j <=i; j++) {
payoff[i][j] = (p*payoff[i+1][j] + q*payoff[i+1][j+1]) * exp(-r * delta_t);
}
}
}
return payoff;
}
double** Tree::AmericanCall() { //아메리칸 콜
int n = this->n;
double** payoff = new double*[n]; //payoff tree
for (int i=n-1; i>=0; i--) {
if ( i == n-1 ){ // 만기 일 때
payoff[i] = new double[i+1];
for ( int j = 0; j < n; j++ ) {
payoff[n-1][j] = this->stockTree[n-1][j] - k; //s-k
if ( payoff[n-1][j] < 0 ) {payoff[n-1][j] = 0;} //max(s-k, 0)
}
}
else { //만기가 아닐 때
payoff[i] = new double[i+1];
for (int j=0 ; j <=i; j++) {
double not_ex = (p*payoff[i+1][j] + q*payoff[i+1][j+1]) * exp(-r * delta_t);
double yes_ex = this->stockTree[i][j] - k;
if (not_ex > yes_ex){
payoff[i][j] = not_ex;
}
else {
payoff[i][j] = yes_ex;
}
}
}
}
return payoff;
}
double** Tree::AmericanPut() { //아메리칸 풋
int n = this->n;
double** payoff = new double*[n]; //payoff tree
for (int i=n-1; i>=0; i--) {
if ( i == n-1 ){ // 만기 일 때
payoff[i] = new double[i+1];
for ( int j = 0; j < n; j++ ) {
payoff[n-1][j] = k - this->stockTree[n-1][j]; //k-s
if ( payoff[n-1][j] < 0 ) {payoff[n-1][j] = 0;} //max(k-s, 0)
}
}
else { //만기가 아닐 때
payoff[i] = new double[i+1];
for (int j=0 ; j <=i; j++) {
double not_ex = (p*payoff[i+1][j] + q*payoff[i+1][j+1]) * exp(-r * delta_t);
double yes_ex = k - this->stockTree[i][j];
if (not_ex > yes_ex){
payoff[i][j] = not_ex;
}
else {
payoff[i][j] = yes_ex;
}
}
}
}
return payoff;
}
Tree::~Tree() {
int n = this->n;
for(int i=0; i<n; i++){ //delete the stock tree
delete[] this->stockTree[i];
}
}
// Payoff Tree to calculate Greeks
Greeks::Greeks(double t_, int n_, double S0_, double r_, double sigma_, double k_, double** stockTree_, double** payoffTree_){
this->t = t_;
this->n = n_;
this->S0 = S0_;
this->r = r_;
this->sigma = sigma_;
this->k = k_;
// etc variable
this->delta_t = t/(n-1); //간격의 개수 = 시점 수 -1
this->u = exp(sigma*sqrt(delta_t)); //u: using Cox, Ross, and Rubinstein
this->d = 1/u;
this->p = (exp(r*delta_t) - d) / (u-d); //p: probability of upward
this->q = 1-p; //q: probability of downward
// Get Stock Tree and Payoff Tree
this->stockTree = stockTree_;
this->payoffTree = payoffTree_;
}
void Greeks::PrintTree() { //Print the Payoff Tree
cout << "Payoff Tree" << endl;
int n = this->n;
for(int i=0; i<n; i++) {
for(int j=0; j<=i; j++) {
cout << this->payoffTree[i][j] <<"\n";
}
cout << endl;
}
}
double Greeks::delta() { //Calculate delta
double delta_;
delta_ = (payoffTree[1][0] - payoffTree[1][1])/((u-d)*S0);
return delta_;
}
double Greeks::gamma(){ //Calculate gamma
double gamma_;
double a1 = (payoffTree[2][0] - payoffTree[2][1]) / ((pow(u,2) - 1)*S0);
double a2 = (payoffTree[2][1] - payoffTree[2][2]) / ((1 - pow(d,2))*S0);
double h = 0.5*S0*(pow(u,2)-pow(d,2));
gamma_ = (a1-a2) / h;
return gamma_;
}
double Greeks::theta(){ //Calculate theta
double theta_;
theta_ = (payoffTree[2][1] - payoffTree[0][0]) / (2*delta_t);
return theta_;
}
double Greeks::vega(Types type){ //Calculate vega
double vega_;
double new_sigma = sigma + 0.01; // new volatility
double original_payoff, new_payoff;
Tree STree0(t, n, S0, r, sigma, k);
Tree STree1(t, n, S0, r, new_sigma, k);
switch(type){
case Types::EuropeanCall:
original_payoff = STree0.EuropeanCall()[0][0]; // original payoff with original volatility
new_payoff = STree1.EuropeanCall()[0][0]; // new payoff with new volatility
break;
case Types::EuropeanPut:
original_payoff = STree0.EuropeanPut()[0][0]; // original payoff with original volatility
new_payoff = STree1.EuropeanPut()[0][0];
break;
case Types::AmericanCall:
original_payoff = STree0.AmericanCall()[0][0]; // original payoff with original volatility
new_payoff = STree1.AmericanCall()[0][0];
break;
case Types::AmericanPut:
original_payoff = STree0.AmericanPut()[0][0]; // original payoff with original volatility
new_payoff = STree1.AmericanPut()[0][0];
break;
default:
original_payoff = 0;
new_payoff = 0;
break;
vega_ = (new_payoff - original_payoff) / (0.01); // (f'-f)/(delat_sigma)
}
return vega_;
}
Greeks::~Greeks(){}
//main.cpp
#define _CRT_SECURE_NO_DEPRECATE
#include "binomial.h"
int main(){
double t, S0, r, sigma, k;
int n;
// Get input
cout << "time, S0, r, sigma, n, k" <<endl;
cin >> t >> S0 >> r >> sigma >> n >> k;
n = n+1; // 0시점을 포함한 개수로 한개 증가 시켜야함
Tree STree(t, n, S0, r, sigma, k); // Make Stock Tree
STree.PrintTree(); // Print Stock Tree
double** underlyingTree = STree.getStockTree(); // Get Stock Tree
// European Call Price
double** Ecall_tree = STree.EuropeanCall();
// European Put Price
double** Eput_tree = STree.EuropeanPut();
// American Call Price
double** Acall_tree = STree.AmericanCall();
// American Put Price
double** Aput_tree = STree.AmericanPut();
cout << "European call_price: " << Ecall_tree[0][0] << endl;
cout << "European put_price: " << Eput_tree[0][0] << endl;
cout << "American call_price: " << Acall_tree[0][0] << endl;
cout << "American put_price: " << Aput_tree[0][0] << endl;
cout << "[put-call parity]" <<endl;
put_call_parity(Eput_tree[0][0], Ecall_tree[0][0], k, r, t, S0);
//Print the Greeks
cout << "\n[Greeks]" << endl;
//Choose one of the tree
cout << "Choose type of Option\n"
"1. European Call\n"
"2. European Put\n"
"3. American Call\n"
"4. American Put\n"<< endl;
int ch;
cin >> ch;
switch(ch){
case 1: //European Call
{Greeks greek(t, n, S0, r, sigma, k, underlyingTree, Ecall_tree);
//greek.PrintTree(); //Print payoff Tree
cout << "delta: "<< greek.delta() << endl;
cout << "gamma: " << greek.gamma() << endl;
cout << "theta: " << greek.theta() << endl;
cout << "vega: "<< greek.vega(Types::EuropeanCall) << endl;}
break;
case 2: //European Put
{Greeks greek(t, n, S0, r, sigma, k, underlyingTree, Eput_tree);
//greek.PrintTree(); //Print payoff Tree
cout << "delta: "<< greek.delta() << endl;
cout << "gamma: " << greek.gamma() << endl;
cout << "theta: " << greek.theta() << endl;
cout << "vega: "<< greek.vega(Types::EuropeanPut) << endl;}
break;
case 3: //American Call
{Greeks greek(t, n, S0, r, sigma, k, underlyingTree, Acall_tree);
//greek.PrintTree(); //Print payoff Tree
cout << "delta: "<< greek.delta() << endl;
cout << "gamma: " << greek.gamma() << endl;
cout << "theta: " << greek.theta() << endl;
cout << "vega: "<< greek.vega(Types::AmericanCall) << endl;}
break;
case 4: // American Put
{Greeks greek(t, n, S0, r, sigma, k, underlyingTree, Aput_tree);
//greek.PrintTree(); //Print payoff Tree
cout << "delta: "<< greek.delta() << endl;
cout << "gamma: " << greek.gamma() << endl;
cout << "theta: " << greek.theta() << endl;
cout << "vega: "<< greek.vega(Types::AmericanCall) << endl;}
break;
default:
break;
}
for(int i=0; i<n; i++){ //delete the tree
delete[] Ecall_tree[i];
delete[] Eput_tree[i];
delete[] Acall_tree[i];
delete[] Aput_tree[i];
}
}