final double deltaShift = 1.0E-6;
final String bumpedCurveName = "Bumped Curve";
// 1. Forward curve sensitivity
final String[] CurveNameBumpedForward = {FUNDING_CURVE_NAME, bumpedCurveName };
final CapFloorCMSSpread floorBumpedForward = (CapFloorCMSSpread) CMS_FLOOR_SPREAD_DEFINITION.toDerivative(REFERENCE_DATE, CurveNameBumpedForward);
final DoubleAVLTreeSet forwardTime = new DoubleAVLTreeSet();
for (int loopcpn = 0; loopcpn < CMS_FLOOR_SPREAD.getUnderlyingSwap1().getSecondLeg().getNumberOfPayments(); loopcpn++) {
final CouponIbor cpn = (CouponIbor) CMS_FLOOR_SPREAD.getUnderlyingSwap1().getSecondLeg().getNthPayment(loopcpn);
forwardTime.add(cpn.getFixingPeriodStartTime());
forwardTime.add(cpn.getFixingPeriodEndTime());
}
for (int loopcpn = 0; loopcpn < CMS_FLOOR_SPREAD.getUnderlyingSwap2().getSecondLeg().getNumberOfPayments(); loopcpn++) {
final CouponIbor cpn = (CouponIbor) CMS_FLOOR_SPREAD.getUnderlyingSwap2().getSecondLeg().getNthPayment(loopcpn);
forwardTime.add(cpn.getFixingPeriodStartTime());
forwardTime.add(cpn.getFixingPeriodEndTime());
}
final double[] nodeTimesForward = forwardTime.toDoubleArray();
final double[] sensiForwardMethod = SensitivityFiniteDifference.curveSensitivity(floorBumpedForward, SABR_BUNDLE, FORWARD_CURVE_NAME, bumpedCurveName, nodeTimesForward, deltaShift,
METHOD_CMS_SPREAD);
final List<DoublesPair> sensiPvForward = pvcsFloor.getSensitivities().get(FORWARD_CURVE_NAME);
for (int loopnode = 0; loopnode < sensiForwardMethod.length; loopnode++) {
final DoublesPair pairPv = sensiPvForward.get(loopnode);
assertEquals("Sensitivity CMS cap/floor pv to forward curve: Node " + loopnode, nodeTimesForward[loopnode], pairPv.getFirst(), 1E-8);
assertEquals("Sensitivity finite difference method: forward node sensitivity " + loopnode + " - Difference " + (sensiForwardMethod[loopnode] - pairPv.second), 0,
(sensiForwardMethod[loopnode] - pairPv.second) / pairPv.second, deltaToleranceRelative);
}
// 2. Discounting curve sensitivity
final String[] CurveNameBumpedDisc = {bumpedCurveName, FORWARD_CURVE_NAME };
final CapFloorCMSSpread floorBumpedDisc = (CapFloorCMSSpread) CMS_FLOOR_SPREAD_DEFINITION.toDerivative(REFERENCE_DATE, CurveNameBumpedDisc);
final DoubleAVLTreeSet discTime = new DoubleAVLTreeSet();
discTime.add(floorBumpedDisc.getPaymentTime());
for (int loopcpn = 0; loopcpn < CMS_FLOOR_SPREAD.getUnderlyingSwap1().getSecondLeg().getNumberOfPayments(); loopcpn++) {
final CouponIbor cpn = (CouponIbor) CMS_FLOOR_SPREAD.getUnderlyingSwap1().getSecondLeg().getNthPayment(loopcpn);
discTime.add(cpn.getPaymentTime());
}
for (int loopcpn = 0; loopcpn < CMS_FLOOR_SPREAD.getUnderlyingSwap2().getSecondLeg().getNumberOfPayments(); loopcpn++) {
final CouponIbor cpn = (CouponIbor) CMS_FLOOR_SPREAD.getUnderlyingSwap2().getSecondLeg().getNthPayment(loopcpn);
discTime.add(cpn.getPaymentTime());
}
final double[] nodeTimesDisc = discTime.toDoubleArray();
final double[] sensiDiscMethod = SensitivityFiniteDifference.curveSensitivity(floorBumpedDisc, SABR_BUNDLE, FUNDING_CURVE_NAME, bumpedCurveName, nodeTimesDisc, deltaShift, METHOD_CMS_SPREAD);
final List<DoublesPair> sensiPvDisc = pvcsFloor.getSensitivities().get(FUNDING_CURVE_NAME);
for (int loopnode = 0; loopnode < sensiDiscMethod.length; loopnode++) {
final DoublesPair pairPv = sensiPvDisc.get(loopnode);
assertEquals("Sensitivity CMS cap/floor pv to forward curve: Node " + loopnode, nodeTimesDisc[loopnode], pairPv.getFirst(), 1E-8);