com.opengamma.analytics.financial.interestrate.annuity.ZSpreadCalculator.java Source code

Java tutorial

Introduction

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.Validate;

import com.opengamma.analytics.financial.interestrate.PresentValueCalculator;
import com.opengamma.analytics.financial.interestrate.PresentValueCurveSensitivityCalculator;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity;
import com.opengamma.analytics.financial.interestrate.payments.derivative.Payment;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.rootfinding.BracketRoot;
import com.opengamma.analytics.math.rootfinding.BrentSingleRootFinder;
import com.opengamma.analytics.math.rootfinding.RealSingleRootFinder;
import com.opengamma.util.tuple.DoublesPair;

/**
 * 
 */
public final class ZSpreadCalculator {
    private static final PresentValueCalculator PRESENT_VALUE_CALCULATOR = PresentValueCalculator.getInstance();
    private static final PresentValueCurveSensitivityCalculator PV_SENSITIVITY_CALCULATOR = PresentValueCurveSensitivityCalculator
            .getInstance();
    private static final BracketRoot ROOT_BRACKETER = new BracketRoot();
    private static final RealSingleRootFinder ROOT_FINDER = new BrentSingleRootFinder();
    private static final ZSpreadCalculator CALCULATOR = new ZSpreadCalculator();

    private ZSpreadCalculator() {
    }

    public static ZSpreadCalculator getInstance() {
        return CALCULATOR;
    }

    public double calculateZSpread(final Annuity<? extends Payment> annuity, final YieldCurveBundle curves,
            final double price) {
        Validate.notNull(annuity, "annuity");
        Validate.notNull(curves, "curves");

        final Function1D<Double, Double> f = new Function1D<Double, Double>() {
            @Override
            public Double evaluate(final Double y) {
                return calculatePriceForZSpread(annuity, curves, y) - price;
            }
        };

        final double[] range = ROOT_BRACKETER.getBracketedPoints(f, 0.0, 1.2);
        return ROOT_FINDER.getRoot(f, range[0], range[1]);
    }

    public double calculatePriceForZSpread(final Annuity<? extends Payment> annuity, final YieldCurveBundle curves,
            final double zSpread) {
        Validate.notNull(annuity, "annuity");
        Validate.notNull(curves, "curves");

        double sum = 0;

        final int n = annuity.getNumberOfPayments();
        Payment payment;
        for (int i = 0; i < n; i++) {
            payment = annuity.getNthPayment(i);
            final double temp = PRESENT_VALUE_CALCULATOR.visit(payment, curves);
            sum += temp * Math.exp(-zSpread * payment.getPaymentTime());
        }
        return sum;
    }

    public double calculatePriceSensitivityToZSpread(final Annuity<? extends Payment> annuity,
            final YieldCurveBundle curves, final double zSpread) {
        Validate.notNull(annuity, "annuity");
        Validate.notNull(curves, "curves");

        double sum = 0;

        final int n = annuity.getNumberOfPayments();
        Payment payment;
        for (int i = 0; i < n; i++) {
            payment = annuity.getNthPayment(i);
            final double temp = PRESENT_VALUE_CALCULATOR.visit(payment, curves);
            final double time = payment.getPaymentTime();
            sum -= time * temp * Math.exp(-zSpread * time);
        }
        return sum;
    }

    public Map<String, List<DoublesPair>> calculatePriceSensitivityToCurve(final Annuity<? extends Payment> annuity,
            final YieldCurveBundle curves, final double zSpread) {
        Validate.notNull(annuity, "annuity");
        Validate.notNull(curves, "curves");

        final Map<String, List<DoublesPair>> temp = PV_SENSITIVITY_CALCULATOR.visit(annuity, curves);
        if (zSpread == 0.0) {
            return temp;
        }
        final Map<String, List<DoublesPair>> result = new HashMap<String, List<DoublesPair>>();
        for (final String name : temp.keySet()) {
            final List<DoublesPair> unadjusted = temp.get(name);
            final ArrayList<DoublesPair> adjusted = new ArrayList<DoublesPair>(unadjusted.size());
            for (final DoublesPair pair : unadjusted) {
                final DoublesPair newPair = new DoublesPair(pair.first,
                        pair.second * Math.exp(-zSpread * pair.first));
                adjusted.add(newPair);
            }
            result.put(name, adjusted);
        }
        return result;
    }

    public Map<String, List<DoublesPair>> calculateZSpreadSensitivityToCurve(
            final Annuity<? extends Payment> annuity, final YieldCurveBundle curves, final double zSpread) {
        Validate.notNull(annuity, "annuity");
        Validate.notNull(curves, "curves");

        final double dPricedZ = calculatePriceSensitivityToZSpread(annuity, curves, zSpread);
        Validate.isTrue(dPricedZ != 0.0, "Price Sensitivity To ZSpread is zero");

        final Map<String, List<DoublesPair>> temp = PV_SENSITIVITY_CALCULATOR.visit(annuity, curves);

        final Map<String, List<DoublesPair>> result = new HashMap<String, List<DoublesPair>>();
        for (final String name : temp.keySet()) {
            final List<DoublesPair> unadjusted = temp.get(name);
            final ArrayList<DoublesPair> adjusted = new ArrayList<DoublesPair>(unadjusted.size());
            for (final DoublesPair pair : unadjusted) {
                final DoublesPair newPair = new DoublesPair(pair.first,
                        -pair.second * Math.exp(-zSpread * pair.first) / dPricedZ);
                adjusted.add(newPair);
            }
            result.put(name, adjusted);
        }
        return result;
    }
}