CouponIborCompoundingFlatSpreadDiscountingMethod { public double presentValueSpreadSensitivity(final CouponIborCompoundingFlatSpread coupon, final MulticurveProviderInterface multicurve) { ArgumentChecker.notNull(coupon, "Coupon"); ArgumentChecker.notNull(multicurve, "Multi-curve provider"); final int nbSubPeriod = coupon.getFixingTimes().length; final double spread = coupon.getSpread(); final double[] cpa = new double[nbSubPeriod + 1]; final double[] cpaAccumulated = new double[nbSubPeriod + 1]; final double[] forward = new double[nbSubPeriod]; cpa[0] = coupon.getCompoundingPeriodAmountAccumulated(); cpaAccumulated[0] = coupon.getCompoundingPeriodAmountAccumulated(); for (int loopsub = 0; loopsub < nbSubPeriod; loopsub++) { forward[loopsub] = multicurve.getSimplyCompoundForwardRate(coupon.getIndex(), coupon.getFixingPeriodStartTimes()[loopsub], coupon.getFixingPeriodEndTimes()[loopsub], coupon.getFixingPeriodAccrualFactors()[loopsub]); cpa[loopsub + 1] += coupon.getNotional() * (forward[loopsub] + spread) * coupon.getSubperiodsAccrualFactors()[loopsub]; cpa[loopsub + 1] += cpaAccumulated[loopsub] * forward[loopsub] * coupon.getSubperiodsAccrualFactors()[loopsub]; cpaAccumulated[loopsub + 1] = cpaAccumulated[loopsub] + cpa[loopsub + 1]; } final double df = multicurve.getDiscountFactor(coupon.getCurrency(), coupon.getPaymentTime()); final double pvBar = 1.0; final double[] cpaAccumulatedBar = new double[nbSubPeriod + 1]; cpaAccumulatedBar[nbSubPeriod] = df * pvBar; final double[] cpaBar = new double[nbSubPeriod + 1]; double spreadBar = 0; for (int loopsub = nbSubPeriod - 1; loopsub >= 0; loopsub--) { cpaAccumulatedBar[loopsub] = cpaAccumulatedBar[loopsub + 1]; cpaBar[loopsub + 1] += cpaAccumulatedBar[loopsub + 1]; cpaAccumulatedBar[loopsub] += forward[loopsub] * coupon.getSubperiodsAccrualFactors()[loopsub] * cpaBar[loopsub + 1]; spreadBar += coupon.getNotional() * coupon.getSubperiodsAccrualFactors()[loopsub] * cpaBar[loopsub + 1]; } return spreadBar; } private  CouponIborCompoundingFlatSpreadDiscountingMethod(); static CouponIborCompoundingFlatSpreadDiscountingMethod getInstance(); MultipleCurrencyAmount presentValue(final CouponIborCompoundingFlatSpread coupon, final MulticurveProviderInterface multicurve); MultipleCurrencyAmount presentValue(
      final CouponIborCompoundingFlatSpread coupon,
      final MulticurveProviderInterface multicurve,
      final ForwardRateProvider<IborIndex> forwardRateProvider); double presentValueSpreadSensitivity(final CouponIborCompoundingFlatSpread coupon, final MulticurveProviderInterface multicurve); MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final CouponIborCompoundingFlatSpread coupon, final MulticurveProviderInterface multicurve);  }
@Test public void presentValueMarketQuoteSensitivity() { final CouponIborCompoundingFlatSpreadDefinition cpnShiftedPDefinition = CouponIborCompoundingFlatSpreadDefinition.from(NOTIONAL, START_DATE, END_DATE, CADCDOR3M, SPREAD + SHIFT, StubType.SHORT_START, CADCDOR3M.getBusinessDayConvention(), CADCDOR3M.isEndOfMonth(), CALENDAR); final CouponIborCompoundingFlatSpreadDefinition cpnShiftedMDefinition = CouponIborCompoundingFlatSpreadDefinition.from(NOTIONAL, START_DATE, END_DATE, CADCDOR3M, SPREAD - SHIFT, StubType.SHORT_START, CADCDOR3M.getBusinessDayConvention(), CADCDOR3M.isEndOfMonth(), CALENDAR); final CouponIborCompoundingFlatSpread cpnShiftedP = cpnShiftedPDefinition.toDerivative(REFERENCE_DATE_BEFORE); final CouponIborCompoundingFlatSpread cpnShiftedM = cpnShiftedMDefinition.toDerivative(REFERENCE_DATE_BEFORE); final MultipleCurrencyAmount pvP = cpnShiftedP.accept(PVDC, MULTICURVES); final MultipleCurrencyAmount pvM = cpnShiftedM.accept(PVDC, MULTICURVES); final double mqsExpected = (pvP.getAmount(CAD) - pvM.getAmount(CAD)) / (2 * SHIFT); final double mqsCalculator = CPN_BEFORE.accept(PVMQSDC, MULTICURVES); final double mqsMethod = METHOD_COMPOUNDED.presentValueSpreadSensitivity(CPN_BEFORE, MULTICURVES); assertEquals("CouponIborCompoundingFlatSpreadDiscountingMethod: Present value market quote sensitivity", mqsExpected, mqsCalculator, TOLERANCE_PV_DELTA); assertEquals("CouponIborCompoundingFlatSpreadDiscountingMethod: Present value market quote sensitivity", mqsCalculator, mqsMethod, TOLERANCE_PV_DELTA); }