/* File: LatticeControls.java Author: Richard Sanders This is a basic construct that both acts as the engine and the shell for the Lattice Applet. It uses the Grid Bag Layout extensively, which I failed to comment because some of the code is a little bit of a hack for layout purposes :) */ import java.awt.*; import java.awt.GridBagConstraints; import java.io.*; import java.lang.*; public class LatticeControls extends Panel { Label PriceLabel, StrikeLabel, RateLabel, VolLabel, StepLabel, TimeLabel, TypeLabel, Line1, Line2, ResultLabel, Greetings; TextField S, K, r, sigma, M, t, Val; Choice OptionType; Button PriceIt; Color DarkGreen; // Constructor public LatticeControls () { DarkGreen = new Color(0, 102, 51); Font Header = new Font("Helvetica", Font.BOLD, 18); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); // This huge uncommented mess that follows is me beating my head against // the wonderous GridBagLayout :). c.anchor = GridBagConstraints.NORTH; c.weightx = 0; c.weighty = 2; c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = 2; Greetings = new Label ("Welcome to the Lattice Method American Option Pricer"); Greetings.setFont(Header); Greetings.setForeground(DarkGreen); gridbag.setConstraints(Greetings, c); c.anchor = GridBagConstraints.WEST; setFont(new Font("Helvetica", Font.PLAIN, 14)); c.gridwidth = 4; c.weighty = 1; PriceLabel = new Label("What is the price of the underlying stock?"); gridbag.setConstraints(PriceLabel, c); StrikeLabel=new Label("What is the strike price of the option?"); gridbag.setConstraints(StrikeLabel, c); RateLabel=new Label("What is the annual interest rate in percent?"); gridbag.setConstraints(RateLabel, c); VolLabel=new Label ("What is the volatility of the underlying in percent"); gridbag.setConstraints(VolLabel, c); TimeLabel=new Label("What is the time (in days) until expiration"); gridbag.setConstraints(TimeLabel, c); StepLabel=new Label("How many time steps would you like calculated?"); gridbag.setConstraints(StepLabel, c); c.gridwidth = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.EAST; S = new TextField("9 ", 5); gridbag.setConstraints(S, c); K = new TextField("10 ", 5); gridbag.setConstraints(K, c); r = new TextField("12 ", 5); gridbag.setConstraints(r, c); sigma = new TextField("50 ", 5); gridbag.setConstraints(sigma, c); t = new TextField("30 ", 5); gridbag.setConstraints(t, c); M = new TextField("16 ", 5); gridbag.setConstraints(M, c); Line1 = new Label(" "); gridbag.setConstraints(Line1, c); Line2 = new Label(" "); gridbag.setConstraints(Line2, c); add(Greetings); add(Line1); add(PriceLabel); add(S); add(StrikeLabel); add(K); add(RateLabel); add(r); add(VolLabel); add(sigma); add(TimeLabel); add(t); add(StepLabel); add(M); add(Line2); TypeLabel = new Label("This option is a"); add(TypeLabel); OptionType = new Choice(); OptionType.addItem("Put"); OptionType.addItem("Call"); add(OptionType); TypeLabel = new Label(" option =========> "); add(TypeLabel); c.gridwidth = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.EAST; PriceIt = new Button(" Price It "); PriceIt.setBackground(DarkGreen); PriceIt.setForeground(Color.white); gridbag.setConstraints(PriceIt, c); add(PriceIt); c.anchor = GridBagConstraints.WEST; c.gridwidth = 4; ResultLabel=new Label ("The price of the option is "); gridbag.setConstraints(ResultLabel, c); add(ResultLabel); c.gridwidth = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.EAST; Val = new TextField(" ", 7); gridbag.setConstraints(Val, c); add(Val); } // These next few get???() functions simply return the values in the // textboxes (after the appropriate parsing from string to double or int) // to the function that calls the lattice pricer. public double getPrice() { Float temp = Float.valueOf(S.getText()); return temp.doubleValue(); } public double getStrike() { Float temp = Float.valueOf(K.getText()); return temp.doubleValue(); } public double getRate() { Float temp = Float.valueOf(r.getText()); return (temp.doubleValue()/100.0); } public double getVol() { Float temp = Float.valueOf(sigma.getText()); return (temp.doubleValue()/100); } public double getTime() { Float temp = Float.valueOf(t.getText()); return (temp.doubleValue()/365.25); } public int getSteps() { return Integer.parseInt(M.getText().trim()); } // This gets the type of option from the "choice" box. Either put or call public boolean getType() { if (OptionType.getSelectedIndex() == 1) return true; else return false; } // When "price-it" is pressed, this causes the lattice method to output // the price of the option public boolean action(Event ev, Object arg) { if (ev.target instanceof Button) { double temp = lattice(getPrice(), getStrike(), getTime(), getRate(), getVol(), getType(), getSteps()); int temp2 = (int)(10000.0*temp); temp = temp2/10000.0; Val.setText("$" + Double.toString(temp)); } return true; } /* Simple max(a,b) function, returns the max of a and b */ private double max(double x, double y) { if (x > y) return x; return y; } /* Returns the intrinsic value of an option given S, K, and type of option */ private double pay_off(double S, double K, boolean call) { if (call) return max(S-K, 0.0); return max(K-S, 0); } /* This is the option pricing function: */ /* It takes the appropriate parameters and uses lattice methods to */ /* output the option value */ public double lattice(double S, double K, double t, double r, double sigma, boolean call, int n) { double dt, p, u, d; double hold; int time, step, i; /* This code allocates memory for two n+1 by n+1 arrays to store */ /* the lattice and the pricing backsolving. */ double[][] prices = new double[n+1][n+1]; double[][] val = new double[n+1][n+1]; /* Special check to see if the stock is already at expiration */ if (t == 0) return pay_off(S, K, call); /* This first determines dt for the discrete walk, and then the p, */ /* d, and u for the option pricing lattice */ dt = t/(float)n; p = (Math.exp(r*dt) - Math.exp(-sigma*Math.sqrt(dt)))/ (Math.exp(sigma*Math.sqrt(dt))-Math.exp(-sigma*Math.sqrt(dt))); u = Math.exp(sigma*Math.sqrt(dt)); d = Math.exp(-sigma*Math.sqrt(dt)); /* This is the lattice of possible underlying stock values */ prices[0][0] = S; for (time = 1; time <= n; time++) { for (step = time; step > 0; --step) { prices[time][step] = u * prices[time-1][step-1]; } prices[time][0] = d * prices[time-1][0]; } /* find option value at payoff, put into the price array */ for (step=0; step <= n; step++) val[n][step] = pay_off(prices[n][step], K, call); /* use risk neutral argument to find option values */ for (time = n-1; time >= 0; time--) for (step=0; step <= time; step++) { hold = Math.exp(-r*dt)*(p*val[time+1][step+1] + (1-p)*val[time+1][step]); val[time][step] = max(pay_off(prices[time][step], K, call), hold); } return val[0][0]; } }