Computational Finance: Midterm Examination

April 23, 2001
Philip H. Dybvig

This is a closed-book examination. Answer all questions as directed. Mark your answers directly on the examination. On the valuation question, make sure your answer is clearly indicated. There are no trick questions on the exam. Good luck!
A. General Concepts Multiple choice: 20 points Circle the one best answer.

  1. Which of the following is an interest derivative?

    A. ARCH
    B. collar
    C. warrant
    D. PDA

  2. In risk-neutral probabilities, the mean change in futures price is which of the following?

    A. riskfree rate
    B. mean return on the underlying security
    C. risk premium on the underlying security
    D. zero

  3. Which is most likely to be a useful tool for valuing mortgage derivatives?

    A. Black-Scholes model
    B. binomial model
    C. simulation
    D. duration

  4. Suppose a bond manager overlays an active bond portfolio with S&P index futures to convert bond market profits into a portfolio that is to be judged against an S&P 500 benchmark. What is the best description of this situation?

    A. portable alpha
    B. asset-liability management
    C. portfolio insurance
    D. hedge fund

  5. Which of the following is the main concept underlying the binomial option pricing model?

    A. absence of arbitrage
    B. time value of money
    C. Modigliani-Miller irrelevancy propositions
    D. value-at-risk

B. Financial Computation 40 points

A Simple Option Pricing Problem in Two Periods

Riskless bond (riskfree interest rate is 25%):

16 --- 20 -- 25

Stock price:

            |- 225
    |- 120 -|
64 -|       |-  75
    |-  40 -|
            |-  25

Derivative security (binary option paying 100 when the stock price is between 50 and 100 and paying zero otherwise):

            |-   0
    |-  ?  -|
?  -|       |- 100
    |-  ?  -|
            |-   0

The actual probabilities are 2/3 for up and 1/3 for down at each node.

  1. What are the risk-neutral probabilities of up and down? (The risk-neutral probabilities are the same at every node: compute them at the first node. Reminder: the formula for the risk-neutral probability of an up move is (r-d)/(u-d). Advice: check to make sure the stock price is consistent with your answer.)

    
    
    
    
    
    
    
    
    
    
    
    
  2. What is the value of the binary option at each node?

    
    
    
    
    
    
    
    
    
    
    
  3. In the portfolio strategy that replicates the binary option, what are the holdings in the stock and the bond at the initial node?

        
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  4. (thought question -- answer in a sentence or two of ordinary length) Suppose you have a view that volatility will be smaller than most people expect. Your investment banker has proposed the purchase of these binary options as a way of profiting if your view is correct. Discuss.

        
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
C. Computer Implementation Short Answer: 40 points

The questions in this section are based on the Stochastic Volatility Option Pricing Applet in Homework 5. You should not need to use the complete program listings, but they are included at the end of the exam in case you would like to have a look at them.

Here is the method eurCall in SVPriceEngine, which computes the price of a European call option.
public double eurCall(double stock,double strike,long nsimu) {
  long i,n;
  double x;
  x=0.0;
  for(n=0;n<nsimu;n++) {
    stockP = stock;
    sigma = sigma0;
    for(i=0;i<npers;i++) {
      stockP *= stocktotret();
      }
    x += Math.max(stockP-strike,0);}
  return(x/((double) nsimu * Math.pow(r1per,(double) npers)));}
  1. How would eurCall be modified to price a European put option?
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  2. What is the variable x in eurCall? Discuss its role in the option valuation.
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  3. Explain the role of Math.pow(r1per,(double) npers) in the denominator of the quantity returned by eurCall.
    
    
    
    
    
    
    
    
    
    
    
  4. (thought question -- answer in a sentence or two of ordinary length) It is quite difficult to modify a simulation program such as the one used in eurCall to price an American option. Why is this?
    
    
    
    
    
    
    
    
    
    
    
D. Advanced Questions and the Speakers Short Answer: up to 20 make-up points Answering these questions correctly can give you up to 20 points to substitute for points missed in Parts A-C.

  1. Sometimes interest-only obligations (i.o.'s) increase in value in response to rising interest rates, and sometimes they respond in the opposite direction. Explain briefly why the response can go either way.

    
    
    
    
    
    
    
    
    
    
  2. Describe briefly an example given by one of the class speakers of a practical problem solved in practice using the tools of this course.

    
    
    
    
    
    
    
    

Supplemental Information

Although you may not need to see the java program files to answer the questions in part C, the files are included for your reference.

Exhibit A: SVPrice.html

<HTML>
<HEAD>
<TITLE>Asset Allocation Simulation</TITLE>
</HEAD>
<BODY>
<P>
<APPLET CODE=SVPrice.class WIDTH=300 HEIGHT=50>
</APPLET>
</p>
<p> WARNING:  The number of simulations equals 100 for
testing only!  It takes many more draws (perhaps 100,000)
to obtain an accurate value.</p>
</BODY>
</HTML>
Exhibit B: SVPrice.java
import java.applet.*;
import java.awt.*;

public class SVPrice extends Applet {
  SVPriceFrame svpf;
  Button startASimu;
    public SVPrice() {
      setLayout(new GridLayout(1,1));
      add(startASimu = new Button("Compute Option Prices Now"));
      svpf = new SVPriceFrame();
      svpf.setTitle("Stochastic Volatility Option Pricing Simulation");
      svpf.pack();
      svpf.resize(500,400);}
    public boolean action(Event e, Object arg) {
      if(e.target == startASimu) {
        svpf.reset();
        return true;}
      return false;}}

class SVPriceFrame extends Frame {
  double[] initSigmas;
  Label[] opvals;
  TextField r,sigmabar,kappa,sigmasigma,ttm,s0,strike,nsimu,nper;
  Button newRandomDraws,resetInputs;
  SVPriceEngine vroom;
  int i;
  public SVPriceFrame() {
    setLayout(new BorderLayout());
    Panel outputs = new Panel();
      outputs.setLayout(new GridLayout(6,2));
      outputs.add(new Label("Initial Sigma"));
      outputs.add(new Label("Call Price"));
      opvals = new Label[5];
      initSigmas = new double[5];
      for(i=0;i<5;i++) {
        initSigmas[i] = .3 + .05*((double) i);
        outputs.add(new Label(Double.toString(initSigmas[i])));
        outputs.add(opvals[i] = new Label("**********"));
        opvals[i].setForeground(Color.yellow);}
    add("North",outputs);
    Panel inputs = new Panel();
      inputs.setLayout(new GridLayout(8,3));
      inputs.add(new Label("stock price"));
      inputs.add(new Label("strike price"));
      inputs.add(new Label("number of simus"));
      inputs.add(s0=new TextField("50",10));
      inputs.add(strike=new TextField("60",10));
      inputs.add(nsimu=new TextField("100",10));
      inputs.add(new Label("interest (%/yr)"));
      inputs.add(new Label("avg sigma (%/yr)"));
      inputs.add(new Label("kappa (%/yr)"));
      inputs.add(r=new TextField("5",10));
      inputs.add(sigmabar=new TextField("40",10));
      inputs.add(kappa=new TextField("3.0",10));
      inputs.add(new Label("vol of vol (%/yr)"));
      inputs.add(new Label("time to mat (yr)"));
      inputs.add(new Label("# subperiods"));
      inputs.add(sigmasigma=new TextField("10",10));
      inputs.add(ttm=new TextField("5",10));
      inputs.add(nper=new TextField("25",10));
      inputs.add(newRandomDraws = new Button("Compute Prices"));
      inputs.add(new Label(""));
      inputs.add(new Label(""));
      inputs.add(resetInputs = new Button("Reset Parameters"));
    add("South",inputs);
    vroom = new SVPriceEngine();}
  public void startSimu() {
    newRandomDraws.setLabel("-- Computing --");
    newRandomDraws.setForeground(Color.red);
    for(i=0;i<5;i++) {
      opvals[i].setForeground(Color.yellow);}
    for(i=0;i<5;i++) {
      vroom.newPars(text2double(ttm),(int) text2double(nper),
        text2double(r)/100.0,initSigmas[i],text2double(sigmabar)/100.0,
        text2double(kappa)/100.0,text2double(sigmasigma)/100.0);
      opvals[i].setText(String.valueOf((float)
        vroom.eurCall(text2double(s0),text2double(strike),
          (long) text2double(nsimu))));
      opvals[i].setForeground(Color.black);}
    newRandomDraws.setLabel("Compute Prices");
    newRandomDraws.setForeground(Color.black);}
  public void reset() {
    r.setText("5");
    sigmabar.setText("40");
    kappa.setText("3.0");
    sigmasigma.setText("10");
    ttm.setText("5");
    nper.setText("25");
    s0.setText("50");
    strike.setText("60");
    nsimu.setText("100");
    show();}
  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();}}
Exhibit C: SVPriceEngine.java
public class SVPriceEngine {
  double npers, tinc, r1per, sigma0, meansigma, sigmasigma, kappa,
    c0, c1, c2, c3, c4;
  double stockP, sigma;

  public SVPriceEngine(){}

  public void newPars(double ttm,int nper,double r,double initstd,
    double meanstd, double k, double sigstd) {
    npers = nper;
    tinc = ttm/(double) nper;
    r1per = 1.0 + r*tinc;
    sigma0 = initstd;
    meansigma = meanstd;
    sigmasigma = sigstd;
    kappa = k;
    c0 = kappa * tinc * meansigma;
    c1 = 1.0 - kappa * tinc;
    c2 = 1.0 - sigmasigma * Math.sqrt(tinc)*0.5*Math.sqrt((double) 12);
    c3 = sigmasigma * Math.sqrt(tinc) * Math.sqrt((double) 12);
    c4 = Math.sqrt(tinc)*Math.sqrt((double) 12);}

public double eurCall(double stock,double strike,long nsimu) {
  long i,n;
  double x;
  x=0.0;
  for(n=0;n<nsimu;n++) {
    stockP = stock;
    sigma = sigma0;
    for(i=0;i<npers;i++) {
      stockP *= stocktotret();
      }
    x += Math.max(stockP-strike,0);}
  return(x/((double) nsimu * Math.pow(r1per,(double) npers)));}

double stocktotret() {
  double stockret;
//
//  The following straightforward computations are algebraically
//  the same as the ones used below but are much slower because
//  many more calculations are performed in each pass through the
//  nested for loops in eurCall.
//
//  stockret = r1per + sigma * Math.sqrt(tinc) *
//    (Math.random()-0.5) * Math.sqrt((double) 12);
//  sigma = (kappa*tinc * meansigma + (1.0 - kappa * tinc) * sigma) *
//    (1 + sigmasigma * Math.sqrt(tinc) *
//    (Math.random()-0.5) * Math.sqrt((double) 12));
//  return(stockret);}
//
  stockret = r1per + sigma * c4 * (Math.random() - 0.5);
  sigma = (c0 + c1 * sigma) * (c2 + c3 * Math.random());
  return(stockret);}}