Annotated versions of CrrA.html and CrrA.java

For Homework 1 of Computational Finance by P Dybvig

CrrA.html

The file CrrA.html is our program's interface to the "outside world." It is written in "hyper text markup language" (hence html), the default language of Web documents. In html, most items are labeled by matched tags. For example, <HTML> and </HTML> around the whole document indicate it is html. <HEAD> and </HEAD> indicate the head of the document, which contains only the title (marked by <TITLE> and </TITLE>) that shows in the top line of the browser. In the body of the document (between <BODY> and </BODY>) is the pair of tags (<APPLET CODE=CrrA.class WIDTH=500 HEIGHT=350> and </APPLET>) instructing the browser to include our applet. Our applet tag has three arguments, CODE which gives the name of the class file, WIDTH which gives the width in pixels, and HEIGHT which gives the height in pixels. (Pixels, short for "picture elements," are the dots used to make up a picture.) Many other arguments can be used in an Applet tag, including user-defined arguments. Here CrrA.class is the name of the class file containing the class CrrA defining the applet. It is important that the two names agree (here they are both CrrA), including capitalization.

<HTML>
<HEAD>
<TITLE>Binomial Option Program: Prototype</TITLE>
</HEAD>
<BODY>
<APPLET CODE=CrrA.class WIDTH=500 HEIGHT=350>
</APPLET>
</BODY>
</HTML>

CrrA.java

CrrA.java is the program file that contains the actual java program. The compiler converts this program to "bytecodes" that are closer to machine language. Actual conversion to machine language would vary from machine to machine this is run on and is not done at time of compilation.

Two classes are defined in CrrA.java: CrrA and Crr. These could be defined instead in separate files (bearing their names exactly including capitalization plus the suffix .java), which would be preferable for classes that will be reused by classes not already defined in this file. Each would then have to be made "public" so they can be used outside of this file. As it is, only CrrA is public, since Crr is only referenced by CrrA which is located in the same source file.

Each class gives a description or template for a type of object. The class CrrA is the overall applet which includes a label, an input area, a results area, and a computational engine. Each of these smaller objects making up the applet could be defined as a separate class; as it is, I chose to define only the computational engine crr in a separate class called Crr. Each time the applet starts, one object each of classes CrrA and Crr is created. In a different application, we might want to have two or more Crr objects to allow comparisons for various parameter values, in which case having the single class definition as a template for each pair would save us some time! Furthermore, having a single class definition would make the program file easier to read and would minimize programming errors.

Each class has a number of methods (functions) that perform operations in the class and variables that keep track of important data or states of the class. This is one of the features of object-oriented programming, characteristic of languages like C++ and java: the data and the functions used to manipulate the data are associated in a combined object. One important method in each class is a Constructor, which is a method with the same name as the class that is used to set up the object (construct it) the first time it is created.

This is the java 1.0 version of the applets. The exact details of the user interface (e.g. the action method and resize method) seem to be in a state of flux and are different in version 1.1. I do not suggest spending too much effort learning these features of the language.

Detailed comments are in the lines marked --> in the code below.

import java.applet.*;
import java.awt.*;

--> These two statements allow us to use the shortcut of omitting
    the prefix in some java classes below.  For example, we can write
    Applet instead of java.applet.Applet in defining CrrA.

public class CrrA extends Applet {

--> This signals the class definition of the new class CrrA which extends
    the class Applet.  Extension means that it inherits a lot of the
    general features of Applets as well as the specific features defined
    here.  The qualifier "public" says that CrrA should be a global name
    that can be referred to from outside the file.

  TextField Strike, S0, sigma, r, ttm, nper;
  Button row6;
  Label optval;
  Crr crr; /* option pricing engine */

--> These statements define variables used in an object of class CrrA.
    Strike, S0, sigma, r, ttm, and nper are the names of TextFields (little
    input boxes), row6 is the name of a Button, optval is the name of a
    Label, and crr is the name of an object of type Crr.  For now the objects
    do not exist and if we referred to these names before they were assigned
    to objects, we would probably get a warning or error like "crr used
    before set."

--> The text between /* and */ is a comment that is ignored by the compiler.
    Including comments is important because it is likely that someone will
    have to use or modify the code besides the original programmer.  Even
    the original programmer will appreciate comments on code written six
    months earlier.  On the other hand, code that is well-organized and
    written in a straightforward way should require reasonably sparse
    comments.

  public CrrA() {

--> This method, which has the same name as the class, does all the initial
    work that is required when a new object of this type is created, in
    this case (for an applet) in response to a call from a .html file (in
    this case CrrA.html).  This is called a Constructor.

    setLayout(new BorderLayout());

--> A layout object of class BorderLayout is arranged in a rectangle with
    a rectangle in the center ("Center"), rectangles on top and bottom
    ("North" and "South"), and rectangles on the sides ("East" and
    "West").  The setLayout method (by default of the current object, an
    applet of class CrrA we are constructing) says to make the new
    BorderLayout object the layout of the current object.

    add("North",new Label("Binomial Option Pricing Applet",Label.CENTER));

--> Add a new Label "Binomial Option Pricing Applet" at the top of the
    applet.  The second argument Label.CENTER to Label indicates this should
    be centered.

    Panel centr = new Panel();
      centr.setLayout(new FlowLayout());

--> The center of the new applet should be a new panel named centr.  The
    new panel should have a layout of type FlowLayout, which means put objects
    added to it in a row horizontally until space is gone and then start again
    below.  In this case, we expect all parts of the panel to fit on one line
    and therefore we do not plan to start again.

      Panel inputs = new Panel();
        inputs.setLayout(new GridLayout(7,1));

--> The panel called inputs is the first panel we will put in centr.  Its layout
    is of a type called GridLayout, which in this case means 7 equally-sized
    cells arranged in 7 rows and one column.

        Panel row0 = new Panel();

--> "Panel" declares the type of the variable row0, which is the name
    assigned to a newly created panel object.

        row0.setLayout(new FlowLayout(FlowLayout.LEFT));

--> row0 is given a new layout of type FlowLayout, left-justified

        row0.add(Strike = new TextField("50",8));
        row0.add(new Label("Option Strike Price"));

--> To row0, we add a textfield 8 characters wide initially containing
    the input 50, and a label "Option Strike Price".  Strike is the
    name of the TextField in row0.

        inputs.add(row0);

--> row0 is added to the new object of type CrrControls (the input panel)
    whose Constructor this is.

--> rows 1-5 work the same way:

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

--> row6 is a Button with the word Recompute on it.  row6 is added
    to our input panel object.

      centr.add(inputs);

--> and the entire input panel is added to the center panel of the applet.

      Panel results = new Panel();
        results.setLayout(new GridLayout(6,1));

--> The panel called results is the second panel we will put in centr.  Like
    inputs, it has a Layout of type GridLayout, which in this case means 6
    equally-sized cells arranged in 6 rows and one column.

        results.add(new Label(""));
        results.add(new Label(""));

--> The first two cells in results are blank labels.

        results.add(new Label("Call Option Value:"));
        optval = new Label("",Label.LEFT);
        optval.resize(180,optval.size().height);
        results.add(optval);

--> The third cell is a Label describing the result in the fourth cell, which
    is a left-justified Label optval, resized to have a width of 180 pixels.

        results.add(new Label(""));
        results.add(new Label(""));

--> and the final two cells in results are two more blank Labels.

      centr.add(results);

--> the entire results panel is added to the center panel of the applet.

    add("Center",centr);

--> and the center panel is added where it belongs.  Caution:  using add(centr);
    instead of add("Center",centr); will cause problems in a BorderLayout.  In
    particular, javac and appletviewer will work fine, but mysteriously browsers
    may not.  I think this is because the location defaults to center if not given
    in version 1.1 but many of the browsers still support only 1.0.

    crr = new Crr(5001);

--> Create a new object crr of type Crr.  The argument 5001 is the argument
    to the constructor, which is the method Crr(int) in Crr. Specifically,
    5001 gives the maximum number of terminal stock prices (which equals the
    maximum number of periods plus one).

    recalc();}

--> The last step in constructing the applet is to perform the option pricing
    calculation the first time.  The } indicates the end of the definition
    of the constructor CrrA().

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

--> This function says what to do when something happens:  recalculate
    if it is a button pressed or a TextField input.  This is part of
    the language that is changing in later versions of Java.

  double text2double(TextField tf) {

--> This method returns a double precision real number represented
    by the text in the TextField.

    return Double.valueOf(tf.getText()).doubleValue();}

--> Starting with the TextField tf, ".getText()" uses the method that
    is part of every TextField to extract just the string that has
    been typed there.  Then, "Double.valueOf" converts the string to
    a Double object, which is an object containing a double precision
    number.  Finally, ".doubleValue()" extracts the number itself.
    A better version of this function might include context-specific
    help to guide the user who types inappropriate input (not a number
    or a number that is too large or too small).

  void recalc() {

--> This function defines what it means to recalculate. The
    void says no value is returned by the method (in contrast to, for
    example, a mathematical function which may return a double).

    row6.setLabel("Computing...Please Wait");

--> In case recomputing takes a while, change the label on the "Recompute"
    button to clue the user in about what is happening.  This will not
    even be noticeable except when there are many periods (or the computer
    is very slow).

    crr.newPars(text2double(ttm),(int) text2double(nper),
      text2double(r)/100.0,text2double(sigma)/100.0);

--> The crr.newPars function is used to change the variables to the
    parameter values currently in the input boxes.  The text2double
    method (defined just above this method) extracts the string from
    the box and converts it to type double.  For the interest rate
    r and standard deviation sigma, division by 100.0 converts the
    percentage to a number.  For the number of periods, (int) forces
    a change to type integer before passing it on to crr.newPars.

    optval.setText(String.valueOf(
      (float)crr.Eurcall(text2double(S0),text2double(Strike))));

--> These two lines are a single program statement.  The function
    crr.Eurcall(double,double) is called to compute the call value
    as a double precision real number, which is cast (converted) to
    a float (single precision real number), and then to a character
    string.  The label optval's text is then set to this string.

    row6.setLabel("Recompute");}}

--> Finally, the label is set back to "Recompute" since the computation
    is done.  The first } tells the compiler this is the end of the
    method recalc; the second } tells the compiler this is the end of the
    class CrrA.

class Crr {

--> Crr is the class in the file that is not immediately visible to
    the user.  It defines a template for the object that does the actual
    calculations of option prices in the binomial tree.

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

--> setting up names for various constants for the binomial option pricing
    tree.  the following are inputs
  
      ttm -- time to maturity
      r -- interest rate
      sigma -- standard deviation of stock returns
      nper -- number of periods to maturity
      maxternodes -- largest permissible number of terminal nodes

           while the following are computed

      tinc -- time increment 
      r1per -- 1 + interest rate over tinc
      disc -- discount factor over tinc
      up -- new stock price over previous at an up node
      down -- new stock price over previous at a down node
      priceup -- state price of consuming in the up state
      pricedn -- state price of consuming in the down state
      Sprice -- stock price at the node we are considering now
      val[] -- vector of option values at different stock prices on the
         date we are currently working on 

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

--> The class constructor's only input is the maximum number of terminal
    nodes, and the only task is to create the vector in which we place the
    values at a given date

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

--> The method newPars changes the underlying parameters of the stock
    price process and computes the derived parameters.  The initial
    stock price could be set here too (instead of being inputs to the
    individual pricing functions).  The derived parameters are the
    quantities that will be used again and again through the tree.
    It saves time to compute them once here instead of computing them
    at each node in the tree.

  public double Eurcall(double S0,double X) {

--> The method Eurcall prices a European call option with strike X when
    the stock price is S0.

    int i,j;

--> these two integer variables are counters for the loops below and
    indicate which node in the binomial tree we are considering

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

--> First, we must set all the values of the option at nodes at the terminal
    date and store these values in the array val.  The for command repeats
    the statements following between curly brackets a number of times.  The
    first argument of for is executed once in preparation for the repetition.
    In this case, we set the counter i (which can be interpreted as the number
    of up moves taken to get to the terminal node) equal to 0.  The second
    argument of for is the criterion for continuing to repeat the statements
    in the loop.  In this case, we repeat so long as i is less than or equal
    to the number of periods.  The final argument is what is done at the end
    of each repetition, in this case, increasing i by one.

--> The calculation for the stock price Sprice at a node uses the power function
    Math.pow(double, double) which takes the first argument to the power of the
    second.  Calculating the option value val[i] at node i uses the function
    Math.max(double,double) which is the max of the arguments.  In each case,
    casting with (double) converts the number to the right type for the function.

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

--> The previous for statment computed the values at the end; this pair of for
    statements computes the value back through the entire tree.  These are called
    nested for loops; for each time through the outer loop (with index j), we go
    through the inner loop a number of times.  At each node (characterized by
    i and j) we compute the option value at a new node.  The vector val is used
    to store both next period's values (previously computed) and this period's
    values (computed now).  This is possible because the time of computing this
    node's value is the last time we need to use the next period's value previously
    stored there.

    return(val[0]);}

--> At the end, the value corresponding to no ups is the option value we are
    returning.
  
  public double binRight(double S0,double lower) {

--> The binRight method gives the value of a European "binary option" that pays
    off 1 when the stock price is higher than ("to the right of") some minimum
    value 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);}

--> This line, used to compute the terminal payoff, is the only real difference
    between binRight and Eurcall.  The construction (a ? b : c) is equal to b
    if a is true and is equal to c if a is false.
    

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

--> The function binLeft gives the value of a binary option that pays of when
    the stock price is left of a critical value upper.  Note that the criterion
    of the (a ? b : c) has been changed from binRight to reflect the difference.