com.opengamma.analytics.financial.model.interestrate.BlackDermanToyYieldOnlyInterestRateModel.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.model.interestrate.BlackDermanToyYieldOnlyInterestRateModel.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.interestrate;

import org.apache.commons.lang.Validate;
import org.threeten.bp.ZonedDateTime;

import com.opengamma.analytics.financial.model.interestrate.definition.StandardDiscountBondModelDataBundle;
import com.opengamma.analytics.financial.model.tree.RecombiningBinomialTree;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.rootfinding.BrentSingleRootFinder;
import com.opengamma.analytics.math.rootfinding.RealSingleRootFinder;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.tuple.Triple;

/**
 * 
 */
public class BlackDermanToyYieldOnlyInterestRateModel {
    private final RealSingleRootFinder _rootFinder = new BrentSingleRootFinder();
    private final int _n;
    private final int _j;

    public BlackDermanToyYieldOnlyInterestRateModel(final int n) {
        if (n < 2) {
            throw new IllegalArgumentException("Must have more than one node");
        }
        _n = n;
        _j = RecombiningBinomialTree.NODES.evaluate(_n);
    }

    public Function1D<StandardDiscountBondModelDataBundle, RecombiningBinomialTree<Triple<Double, Double, Double>>> getTrees(
            final ZonedDateTime time) {
        Validate.notNull(time, "time");
        return new Function1D<StandardDiscountBondModelDataBundle, RecombiningBinomialTree<Triple<Double, Double, Double>>>() {

            @SuppressWarnings({ "unchecked", "synthetic-access" })
            @Override
            public RecombiningBinomialTree<Triple<Double, Double, Double>> evaluate(
                    final StandardDiscountBondModelDataBundle data) {
                Validate.notNull(data, "data");
                final double[][] r = new double[_n + 1][_j];
                final double[][] q = new double[_n + 1][_j];
                final double[][] d = new double[_n + 1][_j];
                final double[] u = new double[_n + 1];
                final double[] p = new double[_n + 2];
                final double t = DateUtils.getDifferenceInYears(data.getDate(), time);
                final double dt = t / _n;
                final double dtSqrt = Math.sqrt(dt);
                final double r1 = data.getShortRate(dt);
                final double sigma = data.getShortRateVolatility(dt);
                p[0] = 1.0;
                for (int i = 1; i <= _n + 1; i++) {
                    p[i] = 1. / Math.pow((1 + data.getShortRate(i) * dt), dt * i);
                }
                q[0][0] = 1.;
                u[0] = r1;
                r[0][0] = r1;
                d[0][0] = 1. / (1 + r1 * dt);
                for (int i = 1; i <= _n; i++) {
                    q[i][0] = 0.5 * q[i - 1][0] * d[i - 1][0];
                    q[i][i] = 0.5 * q[i - 1][i - 1] * d[i - 1][i - 1];
                    for (int j = -i + 2, k = 1; j <= i - 2; j += 2, k++) {
                        q[i][k] = 0.5 * (q[i - 1][k - 1] * d[i - 1][k - 1] + q[i - 1][k] * d[i - 1][k]);
                    }
                    u[i] = _rootFinder.getRoot(getMedian(sigma, i, dt, q, p[i + 1]), 0., 1.);
                    for (int j = -i, k = 0; j <= i; j += 2, k++) {
                        r[i][k] = u[i] * Math.exp(sigma * j * dtSqrt);
                        d[i][k] = 1. / (1 + r[i][k] * dt);
                    }
                }
                final Triple<Double, Double, Double>[][] result = new Triple[_n + 1][_j];
                for (int i = 0; i <= _n; i++) {
                    for (int j = 0; j < _j; j++) {
                        result[i][j] = new Triple<>(r[i][j], d[i][j], q[i][j]);
                    }
                }
                return new RecombiningBinomialTree<>(result);
            }

        };
    }

    protected Function1D<Double, Double> getMedian(final double sigma, final int i, final double dt,
            final double[][] q, final double p) {
        return new Function1D<Double, Double>() {

            @Override
            public Double evaluate(final Double u) {
                double sum = 0.;
                final double dtSqrt = Math.sqrt(dt);
                for (int j = -i, k = 0; j <= i; j += 2, k++) {
                    sum += q[i][k] / (1 + u * Math.exp(sigma * j * dtSqrt) * dt);

                }
                return sum - p;
            }
        };
    }
}