com.opengamma.analytics.financial.provider.sensitivity.multicurve.ParameterSensitivityMulticurveUnderlyingMatrixCalculator.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.provider.sensitivity.multicurve.ParameterSensitivityMulticurveUnderlyingMatrixCalculator.java

Source

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

import it.unimi.dsi.fastutil.ints.IntArrayList;

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

import org.apache.commons.lang.ArrayUtils;

import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitor;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.util.tuple.DoublesPair;

/**
 * For an instrument, computes the sensitivity of a value (often the present value or a par spread) to the parameters used in the curve.
 * The meaning of "parameters" will depend of the way the curve is stored (interpolated yield, function parameters, etc.).
 * The return format is ParameterSensitivity object.
 */
public class ParameterSensitivityMulticurveUnderlyingMatrixCalculator
        extends ParameterSensitivityMulticurveMatrixAbstractCalculator {

    /**
     * Constructor
     * @param curveSensitivityCalculator The curve sensitivity calculator.
     */
    public ParameterSensitivityMulticurveUnderlyingMatrixCalculator(
            final InstrumentDerivativeVisitor<MulticurveProviderInterface, MulticurveSensitivity> curveSensitivityCalculator) {
        super(curveSensitivityCalculator);
    }

    /**
     * Computes the sensitivity with respect to the parameters from the point sensitivities to the continuously compounded rate.
     * @param sensitivity The point sensitivity.
     * @param multicurves The multi-curve provider. Not null.
     * @param curvesSet The set of curves for which the sensitivity will be computed. Not null.
     * @return The sensitivity (as a ParameterSensitivity). ??The order of the sensitivity is by curve as provided by the curvesSet??
     */
    @Override
    public DoubleMatrix1D pointToParameterSensitivity(final MulticurveSensitivity sensitivity,
            final MulticurveProviderInterface multicurves, final Set<String> curvesSet) {
        // TODO: The first part depends only of the multicurves and curvesSet, not the sensitivity. Should it be refactored and done only once?
        final Set<String> curveNamesSet = multicurves.getAllNames(); // curvesSet; //
        final int nbCurve = curveNamesSet.size();
        final String[] curveNamesArray = new String[nbCurve];
        int loopname = 0;
        final LinkedHashMap<String, Integer> curveNum = new LinkedHashMap<>();
        for (final String name : curveNamesSet) { // loop over all curves (by name)
            curveNamesArray[loopname] = name;
            curveNum.put(name, loopname++);
        }
        final int[] nbNewParameters = new int[nbCurve];
        // Implementation note: nbNewParameters - number of new parameters in the curve, parameters not from an underlying curve which is another curve of the bundle.
        final int[][] indexOther = new int[nbCurve][];
        // Implementation note: indexOther - the index of the underlying curves, if any.
        loopname = 0;
        for (final String name : curveNamesSet) { // loop over all curves (by name)
            nbNewParameters[loopname] = multicurves.getNumberOfParameters(name);
            loopname++;
        }
        loopname = 0;
        for (final String name : curveNamesSet) { // loop over all curves (by name)
            final List<String> underlyingCurveNames = multicurves.getUnderlyingCurvesNames(name);
            final IntArrayList indexOtherList = new IntArrayList();
            for (final String u : underlyingCurveNames) {
                final Integer i = curveNum.get(u);
                if (i != null) {
                    indexOtherList.add(i);
                    nbNewParameters[loopname] -= nbNewParameters[i]; // Only one level: a curve used as an underlying can not have an underlying itself.
                }
            }
            indexOther[loopname] = indexOtherList.toIntArray();
            loopname++;
        }
        final int nbSensiCurve = curvesSet.size();
        //    for (final String name : curveNamesSet) { // loop over all curves (by name)
        //      if (curvesSet.contains(name)) {
        //        nbSensiCurve++;
        //      }
        //    }
        final int[] nbNewParamSensiCurve = new int[nbSensiCurve];
        // Implementation note: nbNewParamSensiCurve
        final int[][] indexOtherSensiCurve = new int[nbSensiCurve][];
        // Implementation note: indexOtherSensiCurve -
        final int[] startCleanParameter = new int[nbSensiCurve];
        // Implementation note: startCleanParameter - for each curve for which the sensitivity should be computed, the index in the total sensitivity vector at which that curve start.
        final int[][] startDirtyParameter = new int[nbSensiCurve][];
        // Implementation note: startDirtyParameter - for each curve for which the sensitivity should be computed, the indexes of the underlying curves.
        int nbSensitivityCurve = 0;
        int nbCleanParameters = 0;
        int currentDirtyStart = 0;
        for (final String name : curvesSet) { // loop over all curves (by name)
            //      if (curvesSet.contains(name)) {
            final int num = curveNum.get(name);
            final IntArrayList startDirtyParameterList = new IntArrayList();
            final List<String> underlyingCurveNames = multicurves.getUnderlyingCurvesNames(name);
            for (final String u : underlyingCurveNames) {
                final Integer i = curveNum.get(u);
                if (i != null) {
                    startDirtyParameterList.add(currentDirtyStart);
                    currentDirtyStart += nbNewParameters[i];
                }
            }
            startDirtyParameterList.add(currentDirtyStart);
            currentDirtyStart += nbNewParameters[num];
            startDirtyParameter[nbSensitivityCurve] = startDirtyParameterList.toIntArray();
            nbNewParamSensiCurve[nbSensitivityCurve] = nbNewParameters[num];
            indexOtherSensiCurve[nbSensitivityCurve] = indexOther[num];
            startCleanParameter[nbSensitivityCurve] = nbCleanParameters;
            nbCleanParameters += nbNewParamSensiCurve[nbSensitivityCurve];
            nbSensitivityCurve++;
            //      }
        }
        // Implementation note: Compute the "dirty" sensitivity, i.e. the sensitivity where the underlying curves are not taken into account.
        double[] sensiDirty = new double[0];
        final Map<String, List<DoublesPair>> sensitivityDsc = sensitivity.getYieldDiscountingSensitivities();
        final Map<String, List<ForwardSensitivity>> sensitivityFwd = sensitivity.getForwardSensitivities();
        for (final String name : curvesSet) { // loop over all curves (by name)
            //      if (curvesSet.contains(name)) {
            final int nbParam = multicurves.getNumberOfParameters(name);
            final double[] s1Name = new double[nbParam];
            final double[] sDsc1Name = multicurves.parameterSensitivity(name, sensitivityDsc.get(name));
            final double[] sFwd1Name = multicurves.parameterForwardSensitivity(name, sensitivityFwd.get(name));
            //        if ((sDsc1Name != null) && (sFwd1Name == null)) {
            //          s1Name = sDsc1Name;
            //        }
            //        if ((sDsc1Name == null) && (sFwd1Name != null)) {
            //          s1Name = sFwd1Name;
            //        }
            //        if ((sDsc1Name != null) && (sFwd1Name != null)) {
            for (int loopp = 0; loopp < nbParam; loopp++) {
                s1Name[loopp] = sDsc1Name[loopp] + sFwd1Name[loopp];
            }
            //        }
            sensiDirty = ArrayUtils.addAll(sensiDirty, s1Name);
            //      }
        }
        // Implementation note: "clean" the sensitivity, i.e. add the underlying curve parts.
        final double[] sensiClean = new double[nbCleanParameters];
        for (int loopcurve = 0; loopcurve < nbSensiCurve; loopcurve++) {
            for (int loopo = 0; loopo < indexOtherSensiCurve[loopcurve].length; loopo++) {
                if (curvesSet.contains(curveNamesArray[indexOtherSensiCurve[loopcurve][loopo]])) {
                    for (int loops = 0; loops < nbNewParamSensiCurve[indexOtherSensiCurve[loopcurve][loopo]]; loops++) {
                        sensiClean[startCleanParameter[indexOtherSensiCurve[loopcurve][loopo]]
                                + loops] += sensiDirty[startDirtyParameter[loopcurve][loopo] + loops];
                    }
                }
            }
            for (int loops = 0; loops < nbNewParamSensiCurve[loopcurve]; loops++) {
                sensiClean[startCleanParameter[loopcurve]
                        + loops] += sensiDirty[startDirtyParameter[loopcurve][indexOtherSensiCurve[loopcurve].length]
                                + loops];
            }
        }
        return new DoubleMatrix1D(sensiClean);
    }

}