//
// Fixed income binomial cap pricing applet
//
import java.applet.*;
import java.awt.*;

public class Caplet extends Applet {
  F_I_bin c2;
  double caprate,rzero;
  Label capval;
  TextField interest_rate, capped_level;
  public Caplet() {
    setLayout(new GridLayout(3,2));
    add(new Label("Interest rate (%) ="));
    add(interest_rate = new TextField("5",10));
    add(new Label("Capped level (%) ="));
    add(capped_level = new TextField("5.5",10));
    add(new Label("Cap value (per $100 face) ="));
    add(capval = new Label("**********"));
    c2 = new F_I_bin((double) 2.0, (int) 24, (double) 0.01, (double) 0.05,
      (double) 0.125, (int) 5001);
    recalc();}
 public boolean action(Event ev, Object arg) {
    if(ev.target instanceof TextField) {
      recalc();
      return true;}
    return false;}
  double text2double(TextField tf) {
    return Double.valueOf(tf.getText()).doubleValue();}
  void recalc() {
    capval.setText(String.valueOf((float) (100 * c2.cap(text2double(capped_level)/100.0,
      text2double(interest_rate)/100.0))));}}
//
// Fixed-income binomial option pricing engine
//

class F_I_bin {
  int nper;
  double tinc,up,down,sigma,rbar,kappa,prfact;
  double [] r,val;

  public F_I_bin(double ttm,int nper,double sigma,double rbar,double kappa,
      int maxternodes) {
    this.nper=nper;
    tinc = ttm/(double) nper;
    this.sigma = sigma;
    up = sigma*Math.sqrt(tinc);
    this.rbar = rbar;
    this.kappa = kappa;
    prfact = kappa*Math.sqrt(tinc)/(2.0*sigma);
    val = new double[maxternodes];
    r = new double[maxternodes];}

  double 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 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 = Math.min((double) 1.0,Math.max((double) 0.0,prup));
        val[i] = (prup*val[i+1]+(1.0-prup)*val[i])*Math.exp(-r[i]*tinc);}}
    return(val[0]);}

  double 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 = Math.min((double) 1.0,Math.max((double) 0.0,prup));
        val[i] = (prup*val[i+1]+(1.0-prup)*val[i])*Math.exp(-r[i]*tinc)
          + Math.max((double) 0.0,(r[i]-level)*tinc);}}
    return(val[0]);}}
