ccyList.add(pvInit.getCurrencyAmounts()[loopccy].getCurrency());
}
// Discounting
final Set<Currency> ccyDiscounting = hullWhite.getMulticurveProvider().getCurrencies();
for (final Currency ccy : ccyDiscounting) {
final YieldAndDiscountCurve curve = hullWhite.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[nbCcy][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(hullWhite.getMulticurveProvider().withDiscountFactor(ccy, dscBumpedPlus),
hullWhite.getHullWhiteParameters(), hullWhite.getHullWhiteCurrency());
final MultipleCurrencyAmount pvBumpedPlus = 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(hullWhite.getMulticurveProvider().withDiscountFactor(ccy, dscBumpedMinus),
hullWhite.getHullWhiteParameters(), hullWhite.getHullWhiteCurrency());
final MultipleCurrencyAmount pvBumpedMinus = instrument.accept(_valueCalculator, marketDscBumpedMinus);
final MultipleCurrencyAmount pvDiff = pvBumpedPlus.plus(pvBumpedMinus.multipliedBy(-1.0));
for (int loopccypv = 0; loopccypv < nbCcy; loopccypv++) {
sensitivity[loopccypv][loopnode] = pvDiff.getAmount(ccyList.get(loopccypv)) / (2 * _shift);
}
}
final String name = hullWhite.getMulticurveProvider().getName(ccy);
for (int loopccypv = 0; loopccypv < nbCcy; loopccypv++) {
result = result.plus(new ObjectsPair<>(name, ccyList.get(loopccypv)), new DoubleMatrix1D(sensitivity[loopccypv]));
}
}
// Forward ON
final Set<IndexON> indexON = hullWhite.getMulticurveProvider().getIndexesON();
for (final IndexON index : indexON) {
final YieldAndDiscountCurve curve = hullWhite.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[nbCcy][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(hullWhite.getMulticurveProvider().withForward(index, dscBumpedPlus),
hullWhite.getHullWhiteParameters(), hullWhite.getHullWhiteCurrency());
final MultipleCurrencyAmount pvBumpedPlus = 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(hullWhite.getMulticurveProvider().withForward(index, dscBumpedMinus),
hullWhite.getHullWhiteParameters(), hullWhite.getHullWhiteCurrency());
final MultipleCurrencyAmount pvBumpedMinus = instrument.accept(_valueCalculator, marketFwdBumpedMinus);
final MultipleCurrencyAmount pvDiff = pvBumpedPlus.plus(pvBumpedMinus.multipliedBy(-1.0));
for (int loopccypv = 0; loopccypv < nbCcy; loopccypv++) {
sensitivity[loopccypv][loopnode] = pvDiff.getAmount(ccyList.get(loopccypv)) / (2 * _shift);
}
}
final String name = hullWhite.getMulticurveProvider().getName(index);
for (int loopccypv = 0; loopccypv < nbCcy; loopccypv++) {
result = result.plus(new ObjectsPair<>(name, ccyList.get(loopccypv)), new DoubleMatrix1D(sensitivity[loopccypv]));
}
}
// Forward Ibor
final Set<IborIndex> indexForward = hullWhite.getMulticurveProvider().getIndexesIbor();
for (final IborIndex index : indexForward) {
final YieldAndDiscountCurve curve = hullWhite.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[nbCcy][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(hullWhite.getMulticurveProvider().withForward(index, dscBumpedPlus),
hullWhite.getHullWhiteParameters(), hullWhite.getHullWhiteCurrency());
final MultipleCurrencyAmount pvBumpedPlus = 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(hullWhite.getMulticurveProvider().withForward(index, dscBumpedMinus),
hullWhite.getHullWhiteParameters(), hullWhite.getHullWhiteCurrency());
final MultipleCurrencyAmount pvBumpedMinus = instrument.accept(_valueCalculator, marketFwdBumpedMinus);
final MultipleCurrencyAmount pvDiff = pvBumpedPlus.plus(pvBumpedMinus.multipliedBy(-1.0));