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