Homework 1
Simple Binomial Option Pricing Model

Computational Finance

Copyright © Philip H. Dybvig 1996, 1998

Scenario Your boss wants to develop in-house the capability to use a binomial model to compute theoretical prices and hedges for various traditional and exotic options. This homework represents the first step in carrying out that assignment.

Action Starting with a binomial option pricing applet, you will make changes to customize the applet for pricing of different contracts.

Concept The finance application is the binomial model we reviewed in class. The computational part of this applet is more sophisticated than was the NPV applet in the previous assignment. The changes in the computer program require more sophistication than last time, and you should be more aware than before of what is happening in the program.

Instructions In each of the following steps, provide a crisply written answer. For the program changes, write a short concise description of the changes you made and why. For thought questions, think about the question and answer in no more than two sentences of ordinary length. As in business, writing that is concise and to the point is appreciated. Unnecessarily long answers may be penalized.

  1. Download the required Java program file (CrrA.java) and related web document (CrrA.html) and put them in a directory on your machine where you want to work. Compile the program and have a look at the applet which is the starting point of your analysis. The steps are the same as last week.
  2. Modify the program file CrrA.java to use a default standard deviation of .3 instead of .4 and a default stock price of 52.
  3. Modify the program file CrrA.java to use the binary option method binRight of Crr (to price a binary option) instead of the European call option method Eurcall. Make the appropriate changes to Labels and TextFields (to tell the user this is now binary option pricing not call pricing).
  4. Add a method binMiddle to Crr that pays $1 when the stock price is in the range between lower and upper. Modify CrrA to display this value along with the value from binRight.
  5. Thought question As a user of the program, what other features might you like to see?

Extra for Experts

  1. Add methods AmPut and EurPut to Crr to price American and European put options. Display these two values. (Hint: For the American Option Contract valuation, check whether it pays to exercise at every node as you go back through the tree and record the higher of the two values, i.e., the larger of the proceeds from exercising now and the ongoing value of the unexercised option)
  2. Add a method to Crr that will value a payoff that is a polynomial in the stock price. If you like, fix the order of the polynomial (e.g. make it quadratic), but it is better if the user can specify the order of the polynomial. Modify the applet to make use of the new method.
  3. Currently, the applet has a "hard-wired" limit of 5000 periods in the binomial model and will crash mysteriously if you enter more. Have the program return a warning instead if the user tries to use too many periods. Better yet, have the program adapt to whatever number of periods is specified by the user.

Challenger

  1. Include an method in Crr to evaluate a "up and in" American put option that can be exercised only if at some previous date the stock price increases to meet or exceed a given threshhold.

A Quick Tour of the program and web files.

This is a very quick overview. For much more detail, see the annotated versions in CrrAnotes.html.

The .html (Web) file CrrA.html at which you point your web browser to view the Applet is shown in Exhibit A, and the program file CrrA.java defining the Applet is shown in Exhibit B. The names of the files and critical pieces of the program contain "Crr" in honor of Cox, Ross, and Rubinstein, who are the original developers of the binomial model now used widely in practice.

The .java file has two class definitions, for classes CrrA (the applet) and Crr (the computational engine). Each of the class definitions defines a template for creating and using objects of the class. A public class is one defining objects that can be referenced from outside this file. There is always a public class of the same name as the .java file: in this case, the public class CrrA is defined in the file CrrA.java. When compiled, there is a .class file for each class; in this case the compiler will create files CrrA.class and Crr.class. A .class file contains relatively compact "bytecodes" which give the information about the class in a compact form that can be used on different types of computer. This is an efficient form for transmission and execution across the web: machine language instructions specific to a particular type machine would be more compact (and require less processing at the other end), but would useless for posting on the web if (as is usual) it is important to reach users with differing hardware.

Again, more detail is available in the annotated versions in CrrAnotes.html.

Exhibit A: the browser file CrrA.html
<HTML>
<HEAD>
<TITLE>Binomial Option Program: Prototype</TITLE>
</HEAD>
<BODY>
<APPLET CODE=CrrA.class WIDTH=500 HEIGHT=350>
</APPLET>
</BODY>
</HTML>
Exhibit B: the program file CrrA.java
import java.applet.*;
import java.awt.*;

public class CrrA extends Applet {
  TextField Strike, S0, sigma, r, ttm, nper;
  Button row6;
  Label optval;
  Crr crr;
  public CrrA() {
    setLayout(new BorderLayout());
    add("North",new Label("Binomial Option Pricing Applet",Label.CENTER));
    Panel centr = new Panel();
      centr.setLayout(new FlowLayout());
      Panel inputs = new Panel();
        inputs.setLayout(new GridLayout(7,1));
        Panel row0 = new Panel();
        row0.setLayout(new FlowLayout(FlowLayout.LEFT));
        row0.add(Strike = new TextField("50",8));
        row0.add(new Label("Option Strike Price"));
        inputs.add(row0);
        Panel row1 = new Panel();
        row1.setLayout(new FlowLayout(FlowLayout.LEFT));
        row1.add(S0 = new TextField("50",8));
        row1.add(new Label("Underlying Stock Price"));
        inputs.add(row1);
        Panel row2 = new Panel();
        row2.setLayout(new FlowLayout(FlowLayout.LEFT));
        row2.add(sigma = new TextField("40",8));
        row2.add(new Label("Annual Standard Deviation %"));
        inputs.add(row2);
        Panel row3 = new Panel();
        row3.setLayout(new FlowLayout(FlowLayout.LEFT));
        row3.add(r = new TextField("5",8));
        row3.add(new Label("Annual Interest Rate %"));
        inputs.add(row3);
        Panel row4 = new Panel();
        row4.setLayout(new FlowLayout(FlowLayout.LEFT));
        row4.add(ttm = new TextField("0.25",8));
        row4.add(new Label("Time to Maturity (yrs)"));
        inputs.add(row4);
        Panel row5 = new Panel();
        row5.setLayout(new FlowLayout(FlowLayout.LEFT));
        row5.add(nper = new TextField("10",8));
        row5.add(new Label("Number of Subperiods (whole number)"));
        inputs.add(row5);
        row6 = new Button("Recompute");
        inputs.add(row6);
      centr.add(inputs);
      Panel results = new Panel();
        results.setLayout(new GridLayout(6,1));
        results.add(new Label(""));
        results.add(new Label(""));
        results.add(new Label("Call Option Value:"));
        optval = new Label("",Label.LEFT);
        optval.resize(180,optval.size().height);
        results.add(optval);
        results.add(new Label(""));
        results.add(new Label(""));
      centr.add(results);
    add("Center",centr);
    crr = new Crr(5001);
    recalc();}
 public boolean action(Event ev, Object arg) {
    if(ev.target instanceof TextField) {
      recalc();
      return true;}
    if(ev.target instanceof Button) {
      recalc();
      return true;}
    return false;}
  double text2double(TextField tf) {
    return Double.valueOf(tf.getText()).doubleValue();}
  public void recalc() {
    row6.setLabel("Computing...Please Wait");
    crr.newPars(text2double(ttm),(int) text2double(nper),
      text2double(r)/100.0,text2double(sigma)/100.0);
    optval.setText(String.valueOf(
      (float)crr.Eurcall(text2double(S0),text2double(Strike))));
    row6.setLabel("Recompute");}}

class Crr {
  double ttm=.25,r=.05,sigma=.3;
  int nper=4,maxternodes;
  double tinc,r1per,disc,up,down,priceup,pricedn,Sprice;
  double[] val;

  public Crr(int maxternodes) {
    val = new double[maxternodes];}

  void newPars(double ttm,int nper,double r,double sigma) {
    this.nper = nper;
    tinc = ttm/(double) nper;
    r1per = 1.0 + r * tinc;
    disc = 1.0/r1per;
    up = r1per + sigma * Math.sqrt(tinc);
    down = r1per - sigma * Math.sqrt(tinc);
    priceup = disc * 0.5;
    pricedn = disc * 0.5;}

  public double Eurcall(double S0,double X) {
    int i,j;
//   initialize terminal payoffs
//   i is the number of up moves over the whole life
    for(i=0;i<=nper;i++) {
      Sprice = S0*Math.pow(up,(double) i)*Math.pow(down,(double) (nper-i));
      val[i] = Math.max(Sprice - X,(double) 0.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++) {
        val[i] = pricedn * val[i] + priceup * val[i+1];}}
    return(val[0]);}
  
  public double binRight(double S0,double lower) {
    int i,j;
//   initialize terminal payoffs
//   i is the number of up moves over the whole life
    for(i=0;i<=nper;i++) {
      Sprice = S0*Math.pow(up,(double) i)*Math.pow(down,(double) (nper-i));
      val[i] = ((Sprice>=lower) ? 1.0 : 0.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++) {
        val[i] = pricedn * val[i] + priceup * val[i+1];}}
    return(val[0]);}

  public double binLeft(double S0,double upper) {
    int i,j;
//   initialize terminal payoffs
//   i is the number of up moves over the whole life
    for(i=0;i<=nper;i++) {
      Sprice = S0*Math.pow(up,(double) i)*Math.pow(down,(double) (nper-i));
      val[i] = ((Sprice<=upper) ? 1.0 : 0.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++) {
        val[i] = pricedn * val[i] + priceup * val[i+1];}}
    return(val[0]);}}