Homework 1
Simple Binomial Interest Option Pricing Model

Computational Finance

Copyright © Philip H. Dybvig 1996

Scenario You are managing a fixed-income portfolio, and you would like to explore adding value by selling interest rate caps and related products to corporations whose management would like to hedge some interest rate risk. To evaluate these deals, you require a valuation of caps, floors, and collars.

Action You will be given a program that uses a binomial option pricing model to price caps. You will modify the program to value floors as well.

Concept This problem set illustrates the flexibility of the binomial model and in particular its usefulness in valuing interest-dependent claims. You should make an effort to become aware of more of the details of the program than you may have understood last week. In particular, you will have to change all of the program files in a consistent way.

Instructions

  1. Put the program files (captest.cc, cap.cc, and cap.h ) in a directory on your machine where you want to work. Rename them if necessary for your compiler. Compile the program and run it, trying different values for the current interest rate and the cap value.
  2. Write a new public member function for the class f_i_bin that can be used to value an interest rate floor. The new member function will be very similar to the existing member function f_i_bin::cap and you should model the new member function on that one. Here is an outline of the things you will do.
    Add a declaration (or prototype) to the file cap.h after the declaration of f_i_bin::cap.

    Define the new function f_i_bin::flor in the file cap.cc. You should not use the name ``floor'' since there already exists a function called ``floor'' in most libraries of mathematical functions (perhaps including the library provided with your version of C++).

    Modify the file captest.cc to test your new floor function instead of the existing cap function. Be sure to change the messages to the user to be consistent with the change in the logic of the program.

  3. Thought question How might a CFO of a publicly traded corporation use this sort of program?
Extra for Experts
  1. Write a member function to change the parameters after the object of type f_i_bin has been constructed. Use this to compare the cap value at two different variances without declaring two different objects.
  2. Write a member function to evaluate a collar, which is the difference between a cap and a floor. Write the function two different ways: using the existing cap and floor functions (quickest to program) and as a standalone function modeled after the cap function (quickest to run).
  3. Challenger Often we want to know what setting of cap and floor will make a collar a fair trade. Write a program that can be given the cap value and will find the floor value that makes the collar a fair deal without any up-front transfer (i.e. gives it a price of zero).
About the Program Files The program files are shown in exhibits A, B, and C. The basic structure of the program files is the same as in Homework 0. The file cap.h is the header file that contains the type declarations. The file cap.cc is the file that contains the valuation engine that performs the calculations. And, the file captest.cc gives the instructions to test the program. These three files are completely analogous with the files crr.h, crr.cc, and crrtest.cc in Homework 0. Conceptually, the binomial model in this Homework is almost identical to the binomial model in Homework 0. However, the underlying variable that is changing through the binomial tree is the short-maturity interest rate rather than a stock price. Because the interest rate is varying through the tree, so is the one-period discount factor used to compute the prices of up- and down-states.

Exhibit A: the header file cap.h

// cap.h
//
// Fixed-income binomial option pricing include file
//
#ifndef MAXTERNODES
#define MAXTERNODES 200
#endif
class f_i_bin {
public:
  f_i_bin(double ttm=.25,int npers=4,double sigma=.02,
    double rrbar=.07,double k=.125);
  double bprice(double r0);
  double cap(double level,double r0);
private:
  int nper;
  double tinc,up,down,sig,rbar,kappa,prfact;
  double r[MAXTERNODES],val[MAXTERNODES];};
Exhibit B: the test file captest.cc
// captest.cc
//
// Fixed income binomial option pricing model: test
//
#include <iostream.h>
#include "cap.h"
main() {
  f_i_bin c2;
  double caprate,rzero;
  cout << "\nType the cap rate, a space, the initial"
    << " rate, and then ENTER." << "\n"
    << "Make the cap rate negative to terminate." << "\n\n";
  cout << "State rates in percent per annum (without the "
    << "percent sign).\n\n";
  while(1) {
    cout << "cap-rate initial-rate: ";
    cin >> caprate >> rzero;
    if(!cin) {
      cout << "\nError: expected cap-rate initial-rate\n"
        << "Terminating\n" << endl;
      return(1);}
    if(caprate<0.0) {
      cout << endl;
      return(0);}
    cout << "cap value = " << c2.cap(caprate/100.0,rzero/100.0)
      << "\n\n";}}
Exhibit C: the implementation file cap.cc
// cap.cc
//
// Fixed-income binomial option pricing engine
//
#include <math.h>
#include <iostream.h>
#include "cap.h"
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))

f_i_bin::f_i_bin(double ttm,int npers,double sigma,double rrbar,double k) {
  nper=npers;
  tinc = ttm/(double) nper;
  sig = sigma;
  up = sigma*sqrt(tinc);
  rbar = rrbar;
  kappa = k;
  prfact = kappa*sqrt(tinc)/(2.0*sig);}

double f_i_bin::bprice(double r0) {
  int i,j;
  double prup;
//initialize terminal payoffs
//i is the number of up moves
  for(i=0;i<=nper;i++) {
//  r[i] = r0 + up * (double)(2*i-nper);   not needed for this claim
    val[i] = 1.0;}
//compute prices back through the tree
//j+1 is the number of periods from the end
//i is the number of up moves from the start
  for(j=0;j<nper;j++) { for(i=0;i<nper-j;i++) {
      r[i] = r0 + up * (double) (2*i-nper + j);
      prup = 0.5 + prfact*(rbar-r[i]);
      prup = MIN(1.0,MAX(0.0,prup));
      val[i] = (prup*val[i+1]+(1.0-prup)*val[i])*exp(-r[i]*tinc);}}
  return(val[0]);}

double f_i_bin::cap(double level,double r0) {
  int i,j;
  double prup;
//initialize terminal payoffs
//i is the number of up moves
  for(i=0;i<=nper;i++) {
//  r[i] = r0 + up * (double)(2*i-nper);   not needed for this claim
    val[i] = 0.0;}
//compute prices back through the tree
//j is the number of periods from the end
//i is the number of up moves from the start
  for(j=1;j<=nper;j++) {for(i=0;i<=nper-j;i++) {
      r[i] = r0 + up * (double) (2*i-nper + j);
      prup = 0.5 + prfact*(rbar-r[i]);
      prup = MIN(1.0,MAX(0.0,prup));
      val[i] = (prup*val[i+1]+(1.0-prup)*val[i])*exp(-r[i]*tinc)
        + MAX(0.0,(r[i]-level)*tinc);}}
  return(val[0]);}