com.opengamma.analytics.financial.model.option.pricing.tree.NormalBinomialTreeBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.model.option.pricing.tree.NormalBinomialTreeBuilder.java

Source

/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 * 
 * Please see distribution for license.
 */
package com.opengamma.analytics.financial.model.option.pricing.tree;

import org.apache.commons.lang.Validate;

import com.opengamma.analytics.financial.model.option.definition.GeneralNormalOptionDataBundle;
import com.opengamma.util.tuple.DoublesPair;

/**
* Builds a binomial tree where the nodes are set to locally match a normal process. The process that the tree is emulating is of the form  df = a(f,t)dt + b(f,t)dw.
* From a node at (f,t) the two daughter nodes f+ and f- (at time t + dt) are set such that p*(1-p)*(f+ - f-)^2 = dt*b(f,t)^2, where p is the probability of reaching f+ from f. 
* The forwarding condition is p*f+ + (1-p)*f- = f + a(f,t)*dt. This is adapted from the paper Derman and Kani, The Volatility Smile and Its Implied Tree. 
* @param <T> A GeneralNormalOptionDataBundle or anything that extends it 
*/
public class NormalBinomialTreeBuilder<T extends GeneralNormalOptionDataBundle> extends BinomialTreeBuilder<T> {

    @Override
    protected DoublesPair getCentralNodePair(final double dt, final double sigma, final double forward,
            final double centreLevel) {
        final double sigma2dt = sigma * sigma * dt;
        final double b = 2 * centreLevel;
        final double c = forward * (2 * centreLevel - forward) - sigma2dt;
        final double root = b * b - 4 * c;
        Validate.isTrue(root >= 0, "can't find upper node - root negative");
        final double upper = (b + Math.sqrt(root)) / 2;
        final double lower = 2 * centreLevel - upper;
        return new DoublesPair(lower, upper);
    }

    @Override
    protected double getNextHigherNode(final double dt, final double sigma, final double forward,
            final double lowerNode) {
        final double sigma2dt = sigma * sigma * dt;
        Validate.isTrue(forward > lowerNode, "need forward > lowerNode");
        return sigma2dt / (forward - lowerNode) + forward;
    }

    @Override
    protected double getNextLowerNode(final double dt, final double sigma, final double forward,
            final double higherNode) {
        if (forward == 0.0) {
            return 0.0;
        }
        final double sigma2dt = sigma * sigma * dt;
        Validate.isTrue(higherNode > forward, "need higherNode > forward");
        double lowerNode = sigma2dt / (forward - higherNode) + forward;
        if (lowerNode < 0.0) {
            lowerNode = 0.0; // set zero as an absorbing boundary
        }
        return lowerNode;
    }

    @Override
    protected double[] getForwards(final double[] spots, final T data, final double t, final double dt) {
        final int n = spots.length;
        final double[] forwards = new double[n];
        for (int i = 0; i < n; i++) {
            final double drift = data.getLocalDrift(spots[i], t);
            forwards[i] = spots[i] + drift * dt;
        }
        return forwards;
    }

}