Monday, March 14, 2011

Black scholes calculator in C++

For object oriented programming 2, our first assignment was to build a black scholes calculator in C++.

The code here:
/************ chee tji hun OOP2 Assignment 1***********/

#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>
#include <cmath>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

class Option{
public:
/**** constructors ****/
Option(const string &name, double price, double strike, double rfRate,double stdev,double timeToMat);

/**** Methods ****/
double getCallPrice() const;//calculates the call price
double getPutPrice() const;//calculates the put price
static double erf(double zIn);//calculates the error function
string printStatement() const; //prints the data of the option, as well as the call/put price

/**** Getter/setters ****/
double getPrice() const;
double getRfRate() const;
double getStrike() const;
double getTimeToMat() const;
string getName() const;
double getStdev() const;
void setPrice(double price);
void setRfRate(double rfRate);
void setStrike(double strike);
void setTimeToMat(double timeToMat);
void setName(string name);
void setStdev(double stdev);

private:
string name; //name of underlying asset
double price; //price of the underlying asset
double rfRate; //risk free rate in ratio, 1 = 100%
double timeToMat; //time to maturity in terms of years
double stdev; //standard deviation of price of underlying asset
double strike; //strike price of the option

};

Option::Option(const string &name= "unnamed", double price=0.0, double strike=0.0, double rfRate=0.0,double stdev=0.0,double timeToMat=0.0){
this->name=name;
this->price=price;
this->strike=strike;
this->rfRate=rfRate;
this->stdev=stdev;
this->timeToMat=timeToMat;
}

double Option::getPrice() const
{
return price;
}

double Option::getRfRate() const
{
return rfRate;
}

double Option::getStrike() const
{
return strike;
}

double Option::getTimeToMat() const
{
return timeToMat;
}

string Option::getName() const
{
return name;
}

double Option::getStdev() const
{
return stdev;
}


void Option::setPrice(double price)
{
this->price = price;
}

void Option::setRfRate(double rfRate)
{
this->rfRate = rfRate;
}

void Option::setStrike(double strike)
{
this->strike = strike;
}

void Option::setTimeToMat(double timeToMat)
{
this->timeToMat = timeToMat;
}

void Option::setName(string name)
{
this->name = name;
}

string Option::printStatement() const
{
stringstream ss (stringstream::in | stringstream::out);
ss<<this->name<<" "<<this->price<<" "<<this->strike<<" "<<this->rfRate<<" "<<this->stdev<<" "<<this->timeToMat;
return ss.str();
}

void Option::setStdev(double stdev)
{
this->stdev = stdev;
}


//returns put price of the option
double Option::getPutPrice() const {
double callPrice = getCallPrice(); //set call price here
return strike*pow(M_E, -rfRate*timeToMat)-price+callPrice;
}

//returns call price of the option
double Option::getCallPrice() const{
double d1=log(price/strike)+(rfRate+0.5*pow(stdev,2.0)*timeToMat)/(stdev/sqrt(timeToMat));
double d2=d1-stdev*sqrt(timeToMat);
return price*erf(d1)-strike*pow(M_E,-rfRate*timeToMat)*erf(d2);
}

//returns approximation of error function given an upper/lower limit, zIn
double Option::erf(double zIn){
double z=(zIn<0.0)?-zIn:zIn; //take abs value of zIN
double t=(1.0/(1.0+z/2.0));
double power=
-pow(z,2.0)-1.26551223+1.00002368*t+0.37409196*pow(t,2.0)+0.09678418*pow(t,3.0)-0.18628806*pow(t,4.0)
+0.27886807*pow(t,5.0)-1.13520398*pow(t,6.0)+1.48851587*pow(t,7.0)-0.82215223*pow(t,8.0)+0.17087277*pow(t,9.0);

return 1.0-t*pow(M_E, power)*((zIn<0.0)?-1:1);//multiply erfResult with -1 if zIn is negative
}

class Account{
public:
/**** Constructors/Destructors ****/
Account(string name);
~Account();

/**** Methods ****/
void addOption(Option *option); //add an option to this account
string printStatement() const; //print all the option data, put/get prices in this account

/**** Getter/setters ****/
string getName() const;
void setName(string name);

private:
string name;
Option *options[];
unsigned int numOfOptions;
};

string Account::getName() const
{
return name;
}


void Account::setName(string name)
{
this->name = name;
}

string Account::printStatement() const
{
string line="---------------------------------------------------------------------------";
stringstream ss (stringstream::in | stringstream::out);
ss<<"Name: "+name+"\n";
ss<<line<<+"\n";
if (numOfOptions<=0) ss<<"no option records";
for(unsigned int i=0;i<numOfOptions;i++){
ss<<options[i]->printStatement()+"\n";
}
return ss.str();
}

Account::Account(string name="unnamed")
{
this->numOfOptions=0;//number of options in this account is zero
this->name=name;//name of the account
}

Account::~Account()
{
for(unsigned int i=0;i<numOfOptions;i++){//go through each option in the array and call their destructors
delete options[i];
}
}

void Account::addOption(Option* option)
{

}

class System{

public:
void start()const;
void exit() const;
void showMainMenu(); //add/edit accounts, print account statements, save accounts
void showAccountMenu(); //add/edit options, go back to main Menu
void retreiveAccounts() const; //un-serializes accounts into memory
void saveAccounts() const;//serializes accounts into file
int genMenuForUserSelection(vector<string> menuOptions) const;//takes menuoptions and generates a menu, returns user's selection


private:
vector<Account> accounts;
};

int System::genMenuForUserSelection(vector<string> menuOptions) const{
string errorMessage="";
while (true){
cout<<endl<<endl<<endl<<endl;
int input=0;
string line="---------------------------------------------------------------------------";
cout<<line<<endl;
for(unsigned int i=0;i<menuOptions.size();i++){
cout<<i<<") "<<menuOptions[i]<<endl;
}
cout<<line<<endl;
cout<<errorMessage<<"please make a selection from (0 to "<<menuOptions.size()<<")"<<endl;
cin>>input;
if(cin){//check if cin failed
if(input<menuOptions.size() && input>=0){ //check if the input is valid menu selection
return input;
}
}
errorMessage="Invalid selection, ";
cin.clear();
cin.ignore(numeric_limits<int>::max(), '\n');
}
}

int main(){

System s;
vector<string> menuOptions;
menuOptions.push_back("selection 1");
menuOptions.push_back("selection 2");
menuOptions.push_back("selection 3");
cout<<s.genMenuForUserSelection(menuOptions);
Account main;
string name = "msc";
Option a = Option(name,1.1,1.1,1.1,1.1,1.1);
Option b = Option(name,1.1,1.1,1.1,1.1,1.1);
cout<<main.printStatement();
return 0;
}








No comments:

Post a Comment