public SimpleParameterSensitivity calculateSensitivity(final InstrumentDerivative instrument, final HullWhiteOneFactorProviderDiscount hwcurves) {
SimpleParameterSensitivity result = new SimpleParameterSensitivity();
// Discounting
final Set<Currency> ccyDiscounting = hwcurves.getMulticurveProvider().getCurrencies();
for (final Currency ccy : ccyDiscounting) {
final YieldAndDiscountCurve curve = hwcurves.getMulticurveProvider().getCurve(ccy);
ArgumentChecker.isTrue(curve instanceof YieldCurve, "Curve should be a YieldCurve");
final YieldCurve curveYield = (YieldCurve) curve;
ArgumentChecker.isTrue(curveYield.getCurve() instanceof InterpolatedDoublesCurve, "Yield curve should be based on InterpolatedDoublesCurve");
final InterpolatedDoublesCurve curveInt = (InterpolatedDoublesCurve) curveYield.getCurve();
final int nbNodePoint = curveInt.getXDataAsPrimitive().length;
final double[] sensitivity = new double[nbNodePoint];
for (int loopnode = 0; loopnode < nbNodePoint; loopnode++) {
final double[] yieldBumpedPlus = curveInt.getYDataAsPrimitive().clone();
yieldBumpedPlus[loopnode] += _shift;
final YieldAndDiscountCurve dscBumpedPlus = new YieldCurve(curveInt.getName(), new InterpolatedDoublesCurve(curveInt.getXDataAsPrimitive(), yieldBumpedPlus, curveInt.getInterpolator(), true));
final HullWhiteOneFactorProviderDiscount marketDscBumpedPlus = new HullWhiteOneFactorProviderDiscount(hwcurves.getMulticurveProvider().withDiscountFactor(ccy, dscBumpedPlus),
hwcurves.getHullWhiteParameters(), hwcurves.getHullWhiteCurrency());
final double valueBumpedPlus = instrument.accept(_valueCalculator, marketDscBumpedPlus);
final double[] yieldBumpedMinus = curveInt.getYDataAsPrimitive().clone();
yieldBumpedMinus[loopnode] -= _shift;
final YieldAndDiscountCurve dscBumpedMinus = new YieldCurve(curveInt.getName(),
new InterpolatedDoublesCurve(curveInt.getXDataAsPrimitive(), yieldBumpedMinus, curveInt.getInterpolator(), true));
final HullWhiteOneFactorProviderDiscount marketDscBumpedMinus = new HullWhiteOneFactorProviderDiscount(hwcurves.getMulticurveProvider().withDiscountFactor(ccy, dscBumpedMinus),
hwcurves.getHullWhiteParameters(), hwcurves.getHullWhiteCurrency());
final double valueBumpedMinus = instrument.accept(_valueCalculator, marketDscBumpedMinus);
sensitivity[loopnode] = (valueBumpedPlus - valueBumpedMinus) / (2 * _shift);
}
final String name = hwcurves.getMulticurveProvider().getName(ccy);
result = result.plus(name, new DoubleMatrix1D(sensitivity));
}
// Forward ON
final Set<IndexON> indexON = hwcurves.getMulticurveProvider().getIndexesON();
for (final IndexON index : indexON) {
final YieldAndDiscountCurve curve = hwcurves.getMulticurveProvider().getCurve(index);
ArgumentChecker.isTrue(curve instanceof YieldCurve, "Curve should be a YieldCurve");
final YieldCurve curveYield = (YieldCurve) curve;
ArgumentChecker.isTrue(curveYield.getCurve() instanceof InterpolatedDoublesCurve, "Yield curve should be based on InterpolatedDoublesCurve");
final InterpolatedDoublesCurve curveInt = (InterpolatedDoublesCurve) curveYield.getCurve();
final int nbNodePoint = curveInt.getXDataAsPrimitive().length;
final double[] sensitivity = new double[nbNodePoint];
for (int loopnode = 0; loopnode < nbNodePoint; loopnode++) {
final double[] yieldBumpedPlus = curveInt.getYDataAsPrimitive().clone();
yieldBumpedPlus[loopnode] += _shift;
final YieldAndDiscountCurve dscBumpedPlus = new YieldCurve(curveInt.getName(), new InterpolatedDoublesCurve(curveInt.getXDataAsPrimitive(), yieldBumpedPlus, curveInt.getInterpolator(), true));
final HullWhiteOneFactorProviderDiscount marketFwdBumpedPlus = new HullWhiteOneFactorProviderDiscount(hwcurves.getMulticurveProvider().withForward(index, dscBumpedPlus),
hwcurves.getHullWhiteParameters(), hwcurves.getHullWhiteCurrency());
final double valueBumpedPlus = instrument.accept(_valueCalculator, marketFwdBumpedPlus);
final double[] yieldBumpedMinus = curveInt.getYDataAsPrimitive().clone();
yieldBumpedMinus[loopnode] -= _shift;
final YieldAndDiscountCurve dscBumpedMinus = new YieldCurve(curveInt.getName(),
new InterpolatedDoublesCurve(curveInt.getXDataAsPrimitive(), yieldBumpedMinus, curveInt.getInterpolator(), true));
final HullWhiteOneFactorProviderDiscount marketFwdBumpedMinus = new HullWhiteOneFactorProviderDiscount(hwcurves.getMulticurveProvider().withForward(index, dscBumpedMinus),
hwcurves.getHullWhiteParameters(), hwcurves.getHullWhiteCurrency());
final double valueBumpedMinus = instrument.accept(_valueCalculator, marketFwdBumpedMinus);
sensitivity[loopnode] = (valueBumpedPlus - valueBumpedMinus) / (2 * _shift);
}
final String name = hwcurves.getMulticurveProvider().getName(index);
result = result.plus(name, new DoubleMatrix1D(sensitivity));
}
// Forward Ibor - symmetrical
final Set<IborIndex> indexForward = hwcurves.getMulticurveProvider().getIndexesIbor();
for (final IborIndex index : indexForward) {
final YieldAndDiscountCurve curve = hwcurves.getMulticurveProvider().getCurve(index);
ArgumentChecker.isTrue(curve instanceof YieldCurve, "Curve should be a YieldCurve");
final YieldCurve curveYield = (YieldCurve) curve;
ArgumentChecker.isTrue(curveYield.getCurve() instanceof InterpolatedDoublesCurve, "Yield curve should be based on InterpolatedDoublesCurve");
final InterpolatedDoublesCurve curveInt = (InterpolatedDoublesCurve) curveYield.getCurve();
final int nbNodePoint = curveInt.getXDataAsPrimitive().length;
final double[] sensitivity = new double[nbNodePoint];
for (int loopnode = 0; loopnode < nbNodePoint; loopnode++) {
final double[] yieldBumpedPlus = curveInt.getYDataAsPrimitive().clone();
yieldBumpedPlus[loopnode] += _shift;
final YieldAndDiscountCurve dscBumpedPlus = new YieldCurve(curveInt.getName(), new InterpolatedDoublesCurve(curveInt.getXDataAsPrimitive(), yieldBumpedPlus, curveInt.getInterpolator(), true));
final HullWhiteOneFactorProviderDiscount marketFwdBumpedPlus = new HullWhiteOneFactorProviderDiscount(hwcurves.getMulticurveProvider().withForward(index, dscBumpedPlus),
hwcurves.getHullWhiteParameters(), hwcurves.getHullWhiteCurrency());
final double valueBumpedPlus = instrument.accept(_valueCalculator, marketFwdBumpedPlus);
final double[] yieldBumpedMinus = curveInt.getYDataAsPrimitive().clone();
yieldBumpedMinus[loopnode] -= _shift;
final YieldAndDiscountCurve dscBumpedMinus = new YieldCurve(curveInt.getName(),
new InterpolatedDoublesCurve(curveInt.getXDataAsPrimitive(), yieldBumpedMinus, curveInt.getInterpolator(), true));
final HullWhiteOneFactorProviderDiscount marketFwdBumpedMinus = new HullWhiteOneFactorProviderDiscount(hwcurves.getMulticurveProvider().withForward(index, dscBumpedMinus),
hwcurves.getHullWhiteParameters(), hwcurves.getHullWhiteCurrency());
final double valueBumpedMinus = instrument.accept(_valueCalculator, marketFwdBumpedMinus);
sensitivity[loopnode] = (valueBumpedPlus - valueBumpedMinus) / (2 * _shift);