CouponIborCompoundingSimpleSpreadDiscountingMethod { public MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final CouponIborCompoundingSimpleSpread coupon, final MulticurveProviderInterface multicurve) { ArgumentChecker.notNull(coupon, "coupon"); ArgumentChecker.notNull(multicurve, "multicurve"); int nbSubPeriod = coupon.getFixingTimes().length; double cpa = coupon.getCompoundingPeriodAmountAccumulated(); double[] investFactor = new double[nbSubPeriod]; for (int loopsub = 0; loopsub < nbSubPeriod; loopsub++) { final double forward = multicurve.getSimplyCompoundForwardRate(coupon.getIndex(), coupon.getFixingPeriodStartTimes()[loopsub], coupon.getFixingPeriodEndTimes()[loopsub], coupon.getFixingPeriodAccrualFactors()[loopsub]); investFactor[loopsub] = 1.0d + forward * coupon.getPaymentPeriodAccrualFactors()[loopsub]; cpa *= investFactor[loopsub]; } final double df = multicurve.getDiscountFactor(coupon.getCurrency(), coupon.getPaymentTime()); double pvBar = 1.0; double dfBar = (cpa - coupon.getNotional() + coupon.getNotional() * coupon.getPaymentYearFraction() * coupon.getSpread()) * pvBar; double cpaBar = df * pvBar; final double[] forwardBar = new double[nbSubPeriod]; for (int loopsub = nbSubPeriod - 1; loopsub >= 0; loopsub--) { forwardBar[loopsub] = cpa / investFactor[loopsub] * coupon.getPaymentPeriodAccrualFactors()[loopsub] * cpaBar; } final Map<String, List<DoublesPair>> mapDsc = new HashMap<>(); final List<DoublesPair> listDiscounting = new ArrayList<>(); listDiscounting.add(DoublesPair.of(coupon.getPaymentTime(), -coupon.getPaymentTime() * df * dfBar)); mapDsc.put(multicurve.getName(coupon.getCurrency()), listDiscounting); final Map<String, List<ForwardSensitivity>> mapFwd = new HashMap<>(); final List<ForwardSensitivity> listForward = new ArrayList<>(); for (int loopsub = 0; loopsub < nbSubPeriod; loopsub++) { listForward.add(new SimplyCompoundedForwardSensitivity(coupon.getFixingPeriodStartTimes()[loopsub], coupon.getFixingPeriodEndTimes()[loopsub], coupon.getFixingPeriodAccrualFactors()[loopsub], forwardBar[loopsub])); } mapFwd.put(multicurve.getName(coupon.getIndex()), listForward); return MultipleCurrencyMulticurveSensitivity.of(coupon.getCurrency(), MulticurveSensitivity.of(mapDsc, mapFwd)); } private  CouponIborCompoundingSimpleSpreadDiscountingMethod(); static CouponIborCompoundingSimpleSpreadDiscountingMethod getInstance(); MultipleCurrencyAmount presentValue(final CouponIborCompoundingSimpleSpread coupon, final MulticurveProviderInterface multicurve); MultipleCurrencyMulticurveSensitivity presentValueCurveSensitivity(final CouponIborCompoundingSimpleSpread coupon, final MulticurveProviderInterface multicurve);  }
@Test public void presentValueCurveSensitivity() { final MultipleCurrencyParameterSensitivity pvpsDepositExact = PS_PV_C.calculateSensitivity(CPN_BEFORE, MULTICURVES, MULTICURVES.getAllNames()); final MultipleCurrencyParameterSensitivity pvpsDepositFD = PS_PV_FDC.calculateSensitivity(CPN_BEFORE, MULTICURVES); AssertSensitivityObjects.assertEquals("CouponIborCompoundingSimpleSpreadDiscountingMethod: presentValueCurveSensitivity ", pvpsDepositExact, pvpsDepositFD, TOLERANCE_PV_DELTA); }
@Test public void presentValueCurveSensitivityMethodVsCalculator() { final MultipleCurrencyMulticurveSensitivity pvcsMethod = METHOD_COMPOUNDED.presentValueCurveSensitivity(CPN_BEFORE, MULTICURVES); final MultipleCurrencyMulticurveSensitivity pvcsCalculator = CPN_BEFORE.accept(PVCSDC, MULTICURVES); AssertSensitivityObjects.assertEquals("CouponIborCompoundingSimpleSpreadDiscountingMethod: Present value curve sensitivity", pvcsMethod, pvcsCalculator, TOLERANCE_PV_DELTA); }