final double deltaShift = 1.0E-8;
final double pv = FRA_METHOD.presentValue(FRA, curves).getAmount();
// 1. Forward curve sensitivity
final String bumpedCurveName = "Bumped Curve";
final String[] bumpedCurvesForwardName = {FUNDING_CURVE_NAME, bumpedCurveName};
final ForwardRateAgreement fraBumpedForward = (ForwardRateAgreement) FRA_DEFINITION.toDerivative(REFERENCE_DATE, bumpedCurvesForwardName);
final YieldAndDiscountCurve curveForward = curves.getCurve(FORWARD_CURVE_NAME);
final double[] timeForward = new double[2];
timeForward[0] = FRA.getFixingPeriodStartTime();
timeForward[1] = FRA.getFixingPeriodEndTime();
final int nbForwardDate = timeForward.length;
final double[] yieldsForward = new double[nbForwardDate + 1];
final double[] nodeTimesForward = new double[nbForwardDate + 1];
yieldsForward[0] = curveForward.getInterestRate(0.0);
for (int i = 0; i < nbForwardDate; i++) {
nodeTimesForward[i + 1] = timeForward[i];
yieldsForward[i + 1] = curveForward.getInterestRate(nodeTimesForward[i + 1]);
}
final YieldAndDiscountCurve tempCurveForward = YieldCurve.from(InterpolatedDoublesCurve.fromSorted(nodeTimesForward, yieldsForward, new LinearInterpolator1D()));
final double[] sensiPvForwardFD = new double[nbForwardDate];
for (int i = 0; i < nbForwardDate; i++) {
final YieldAndDiscountCurve bumpedCurveForward = tempCurveForward.withSingleShift(nodeTimesForward[i + 1], deltaShift);
final YieldCurveBundle curvesBumpedForward = new YieldCurveBundle();
curvesBumpedForward.addAll(curves);
curvesBumpedForward.setCurve("Bumped Curve", bumpedCurveForward);
final double bumpedPv = FRA_METHOD.presentValue(fraBumpedForward, curvesBumpedForward).getAmount();
sensiPvForwardFD[i] = (bumpedPv - pv) / deltaShift;
}
final double[] nodeTimesForwardMethod = new double[] {FRA.getFixingPeriodStartTime(), FRA.getFixingPeriodEndTime()};
final double[] sensiForwardMethod = SensitivityFiniteDifference.curveSensitivity(fraBumpedForward, curves, pv, FORWARD_CURVE_NAME, bumpedCurveName, nodeTimesForwardMethod, deltaShift, FRA_METHOD);
assertEquals("Sensitivity finite difference method: number of node", 2, sensiForwardMethod.length);
for (int loopnode = 0; loopnode < sensiForwardMethod.length; loopnode++) {
assertEquals("Sensitivity finite difference method: node sensitivity", sensiPvForwardFD[loopnode], sensiForwardMethod[loopnode]);
}
// 2. Funding curve sensitivity
final String[] bumpedCurvesFundingName = {bumpedCurveName, FORWARD_CURVE_NAME};
final ForwardRateAgreement fraBumped = (ForwardRateAgreement) FRA_DEFINITION.toDerivative(REFERENCE_DATE, bumpedCurvesFundingName);
final YieldAndDiscountCurve curveFunding = curves.getCurve(FUNDING_CURVE_NAME);
final double[] yieldsFunding = new double[2];
final double[] nodeTimesFunding = new double[2];
yieldsFunding[0] = curveFunding.getInterestRate(0.0);
nodeTimesFunding[1] = FRA.getPaymentTime();