파일

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];
    }
}