• C++ Programming for Financial Engineering
    Highly recommended by thousands of MFE students. Covers essential C++ topics with applications to financial engineering. Learn more Join!
    Python for Finance with Intro to Data Science
    Gain practical understanding of Python to read, understand, and write professional Python code for your first day on the job. Learn more Join!
    An Intuition-Based Options Primer for FE
    Ideal for entry level positions interviews and graduate studies, specializing in options trading arbitrage and options valuation models. Learn more Join!

My first C++ Black-Scholes-Merton program

Copy-pasted from my Code::Blocks compiler ^_^. First time ever doing classes in C++. Took me around...3 hours to write up. Write a few similar lines, compile, get a bunch of errors thrown at me, look at Savitch book, fix errors, rinse, repeat, run program, get ridiculous numbers, check code, rewrite some code, fix code, rerun program, profit!

Hopefully I'm not a lost cause.

C++:
#include <iostream>
#include <math.h>
#include <cmath>
#include <cstdlib>

using namespace std;

double N(double z);

class BlackScholes
{
      public:
      double d1();
      double d2();
      double Price();
      BlackScholes(double callFlagInput, double SInput, double XInput, double rInput, double volInput, double TInput);
      void printTest();
      void ErrorChecker();
      BlackScholes();
      ~BlackScholes();
      double callFlag;
      private:
      double S;
      double X;
      double r;
      double vol;
      double T;
};


BlackScholes::BlackScholes(double callFlagInput, double SInput, double XInput, double rInput, double volInput, double TInput)//Yay constructor ^_^
{
callFlag=callFlagInput;
S=SInput;
X=XInput;
r=rInput/100;
vol=volInput;
T=TInput/365;
}

BlackScholes::BlackScholes()//default constructor ^_^
{
}

double BlackScholes::d1()//calculates d1 ^_^
{

    return (log(S/X)+(r+pow(vol,2)/2)*T)/(vol*sqrt(T));
}

double BlackScholes::d2()//calculates d2 ^_^
{

    return d1()-vol*sqrt(T);
}

double BlackScholes::Price()//Options pricing!  Yay!  Okay, fine, I know that BSM is outdated -_-...but I don't know much else >_<
{

    double x=S*N(callFlag*d1());
    double y=X*exp(-1*r*T)*N(callFlag*d2());
    if(callFlag==1)
    {
        cout<<"The price of the call is "<<callFlag*(x-y)<<endl;
    }
    if(callFlag==-1)
    {
        cout<<"The price of the put is "<<callFlag*(x-y)<<endl;
    }
}

void BlackScholes::ErrorChecker()
{
    if(S<=0)
    {
        cout<<"All stocks cost something!  Illegal input!  CRASH!"<<endl;
        exit(1);
    }
    if(X<=0)
    {
        cout<<"No such thing as a strike price of 0!  Illegal input!  CRASH!"<<endl;
        exit(1);
    }
    if(vol<=0)
    {
        cout<<"There's always volatility!  Illegal input!  CRASH!"<<endl;
        exit(1);
    }
    if(T<=0)
    {
        cout<<"You can't go back in time!  Illegal input!  CRASH!"<<endl;
        exit(1);
    }
    if(callFlag!=-1&&callFlag!=1)
    {
        cout<<"Illegal input!  CRASH!"<<endl;
        exit(1);
    }
}

void BlackScholes::printTest()//This allows me to keep track of variables in case something looks screwy =P
{
if(callFlag==1)
    {
        cout<<"The option is a call."<<endl;
    }
if(callFlag==-1)
    {
        cout<<"The option is a put."<<endl;
    }
cout<<"The volatility is "<<vol<<endl;
cout<<"The stock price is "<<S<<endl;
cout<<"The strike price is "<<X<<endl;
cout<<"LIBOR is "<<r<<endl;
cout<<"The time in years to expiration is "<<T<<endl;
cout<<"d1 is "<<d1()<<endl;
cout<<"d2 is "<<d2()<<endl;
cout<<"The normalized d1 is "<<N(callFlag*d1())<<endl;
cout<<"The normalized d2 is "<<N(callFlag*d2())<<endl;

}

BlackScholes::~BlackScholes()//Destructors!  My first time writing one ^_^
{

}

double N(double z)//Cumulative Normal approximation here.  I pulled this thing off the net.
{
  const double b1 =  0.319381530;
  const double b2 = -0.356563782;
  const double b3 =  1.781477937;
  const double b4 = -1.821255978;
  const double b5 =  1.330274429;
  const double p  =  0.2316419;
  const double c2  =  0.39894228;

  double a=fabs(z);
  double t=1.0/(1.0+a*p);
  double b=c2*exp((-z)*(z/2.0));
  double n=((((b5*t+b4)*t+b3)*t+b2)*t+b1)*t;
  n=1-b*n;
  if(z<0) n=1-n;
  return n;
}

int main(){//test method ^_^...hey, I might be a good programmer yet ^_^
    cout<<"I has a black-scholes!"<<endl;
    double callFlag;
    double S;
    double X;
    double r;
    double vol;
    double days;
    cout<<"Please enter -1 if the option is a put or 1 if the option is a call."<<endl;
    cin>>callFlag;
    cout<<"Please enter the stock price."<<endl;
    cin>>S;
    cout<<"Please enter the strike price."<<endl;
    cin>>X;
    cout<<"Please enter LIBOR as a percentage.  (If Libor is 4%, please enter 4.)"<<endl;
    cin>>r;
    cout<<"Please enter the volatility.  Yes, I know, I should calculate the volatility from an array of stock prices.  Oh well.  You do that instead."<<endl;
    cin>>vol;
    cout<<"Please enter the time to expiration in days.  This is because I'm too lazy to import a calendar into the program."<<endl;
    cin>>days;
    BlackScholes IMK(callFlag,S,X,r,vol,days);
    IMK.ErrorChecker();
    IMK.Price();
    int repeat;
    cout<<"Would you like to use the program again?  If so, please press 0."<<endl;
    cin>>repeat;
    if(repeat==0)
    {
        main();
    }
    else
    {
        cout<<"Thanks for using my Black Scholes program.  Bye!"<<endl;
        return(0);
    }
}
//182 lines of code for a preliminary Black-Scholes ^_^. Sheesh, this thing took me a while because of all the bumps >_<.
//I'm not sure if writing BSM as a class is the best way to implement it.
 
Good start. After you understand a bit more about C++, the next step is to slowly incorporate design patterns. They will come as answers to something like ...
How would you change the code if r or volatilty is a known function of time?
How would you change the code if you want to add another closed formula option?
How would you incorporate implied volatility?
How would you be able to add other methods for computing option value?
 
1) I'd change the code by removing the r parameter, and instead create a method which computes that value as a function of time.
2) I'd write another class to value a different option (swaps, futures, forwards)
3) See, I don't know many good numerical methods. I guess there's the usual newton/bisect/secant method, but I doubt that's what the masters use. But anyhow, it'd just be a plug-and-chug approximation, so find whatever has the lowest big-O notation.
4) Other methods for computing option value? Depends on the inputs. But my price method is like four lines, and the rest of that is error checking, a test printing function, and a normal CDF approximation.

In the meantime, in terms of the IV, I'd have to set up a new constructor for that to take different arguments.
 
Some ideas for you ...

1) I'd change the code by removing the r parameter, and instead create a method which computes that value as a function of time.

Fine. One problem is that the function is linked to this class. Is function to compute r linked to your Black Scholes class or is it independent?
Another problem is that each time you need to set a different function, you need to recompile everything and of course introduce possible errors ...

2) I'd write another class to value a different option (swaps, futures, forwards)

Do these options have anything in common? If you have a common interface, maybe other classes can use this generic interface.

3) See, I don't know many good numerical methods. I guess there's the usual newton/bisect/secant method, but I doubt that's what the masters use. But anyhow, it'd just be a plug-and-chug approximation, so find whatever has the lowest big-O notation.

Thinking about implied volatility with newton's method it leads you to vega, maybe other greeks too ...
By the way, swaps and futures are not options. They can be replicated using options but they are not literally contigent claims ...

4) Other methods for computing option value? Depends on the inputs. But my price method is like four lines, and the rest of that is error checking, a test printing function, and a normal CDF approximation.
In the meantime, in terms of the IV, I'd have to set up a new constructor for that to take different arguments.

The question is to look back at the code and try to see if it is flexible. You don't need to add other methods yet. Yes constructor can be adjusted.
 
Ohh, right, I was thinking about derivatives in general. Other options, such as the exotic ones.

Interesting stuff. I'll have to add to my program then sometime later, because I am pretty sure I can code all of this stuff.

As for a time dependent rate, I'm guessing you're talking about the yield curve. In all honesty, I've never actually seen a model of the yield curve. It's just always been "well, right now, if you want to take out a 5-year loan, your interest will be X", not to mention that the yield curve is always in flux anyway.

Though once I have a slightly better grip on coding, I'll start looking over the D.E. Shaw and Microsoft coding interview questions in earnest.
 
Greeks maybe considered later:
Download Black-Scholes: Just plug-in the numbers

C++:
                                               Wed Jan 21 16:32:10 2009
    EXSAN v.0.3.18.S - [EMAIL="exsan.software@gmail.com"]exsan.software@gmail.com[/EMAIL]   [EMAIL="exsan@uio.satnet.net"]exsan@uio.satnet.net[/EMAIL]
    E X S A N     M E N U
 6 Quantitative Finance Room
 a Black-Scholes:  Just plug-in the numbers 
    [URL="http://en.wikipedia.org/wiki/Greeks_(finance"]Greeks (finance - Wikipedia, the free encyclopedia[/URL])
    Price of the Stock St                     ->    100
    exercise price K (strike)                ->    120
    Vol  (percent)                               ->     33
    risk-free interest rate r                ->     10
    time to expiration (weeks)           ->     26
    d1 = -0.450391    d2 = -0.683736
    Black-Sholes Price
                       delta    gamma      vega       theta     rho    volga    vanna
    CALL =   4.4189    0.326214 0.0154476 25.4886 -11.3466  14.6767  23.7854  0.746854
    PUT  =  18.5664    0.673786 0.0154476 25.4886 0.534004  -44.7262  23.7854  0.746854
 
Thanks for raining on my parade -_-...I'll go dry off now.
Okay, I kid. Nice stuff. I see you put a lot of work into it. I'm not at all sold on the command line for matrices interface, though, so once the GUI gets done, it should be a nice piece of work (let me beta test it, please?).
 
Black-Sholes Calculator / Just plug-in numbers

Black-Sholes Calculator / Just plug-in numbers
From the Downloadable File extract program BLACK_SHOLES to your desktop and execute.
added value : Graphs + Greeks

C++:
   - 0 EXIT- Price of the Stock St       --->  110
    exercise price K (strike)             --->  115
    Vol  (percent)                        --->   20
    risk-free interest rate r (percent)   --->    5
    time to expiration (weeks)            --->   26
    d1 =  -0.0668341   d2 =  -0.208255 

    Black-Sholes Price
                           delta          gamma          vega            theta           rho       
    CALL =  5.24054 	 0.473357 	 0.0255878 	 30.9612 	 8.58696 	 23.4144 
    PUT  =  7.40118 	 -0.526643 	 0.0255878 	 30.9612 	 2.85131 	 -32.666
 

Attachments

  • ExSan4.00.M_Black_Sholes.zip
    2 MB · Views: 153
Top