/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.provider.calculator.generic; import java.util.LinkedHashMap; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlock; import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle; import com.opengamma.analytics.financial.provider.description.interestrate.ParameterProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterAbstractCalculator; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; import com.opengamma.analytics.math.matrix.MatrixAlgebra; import com.opengamma.analytics.math.matrix.OGMatrixAlgebra; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * Calculator of the sensitivity to the market quotes of instruments used to build the curves. * The sensitivities are computed as a block (vector) for each curve/currency pair. * The sensitivity to a particular curve can be in several currencies. * @param <DATA_TYPE> Data type. */ public final class MarketQuoteSensitivityBlockCalculator<DATA_TYPE extends ParameterProviderInterface> { /** * The matrix algebra used for matrix inversion. */ private static final MatrixAlgebra MATRIX_ALGEBRA = new OGMatrixAlgebra(); //TODO make this a parameter /** * The parameter sensitivity calculator. The parameters are the parameters used to described the curve. */ private final ParameterSensitivityParameterAbstractCalculator<DATA_TYPE> _parameterSensitivityCalculator; /** * The constructor. * @param parameterSensitivityCalculator The parameter sensitivity calculator. */ public MarketQuoteSensitivityBlockCalculator(final ParameterSensitivityParameterAbstractCalculator<DATA_TYPE> parameterSensitivityCalculator) { _parameterSensitivityCalculator = parameterSensitivityCalculator; } /** * Compute the market quote sensitivity from a parameter sensitivity. * @param parameterSensitivity The parameter sensitivity. * @param units The curve building units data. * @return The market quote sensitivity. */ public MultipleCurrencyParameterSensitivity fromParameterSensitivity(final MultipleCurrencyParameterSensitivity parameterSensitivity, final CurveBuildingBlockBundle units) { ArgumentChecker.notNull(parameterSensitivity, "Sensitivity"); ArgumentChecker.notNull(units, "Units"); MultipleCurrencyParameterSensitivity result = new MultipleCurrencyParameterSensitivity(); for (final Pair<String, Currency> nameCcy : parameterSensitivity.getAllNamesCurrency()) { final LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> oneCurveSensiMap = new LinkedHashMap<>(); final Pair<CurveBuildingBlock, DoubleMatrix2D> unitPair = units.getBlock(nameCcy.getFirst()); ArgumentChecker.notNull(parameterSensitivity.getSensitivity(nameCcy), "sensitivity for " + nameCcy); ArgumentChecker.notNull(unitPair, "curve building block / Jacobian pair for " + nameCcy.getFirst()); ArgumentChecker.notNull(unitPair.getSecond(), "Jacobian"); final DoubleMatrix1D matrix = (DoubleMatrix1D) MATRIX_ALGEBRA.multiply(parameterSensitivity.getSensitivity(nameCcy), unitPair.getSecond()); if (matrix != null) { final double[] oneCurveSensiArray = ((DoubleMatrix1D) MATRIX_ALGEBRA.multiply(parameterSensitivity.getSensitivity(nameCcy), unitPair.getSecond())).getData(); for (final String name2 : unitPair.getFirst().getAllNames()) { final int nbParameters = unitPair.getFirst().getNbParameters(name2); final int start = unitPair.getFirst().getStart(name2); final double[] sensiName2 = new double[nbParameters]; System.arraycopy(oneCurveSensiArray, start, sensiName2, 0, nbParameters); oneCurveSensiMap.put(Pairs.of(name2, nameCcy.getSecond()), new DoubleMatrix1D(sensiName2)); } final MultipleCurrencyParameterSensitivity sensiName = new MultipleCurrencyParameterSensitivity(oneCurveSensiMap); result = result.plus(sensiName); } } return result; } /** * Compute the market quote sensitivity from an instrument. * @param instrument The instrument. Not null. * @param provider The provider * @param units The curve building units data. * @return The market quote sensitivity. */ public MultipleCurrencyParameterSensitivity fromInstrument(final InstrumentDerivative instrument, final DATA_TYPE provider, final CurveBuildingBlockBundle units) { ArgumentChecker.notNull(instrument, "instrument"); ArgumentChecker.notNull(provider, "provider"); ArgumentChecker.notNull(units, "units"); final MultipleCurrencyParameterSensitivity parameterSensitivity = _parameterSensitivityCalculator.calculateSensitivity(instrument, provider); return fromParameterSensitivity(parameterSensitivity, units); } }