next up previous contents index
Next: Finite Differences Up: Binomial option pricing. Previous: Estimating partials.   Contents   Index

Subsections

Binomial approximation, dividends.

If the underlying asset is a stock paying dividends during the maturity of the option, the terms of the option is not adjusted to reflect this cash payment, which means that the option value will reflect the dividend payments.

In the binomial model, the adjustment for dividends depend on whether the dividends are discrete or proportional.

Proportional dividends.

For proportional dividends, we simply multiply with an adjustment factor the stock prices at the ex-dividend date, the nodes in the binomial tree will ``link up'' again, and we can use the same ``rolling back'' procedure.



// file bin_am_prop_div_call.cc
// author: Bernt Arne Oedegaard
// binomial option pricing adjusting for dividends.

#include <cmath>
#include <algorithm>
#include <vector>
#include "fin_algoritms.h"

double option_price_call_american_proportional_dividends_binomial(
   double S, 
   double X,
   double r,
   double sigma, 
   double time, 
   int no_steps,
   vector<double>& dividend_times,
   vector<double>& dividend_yields) 
// given a dividend yield, the binomial tree recombines 
{
   int no_dividends=dividend_times.size();
   if (no_dividends == 0)               // just take the regular binomial 
      return option_price_call_american_binomial(S,X,r,sigma,time,no_steps);
   double R = exp(r*(time/no_steps));
   double Rinv = 1.0/R;
   double u = exp(sigma*sqrt(time/no_steps));
   double uu= u*u;
   double d = 1.0/u;
   double pUp   = (R-d)/(u-d);
   double pDown = 1.0 - pUp;
   
   vector<int> dividend_steps(no_dividends); // when dividends are paid
   for (int i=0; i<no_dividends; ++i) {
      dividend_steps[i] = (int)(dividend_times[i]/time*no_steps);
   };
   vector<double> prices(no_steps+1);
   vector<double> call_prices(no_steps+1);
   prices[0] = S*pow(d, no_steps);
   for (int i=0; i<no_dividends; ++i) { prices[0]*=(1.0-dividend_yields[i]); };
   for (int i=1; i<=no_steps; ++i) prices[i] = uu*prices[i-1]; // terminal tree nodes
   for (int i=0; i<=no_steps; ++i) call_prices[i] = max(0.0, (prices[i]-X));
   for (int step=no_steps-1; step>=0; --step) {
      for (int i=0;i<no_dividends;++i) {   // check whether dividend paid
	 if (step==dividend_steps[i]) { 
	    for (int j=0;j<=step;++j) {
	       prices[j]*=(1.0/(1.0-dividend_yields[i])); 
	    };
	 };
      };
      for (int i=0; i<=step; ++i)   {
	 prices[i] = d*prices[i+1];
	 call_prices[i] = (pDown*call_prices[i]+pUp*call_prices[i+1])*Rinv;
	 call_prices[i] = max(call_prices[i], prices[i]-X);         // check for exercise
      };
   };
   return call_prices[0];
};


Discrete dividends.

The problem is when the dividends are constant dollar amounts.

In that case the nodes of the binomial tree do not ``link up,'' and the number of branches increases dramatically, which means that the time to do the calculation is increased.

The algorithm presented here implements this case, with no linkup, by constructing a binomial tree up to the ex-dividend date, and then, at the terminal nodes of that tree, call itself with one less dividend payment, and time to maturity the time remaining at the ex-dividend date. Doing that calculates the value of the option at the ex-dividend date, which is then compared to the value of exercising just before the ex-dividend date. It is a cute example of using recursion in simplifying calculations, but as with most recursive solutions, it has a cost in computing time. For large binomial trees and several dividends this procedure will take a long time. In that case it will be a good deal faster to avoid the recursive calls. Look in (Hull, 1993, pg 347) for ways to achieve this by making some small assumptions.

Computer algorithm, binomial pricing with discrete dividends.



// file bin_am_div_call.cc
// author: Bernt Arne Oedegaard
// binomial option pricing adjusting for dividends.

#include <cmath>
#include <vector>
#include "fin_algoritms.h"

double option_price_call_american_discrete_dividends_binomial(double S, 
							      double X,
							      double r,
							      double sigma, 
							      double t, 
							      int steps,
							      vector<double>& dividend_times,
							      vector<double>& dividend_amounts) 
// given an amount of dividend, the binomial tree does not recombine, have to 
// start a new tree at each ex-dividend date.
// do this recursively, at each ex dividend date, at each step, call the 
// binomial formula starting at that point to calculate the value of the live
// option, and compare that to the value of exercising now.
{
   int no_dividends = dividend_times.size();
   if (no_dividends == 0)               // just take the regular binomial 
      return option_price_call_american_binomial(S,X,r,sigma,t,steps);
   int steps_before_dividend = (int)(dividend_times[0]/t*steps);
    
   double R = exp(r*(t/steps));
   double Rinv = 1.0/R;
   double u = exp(sigma*sqrt(t/steps));
   double uu= u*u;
   double d = 1.0/u;
   double pUp   = (R-d)/(u-d);
   double pDown = 1.0 - pUp;
   double dividend_amount = dividend_amounts[0];
   vector<double> tmp_dividend_times(no_dividends-1);  // temporaries with 
   vector<double> tmp_dividend_amounts(no_dividends-1);  // one less dividend
   for (int i=0;i<no_dividends-1;++i){ 
      tmp_dividend_amounts[i] = dividend_amounts[i+1];
      tmp_dividend_times[i]   = dividend_times[i+1] - dividend_times[0];
   };
   vector<double> prices(steps_before_dividend+1);
   vector<double> call_values(steps_before_dividend+1);

   prices[0] = S*pow(d, steps_before_dividend);
   for (int i=1; i<=steps_before_dividend; ++i) prices[i] = uu*prices[i-1];
   for (int i=0; i<=steps_before_dividend; ++i){
      double value_alive  
	 = option_price_call_american_discrete_dividends_binomial(
	    prices[i]-dividend_amount, 
	    X, r, sigma, 
	    t-dividend_times[0], // time after first dividend
	    steps-steps_before_dividend, 
	    tmp_dividend_times, 
	    tmp_dividend_amounts);  
      // what is the value of keeping the option alive?  Found recursively, 
      // with one less dividend, the stock price is current value 
      // less the dividend.
      call_values[i] = max(value_alive,(prices[i]-X));  // compare to exercising now
   };
   for (int step=steps_before_dividend-1; step>=0; --step) {
      for (int i=0; i<=step; ++i)   {
	 prices[i] = d*prices[i+1];
	 call_values[i] = (pDown*call_values[i]+pUp*call_values[i+1])*Rinv;
	 call_values[i] = max(call_values[i], prices[i]-X);         // check for exercise
      };
   };
   return call_values[0];
};



next up previous contents index
Next: Finite Differences Up: Binomial option pricing. Previous: Estimating partials.   Contents   Index
Bernt Arne Odegaard
1999-09-09