//
// Asset Allocation Applet
//
// This applet simulates asset allocation between risky and riskless
// assets.  The horizon is fixed at 10 years and initial wealth is
// normalized to be 100.  The interest rate is constant and stock
// returns are i.i.d. over time.
//

import java.applet.*;
import java.awt.*;

public class AssetAlloc extends Applet {
  ValuePlotFrame valuePlotFrame;
  Button startASimu;
    public AssetAlloc() {
      setLayout(new GridLayout(1,1));
      add(startASimu = new Button("Start a Simulation"));
      valuePlotFrame = new ValuePlotFrame();
      valuePlotFrame.setTitle("Asset Allocation Simulation");
      valuePlotFrame.pack();
      valuePlotFrame.resize(500,400);}
    public boolean action(Event e, Object arg) {
      if(e.target == startASimu) {
        valuePlotFrame.reset();
        return true;}
      return false;}}

class ValuePlotFrame extends Frame {
  BasicLinePlot blp;
  TextField r,mu,sigma,inrisky;
  Button newRandomDraws,resetInputs;
  double ttm = 10.0,ir;
  double[] times,values;
  int nper = 1200;
  int i;
  AssetAllocEngine vroom;
  double[] xgrid,ygrid;
  public ValuePlotFrame() {
    setLayout(new BorderLayout());
    blp = new BasicLinePlot();
    add("Center",blp);
    Panel inputs = new Panel();
    inputs.setLayout(new GridLayout(6,2));
      inputs.add(new Label("interest rate (%/yr)"));
      inputs.add(r = new TextField("5",10));
      inputs.add(new Label("mean stock return (%/yr)"));
      inputs.add(mu = new TextField("15",10));
      inputs.add(new Label("std dev of stock return (%/yr)"));
      inputs.add(sigma = new TextField("30",10));
      inputs.add(new Label("allocation to risky asset (%)"));
      inputs.add(inrisky = new TextField("70",10));
      inputs.add(newRandomDraws = new Button("Simulate again"));
      inputs.add(new Label(""));
      inputs.add(resetInputs = new Button("Reset and simulate again"));
    add("South",inputs);
    vroom = new AssetAllocEngine(nper);
    times = new double[nper + 1];
    for(i=0;i<=nper;i++) times[i] = ((double) i) * ttm / ((double) nper);
    xgrid = new double[6];
    for(i=0;i<6;i++) xgrid[i] = ((double) i) * 2.0;
    ygrid = new double[6];
    for(i=0;i<6;i++) ygrid[i] = ((double) i) * 100.0;}
  public void startSimu() {
    vroom.newPars(text2double(r)/100.0,
        text2double(mu)/100.0,text2double(sigma)/100.0,ttm);
    ir = text2double(inrisky)/100.0;
    values = vroom.fixProps(ir,ir * 100.0,(1.0-ir)*100.0);
    blp.newXY(times,values,xgrid,ygrid,"Simulated Wealth, Fixed Proportions Startegy: 0-10 years out");
    show();}
  public void reset() {
    r.setText("5");
    mu.setText("15");
    sigma.setText("30");
    inrisky.setText("70");
    startSimu();}
  public boolean action(Event e, Object arg) {
    if(e.target == newRandomDraws) {
      startSimu();
      return true;}
    if(e.target == resetInputs) {
      reset();
      return true;}
    return false;}
  public boolean handleEvent(Event event) {
    if(event.id == Event.WINDOW_DESTROY) {
      dispose();}
    return super.handleEvent(event);}
  double text2double(TextField tf) {
    return Double.valueOf(tf.getText()).doubleValue();}}

class AssetAllocEngine {
  int nper;
  double tinc,r1per,mean1per,std1persqrt12;
  double[] values;
  public AssetAllocEngine(int nper) {
    values = new double[nper+1];
    this.nper = nper;}
  public void newPars(double r,double mu,double sigma,double ttm) {
    tinc = ttm/((double) nper);
    r1per = 1.0 + r * tinc;
    mean1per = 1.0 + mu * tinc;
    std1persqrt12 = sigma * Math.sqrt(12.0 * tinc);}
  public double[] fixProps(double inrisky,double initstock,double initcash) {
    double stock,cash,wealth,stockret;
    int i;
    stock = initstock;
    cash = initcash;
    for(i=1,values[0]=stock + cash;i<=nper;i++) {
      wealth = stock + cash;
      stock = wealth * inrisky;
      cash = wealth - stock;
      stockret = stockTotRet();
      stock *= stockret;
      cash *= r1per;
      values[i] = cash + stock;}
    return values;}
  double stockTotRet() {
    return mean1per + std1persqrt12 * (Math.random()-0.5);}}
