com.opengamma.analytics.financial.interestrate.capletstripping.CapletStrippingJacobian.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.interestrate.capletstripping.CapletStrippingJacobian.java

Source

/**
 * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.analytics.financial.interestrate.capletstripping;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;

import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption;
import com.opengamma.analytics.financial.model.volatility.BlackFormulaRepository;
import com.opengamma.analytics.financial.model.volatility.SABRTermStructureParameters;
import com.opengamma.analytics.financial.model.volatility.VolatilityModel1D;
import com.opengamma.analytics.financial.model.volatility.smile.function.SABRFormulaData;
import com.opengamma.analytics.financial.model.volatility.smile.function.SABRHaganVolatilityFunction;
import com.opengamma.analytics.math.curve.Curve;
import com.opengamma.analytics.math.curve.InterpolatedCurveBuildingFunction;
import com.opengamma.analytics.math.curve.InterpolatedDoublesCurve;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.interpolation.Interpolator1D;
import com.opengamma.analytics.math.interpolation.TransformedInterpolator1D;
import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle;
import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundleBuilderFunction;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.minimization.ParameterLimitsTransform;

/**
 * @deprecated {@link YieldCurveBundle} is deprecated
 */
@Deprecated
public class CapletStrippingJacobian extends Function1D<DoubleMatrix1D, DoubleMatrix2D> {

    private static final String ALPHA = "alpha";
    private static final String BETA = "beta";
    private static final String NU = "nu";
    private static final String RHO = "rho";

    private static final SABRHaganVolatilityFunction SABR = new SABRHaganVolatilityFunction();

    private final LinkedHashMap<String, Interpolator1D> _interpolators;

    private final Set<String> _parameterNames;
    private final List<CapFloorPricer> _capPricers;
    private final LinkedHashMap<String, InterpolatedDoublesCurve> _knownParameterTermSturctures;
    private final InterpolatedCurveBuildingFunction _curveBuilder;
    private final Interpolator1DDataBundleBuilderFunction _dataBundleBuilder;

    public CapletStrippingJacobian(final List<CapFloor> caps, final YieldCurveBundle yieldCurves,
            final LinkedHashMap<String, double[]> knotPoints,
            final LinkedHashMap<String, Interpolator1D> interpolators,
            final LinkedHashMap<String, ParameterLimitsTransform> parameterTransforms,
            final LinkedHashMap<String, InterpolatedDoublesCurve> knownParameterTermSturctures) {
        Validate.notNull(caps, "caps null");
        Validate.notNull(knotPoints, "null node points");
        Validate.notNull(interpolators, "null interpolators");
        Validate.isTrue(knotPoints.size() == interpolators.size(), "size mismatch between nodes and interpolators");

        _knownParameterTermSturctures = knownParameterTermSturctures;

        final LinkedHashMap<String, Interpolator1D> transInterpolators = new LinkedHashMap<>();
        final Set<String> names = interpolators.keySet();
        _parameterNames = names;
        for (final String name : names) {
            final Interpolator1D temp = new TransformedInterpolator1D(interpolators.get(name),
                    parameterTransforms.get(name));
            transInterpolators.put(name, temp);
        }

        _capPricers = new ArrayList<>(caps.size());
        for (final CapFloor cap : caps) {
            _capPricers.add(new CapFloorPricer(cap, yieldCurves));
        }
        _interpolators = transInterpolators;
        _curveBuilder = new InterpolatedCurveBuildingFunction(knotPoints, transInterpolators);
        _dataBundleBuilder = new Interpolator1DDataBundleBuilderFunction(knotPoints, transInterpolators);

    }

    @Override
    public DoubleMatrix2D evaluate(final DoubleMatrix1D x) {

        final LinkedHashMap<String, Interpolator1DDataBundle> db = _dataBundleBuilder.evaluate(x); //TODO merge these - they do the same work!
        final LinkedHashMap<String, InterpolatedDoublesCurve> curves = _curveBuilder.evaluate(x);

        // set any known (i.e. fixed) curves
        if (_knownParameterTermSturctures != null) {
            curves.putAll(_knownParameterTermSturctures);
        }

        //TODO make this general - not SABR specific
        final Curve<Double, Double> cAlpha = curves.get(ALPHA);
        final Curve<Double, Double> cBeta = curves.get(BETA);
        final Curve<Double, Double> cRho = curves.get(RHO);
        final Curve<Double, Double> cNu = curves.get(NU);
        final VolatilityModel1D volModel = new SABRTermStructureParameters(cAlpha, cBeta, cRho, cNu);

        final int nCaps = _capPricers.size();
        final int m = x.getNumberOfElements();
        final double[][] jac = new double[nCaps][m];
        double f, k, t;

        for (int i = 0; i < nCaps; i++) { //outer loop over caps

            final CapFloorPricer capPricer = _capPricers.get(i);
            final double vega = capPricer.vega(volModel);
            final int nCaplets = capPricer.getNumberCaplets();
            final double[][] greeks = new double[nCaplets][]; //the sensitivity of vol to the model parameters
            final double[] capletVega = new double[nCaplets];
            final double[] capletExpiries = capPricer.getExpiries();
            final double[] capletFwds = capPricer.getForwards();
            final double[] capletDF = capPricer.getDiscountFactors();
            final double[][][] nodeSens = new double[_parameterNames.size()][nCaplets][]; //Sensitivity to the nodes of a particular curve at a particular time
            k = capPricer.getStrike();

            //TODO There will be much repeated calculations here, as many of the caplets are shared across caps
            for (int tIndex = 0; tIndex < nCaplets; tIndex++) {
                f = capletFwds[tIndex];
                t = capletExpiries[tIndex];
                final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
                //TODO again this is SABR specific
                final SABRFormulaData data = new SABRFormulaData(cAlpha.getYValue(t), cBeta.getYValue(t),
                        cRho.getYValue(t), cNu.getYValue(t));
                greeks[tIndex] = SABR.getVolatilityAdjoint(option, f, data); //2nd and 3rd entries are forward & strike sensitivity which we don't use
                capletVega[tIndex] = capletDF[tIndex] * BlackFormulaRepository.vega(f, k, t, greeks[tIndex][0]);

                int parmIndex = 0;
                for (final String name : _parameterNames) {
                    final Interpolator1D itrp = _interpolators.get(name);
                    nodeSens[parmIndex++][tIndex] = itrp.getNodeSensitivitiesForValue(db.get(name), t);
                }
            }

            final double[] res = new double[x.getNumberOfElements()];
            for (int tIndex = 0; tIndex < nCaplets; tIndex++) {
                int index = 0;
                for (int parmIndex = 0; parmIndex < _parameterNames.size(); parmIndex++) {
                    final double temp = capletVega[tIndex] * greeks[tIndex][parmIndex + 3]; //1st 3 are vol, dForward & dStrike
                    final double[] ns = nodeSens[parmIndex][tIndex];
                    for (final double element : ns) {
                        res[index] += element * temp;
                        index++;
                    }
                }
            }
            for (int j = 0; j < res.length; j++) {
                jac[i][j] = res[j] / vega;
            }

        }
        return new DoubleMatrix2D(jac);

    }

}