@Test
  public void curveSensitivityFRA() {
    final YieldCurveBundle curves = TestsDataSetsSABR.createCurves1();
    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();
    yieldsFunding[1] = curveFunding.getInterestRate(nodeTimesFunding[1]);
    final YieldAndDiscountCurve tempCurveFunding =
        YieldCurve.from(
            InterpolatedDoublesCurve.fromSorted(
                nodeTimesFunding, yieldsFunding, new LinearInterpolator1D()));
    final YieldAndDiscountCurve bumpedCurve =
        tempCurveFunding.withSingleShift(nodeTimesFunding[1], deltaShift);
    final YieldCurveBundle curvesBumped = new YieldCurveBundle();
    curvesBumped.addAll(curves);
    curvesBumped.replaceCurve("Bumped Curve", bumpedCurve);
    final double bumpedPvDsc = FRA_METHOD.presentValue(fraBumped, curvesBumped).getAmount();
    final double[] resDsc = new double[1];
    resDsc[0] = (bumpedPvDsc - pv) / deltaShift;

    final double[] nodeTimesFundingMethod = new double[] {FRA.getPaymentTime()};
    final double[] sensiFundingMethod =
        SensitivityFiniteDifference.curveSensitivity(
            fraBumped,
            curves,
            pv,
            FUNDING_CURVE_NAME,
            bumpedCurveName,
            nodeTimesFundingMethod,
            deltaShift,
            FRA_METHOD);
    assertEquals(
        "Sensitivity finite difference method: number of node", 1, sensiFundingMethod.length);
    for (int loopnode = 0; loopnode < sensiFundingMethod.length; loopnode++) {
      assertEquals(
          "Sensitivity finite difference method: node sensitivity",
          resDsc[loopnode],
          sensiFundingMethod[loopnode]);
    }
  }
 @Test
 public void curveSensitivityCentered() {
   final YieldCurveBundle curves = TestsDataSetsSABR.createCurves1();
   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 double[] nodeTimesForwardMethod =
       new double[] {FRA.getFixingPeriodStartTime(), FRA.getFixingPeriodEndTime()};
   final double[] sensiForward =
       SensitivityFiniteDifference.curveSensitivity(
           fraBumpedForward,
           curves,
           pv,
           FORWARD_CURVE_NAME,
           bumpedCurveName,
           nodeTimesForwardMethod,
           deltaShift,
           FRA_METHOD);
   final double[] sensiForwardCentered =
       SensitivityFiniteDifference.curveSensitivity(
           fraBumpedForward,
           curves,
           pv,
           FORWARD_CURVE_NAME,
           bumpedCurveName,
           nodeTimesForwardMethod,
           deltaShift,
           FRA_METHOD,
           FiniteDifferenceType.CENTRAL);
   final double[] sensiForwardCentered2 =
       SensitivityFiniteDifference.curveSensitivity(
           fraBumpedForward,
           curves,
           FORWARD_CURVE_NAME,
           bumpedCurveName,
           nodeTimesForwardMethod,
           deltaShift,
           FRA_METHOD);
   final double[] sensiForwardForward =
       SensitivityFiniteDifference.curveSensitivity(
           fraBumpedForward,
           curves,
           pv,
           FORWARD_CURVE_NAME,
           bumpedCurveName,
           nodeTimesForwardMethod,
           deltaShift,
           FRA_METHOD,
           FiniteDifferenceType.FORWARD);
   final double[] sensiForwardBackward =
       SensitivityFiniteDifference.curveSensitivity(
           fraBumpedForward,
           curves,
           pv,
           FORWARD_CURVE_NAME,
           bumpedCurveName,
           nodeTimesForwardMethod,
           deltaShift,
           FRA_METHOD,
           FiniteDifferenceType.BACKWARD);
   assertEquals("Sensitivity finite difference method: number of node", 2, sensiForward.length);
   assertEquals(
       "Sensitivity finite difference method: number of node", 2, sensiForwardCentered.length);
   assertEquals(
       "Sensitivity finite difference method: number of node", 2, sensiForwardCentered2.length);
   assertEquals(
       "Sensitivity finite difference method: number of node", 2, sensiForwardForward.length);
   assertEquals(
       "Sensitivity finite difference method: number of node", 2, sensiForwardBackward.length);
   for (int loopnode = 0; loopnode < sensiForward.length; loopnode++) {
     assertEquals(
         "Sensitivity finite difference method: centered vs non-centered",
         sensiForward[loopnode],
         sensiForwardForward[loopnode],
         1.0E-10);
     assertEquals(
         "Sensitivity finite difference method: centered vs non-centered",
         sensiForwardForward[loopnode],
         sensiForwardCentered[loopnode],
         1.0E-1);
     assertEquals(
         "Sensitivity finite difference method: centered vs non-centered",
         sensiForwardBackward[loopnode],
         sensiForwardCentered[loopnode],
         1.0E-1);
     assertEquals(
         "Sensitivity finite difference method: centered vs non-centered",
         sensiForwardCentered[loopnode],
         sensiForwardCentered2[loopnode],
         1.0E-10);
   }
 }