If the option is European, it can only be used (exercised) at the maturity date. If the option is American, it can be used at any date up to and including the maturity date.
We use the following notation:
// file: black_scholes_call
// author: Bernt A Oedegaard
// Calculation of the Black Scholes option price formula.
#include <cmath> // mathematical library
#include "normdist.h" // this defines the normal distribution
double option_price_call_black_scholes( double S, // spot price
double X, // Strike (exercise) price,
double r, // interest rate
double sigma,
double time)
{
double time_sqrt = sqrt(time);
double d1 = (log(S/X)+r*time)/(sigma*time_sqrt) + 0.5*sigma*time_sqrt;
double d2 = d1-(sigma*time_sqrt);
double c = S * N(d1) - X * exp(-r*time) * N(d2);
return c;
};
In trading of options, a number of partial derivatives of the option price formula is important.
The first derivative of the option price with respect to the underlying is
called the delta of the option price. It is the derivative most people
will run into, since it is important in hedging of options.
// file: black_scholes_delta_call.cc
// author: Bernt A Oedegaard
// The delta of the Black - Scholes formula
#include <cmath>
#include "normdist.h"
double option_price_delta_call_black_scholes(double S, // spot price
double X, // Strike (exercise) price,
double r, // interest rate
double sigma, // volatility
double time){ // time to maturity
double time_sqrt = sqrt(time);
double d1 = (log(S/X)+r*time)/(sigma*time_sqrt) + 0.5*sigma*time_sqrt;
double delta = N(d1);
return delta;
};
The remaining derivatives are more seldom used, but all of them are relevant.
The partial with respect to time-to-maturity.
Here is the algorithm that calculates all the above derivatives.
// black_scholes_partials_call.cc
// author: Bernt A Oedegaard
// The partial derivatives of the Black - Scholes formula
#include <cmath>
#include "normdist.h"
void option_price_partials_call_black_scholes( double S, // spot price
double X, // Strike (exercise) price,
double r, // interest rate
double sigma, // volatility
double time, // time to maturity
double& Delta, // partial wrt S
double& Gamma, // second prt wrt S
double& Theta, // partial wrt time
double& Vega, // partial wrt sigma
double& Rho){ // partial wrt r
double time_sqrt = sqrt(time);
double d1 = (log(S/X)+r*time)/(sigma*time_sqrt) + 0.5*sigma*time_sqrt;
double d2 = d1-(sigma*time_sqrt);
Delta = N(d1);
Gamma = n(d1)/(S*sigma*time_sqrt);
Theta =- (S*sigma*n(d1)) / (2*time_sqrt) - r*X*exp( -r*time)*N(d2);
Vega = S * time_sqrt * n(d1);
Rho = X * time * exp(-r * time) * N(d2);
};
In calculation of the option pricing formulas, in particular the Black Scholes
formula, the only unknown is the standard deviation of the underlying stock. A
common problem in option pricing is to find the implied volatility, given the
observed price quoted in the market. For example, given
, the price of a
call option, the following equation should be solved for the value of
// file black_scholes_imp_vol_bisect.cc
// author: Bernt A Oedegaard
// calculate implied volatility of Black Scholes formula
#include "fin_algoritms.h"
#include <cmath>
double option_price_implied_volatility_call_black_scholes_bisections(
double S, double X, double r, double time, double option_price)
{ // check for arbitrage violations:
// if price at almost zero volatility greater than price, return 0
double sigma_low=0.0001;
double price = option_price_call_black_scholes(S,X,r,sigma_low,time);
if (price>option_price) return 0.0;
// simple binomial search for the implied volatility.
// relies on the value of the option increasing in volatility
const double ACCURACY = 1.0e-5; // make this smaller for higher accuracy
const int MAX_ITERATIONS = 100;
const double HIGH_VALUE = 1e10;
const double ERROR = -1e40;
// want to bracket sigma. first find a maximum sigma by finding a sigma
// with a estimated price higher than the actual price.
double sigma_high=0.3;
price = option_price_call_black_scholes(S,X,r,sigma_high,time);
while (price < option_price) {
sigma_high = 2.0 * sigma_high; // keep doubling.
price = option_price_call_black_scholes(S,X,r,sigma_high,time);
if (sigma_high>HIGH_VALUE) return ERROR; // panic, something wrong.
};
for (int i=0;i<MAX_ITERATIONS;i++){
double sigma = (sigma_low+sigma_high)*0.5;
price = option_price_call_black_scholes(S,X,r,sigma,time);
double test = (price-option_price);
if (fabs(test)<ACCURACY) { return sigma; };
if (test < 0.0) { sigma_low = sigma; }
else { sigma_high = sigma; }
};
return ERROR;
};
In our case
// file black_scholes_imp_vol_newt.cc
// author: Bernt A Oedegaard
// calculate implied volatility of Black Scholes formula using newton steps
#include "fin_algoritms.h"
#include "normdist.h"
#include <cmath>
double option_price_implied_volatility_call_black_scholes_newton(
double S, double X, double r, double time, double option_price)
{
// check for arbitrage violations:
// if price at almost zero volatility greater than price, return 0
double sigma_low = 1e-5;
double price = option_price_call_black_scholes(S,X,r,sigma_low,time);
if (price > option_price) return 0.0;
const int MAX_ITERATIONS = 100;
const double ACCURACY = 1.0e-4;
double t_sqrt = sqrt(time);
double sigma = (option_price/S)/(0.398*t_sqrt); // find initial value
for (int i=0;i<MAX_ITERATIONS;i++){
price = option_price_call_black_scholes(S,X,r,sigma,time);
double diff = option_price -price;
if (fabs(diff)<ACCURACY) return sigma;
double d1 = (log(S/X)+r*time)/(sigma*t_sqrt) + 0.5*sigma*t_sqrt;
double vega = S * t_sqrt * n(d1);
sigma = sigma + diff/vega;
};
return -99e10; // something screwy happened, should throw exception
};