Java tutorial
/** * 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); } }