next up previous contents index
Next: Adjusting for payouts of Up: Basic Option Pricing, analytical Previous: Setup.   Contents   Index

Subsections

European call and put options, The Black Scholes analysis.

A call (put) option gives the holder the right, but not the obligation, to buy (sell) some underlying asset at a given price $X$, called the exercise price, on or before some given date $T$.

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:

At maturity, a call option is worth

\begin{displaymath}C_T = \max(0,S_T-X) \end{displaymath}

and a put option is worth

\begin{displaymath}P_T = \max(0,X-S_T) \end{displaymath}

This can be used in solving the pde above, since they define a boundary condition for the pde.

Analytical option prices, Black Scholes case.

The pde with the boundary condition

\begin{displaymath}c_T = \max(0,S_T-X) \end{displaymath}

was shown by Black and Scholes to have an analytical solution of the following functional form

\begin{displaymath}c=SN(d_1)-Xe^{-r(T-t)}N(d_2) \end{displaymath}

where

\begin{displaymath}d_1 = \frac{\log\left(\frac{S}{X}\right) +
(r+\frac{1}{2}\si...
...+ r(T-t) }{ \sigma \sqrt{T-t} } + \frac{1}{2} \sigma \sqrt{T-t}\end{displaymath}


\begin{displaymath}d_2 = d_1 - \sigma\sqrt{T-t} \end{displaymath}


\begin{displaymath}N(\cdot) = \mbox{ The cumulative normal distribution} \end{displaymath}

Similarly, the price for a put option is

\begin{displaymath}p = X e^{-r(T-t)} N(-d_2) - S N(-d_1) \end{displaymath}

Computer Algorithm, Black Scholes price.



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


Partial derivatives.

In trading of options, a number of partial derivatives of the option price formula is important.


Delta

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.

\begin{displaymath}\frac{\partial c}{\partial S} = N(d_1) \end{displaymath}


\begin{displaymath}\frac{\partial p}{\partial S} = -N(-d_1) \end{displaymath}

Since delta is often used, here is a subroutine that calculates it



// 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.


Gamma

The second derivative of the option price wrt the underlying stock. These are equal for puts and calls

\begin{displaymath}\Gamma_c = \frac{\partial^2 c}{\partial S^2} =
\Gamma_p = \fr...
...tial \Delta}{\partial
S} = \frac{n(d_1)}{S\sigma\sqrt{T-t} }
\end{displaymath}


Theta

The partial with respect to time-to-maturity.

\begin{displaymath}\Theta_c = \frac{\partial c}{\partial (T-t) }
=- \frac{n(d_1)S\sigma}{2\sqrt{T-t}}-rXe^{-r(T-t)}N(d_2) \end{displaymath}


\begin{displaymath}\Theta_p = \frac{\partial p}{\partial (T-t) }
= -\frac{n(d_1)S\sigma}{2\sqrt{T-t}} + rXe^{-r(T-t)}N(-d_2)
\end{displaymath}


Vega

The partial with respect to volatility.

\begin{displaymath}\textrm{Vega}_c = \frac{\partial c}{\partial \sigma} = S\sqrt{T-t}n(d_1)\end{displaymath}


\begin{displaymath}\textrm{Vega}_p = \frac{\partial p}{\partial \sigma} = S\sqrt{T-t}n(d_1)\end{displaymath}


Rho

The partial with respect to the interest rate.

\begin{displaymath}\textrm{Rho}_c = \frac{\partial c}{\partial r} = X(T-t) e^{-r(T-t)}N(d_2)\end{displaymath}


\begin{displaymath}\textrm{Rho}_p = \frac{\partial p}{\partial r} = -X(T-t) e^{-r(T-t)}N(-d_2)\end{displaymath}


Computer algorithm, Black Scholes partials.

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



Implied Volatility.

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 $c_0$, the price of a call option, the following equation should be solved for the value of $\sigma$

\begin{displaymath}c_0 = c(S,X,r,\sigma,T-t) \end{displaymath}

Unfortunately, this equation has no closed form solution, which means the equation must be numerically solved to find $\sigma$. What is probably the algorithmic simplest way to solve this is to use a binomial search algorithm, which is implemented in the following. We start by bracketing the sigma by finding a high sigma that makes the BS price higher than the observed price, and then, given the bracketing interval, we search for the volatility in a systematic way.

Computer algorithm, implied volatility, bisections.



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


Implied volatility, Newton-Raphson.

Instead of this simple bracketing, which is actually pretty fast, and will (almost) always find the solution, we can use the Newton-Raphson formula for finding the root of an equation in a single variable. If

\begin{displaymath}f(x) = 0 \end{displaymath}

is the equation we want to solve, given a first guess $x_0$, we iterate by

\begin{displaymath}x_{i+1} = x_i - \frac{f(x_i)}{f^\prime(x_i)} \end{displaymath}

until

\begin{displaymath}\vert f(x_i)\vert<\epsilon \end{displaymath}

where $\epsilon$ is the desired accuracy.

In our case

\begin{displaymath}f(x) = c_{obs} - c_{BS}(\sigma) \end{displaymath}

and, each new iteration will calculate

\begin{displaymath}\sigma_{i+1} = \sigma_i + \frac{c_{obs}-c_{BS}(\sigma_i)}
{-\frac{\partial c_{BS}()}{\partial \sigma}}
\end{displaymath}

Note that to use Newton-Raphson we need the derivative of the option price. For the Black-Scholes formula this is known, and we can use this. But for pricing formulas like the binomial, where the partial derivatives are not that easy to calculate, simple bisection is the preferred algorithm.

Computer algoritm, implied volatility, Newton steps.



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


Further Reading

For the Newton-Raphson formula and bracketing, a good source is chapter 9 of Press et al. (1992)


next up previous contents index
Next: Adjusting for payouts of Up: Basic Option Pricing, analytical Previous: Setup.   Contents   Index
Bernt Arne Odegaard
1999-09-09