@Test
 /** Test the present value. */
 public void presentValueExplicit() {
   final MultipleCurrencyAmount pv = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES);
   final double timeToExpiry = SWAPTION_LONG_PAYER.getTimeToExpiry();
   final AnnuityPaymentFixed cfe =
       CFEC.visitSwap(SWAPTION_LONG_PAYER.getUnderlyingSwap(), MULTICURVES);
   final int numberOfPayments = cfe.getNumberOfPayments();
   final double alpha[] = new double[numberOfPayments];
   final double disccf[] = new double[numberOfPayments];
   for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) {
     alpha[loopcf] =
         MODEL.alpha(
             HW_PARAMETERS,
             0.0,
             timeToExpiry,
             timeToExpiry,
             cfe.getNthPayment(loopcf).getPaymentTime());
     disccf[loopcf] =
         MULTICURVES.getDiscountFactor(EUR, cfe.getNthPayment(loopcf).getPaymentTime())
             * cfe.getNthPayment(loopcf).getAmount();
   }
   final double kappa = MODEL.kappa(disccf, alpha);
   double pvExpected = 0.0;
   for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) {
     pvExpected += disccf[loopcf] * NORMAL.getCDF(-kappa - alpha[loopcf]);
   }
   assertEquals(
       "Swaption physical - Hull-White - present value", pvExpected, pv.getAmount(EUR), 1E-2);
   final MultipleCurrencyAmount pv2 =
       METHOD_HW.presentValue(SWAPTION_LONG_PAYER, cfe, HW_MULTICURVES);
   assertEquals("Swaption physical - Hull-White - present value", pv, pv2);
 }
 public void curveConstructionTest(
     final InstrumentDefinition<?>[][][] definitions,
     final MulticurveProviderDiscount curves,
     final boolean withToday,
     final int block) {
   final int nbBlocks = definitions.length;
   for (int loopblock = 0; loopblock < nbBlocks; loopblock++) {
     final InstrumentDerivative[][] instruments = convert(definitions[loopblock], withToday);
     final double[][] pv = new double[instruments.length][];
     for (int loopcurve = 0; loopcurve < instruments.length; loopcurve++) {
       pv[loopcurve] = new double[instruments[loopcurve].length];
       for (int loopins = 0; loopins < instruments[loopcurve].length; loopins++) {
         pv[loopcurve][loopins] =
             curves
                 .getFxRates()
                 .convert(instruments[loopcurve][loopins].accept(PVC, curves), AUD)
                 .getAmount();
         assertEquals(
             "Curve construction: block "
                 + block
                 + ", unit "
                 + loopblock
                 + " - instrument "
                 + loopins,
             0,
             pv[loopcurve][loopins],
             TOLERANCE_CAL);
       }
     }
   }
 }
 @Test(enabled = true)
 /**
  * Tests to estimate the impact of mu on the CMS coupon pricing. "enabled = false" for the
  * standard testing.
  */
 public void testPriceMultiMu() {
   final double[] mu = new double[] {1.10, 1.30, 1.55, 2.25, 3.50, 6.00, 15.0};
   final int nbMu = mu.length;
   final double priceCouponStd =
       METHOD_STANDARD_CPN.presentValue(CMS_COUPON, SABR_MULTICURVES).getAmount(EUR);
   @SuppressWarnings("unused")
   final double rateCouponStd =
       priceCouponStd
           / (CMS_COUPON.getPaymentYearFraction()
               * CMS_COUPON.getNotional()
               * MULTICURVES.getDiscountFactor(EUR, CMS_COUPON.getPaymentTime()));
   final double[] priceCouponExtra = new double[nbMu];
   final double[] rateCouponExtra = new double[nbMu];
   for (int loopmu = 0; loopmu < nbMu; loopmu++) {
     final CouponCMSSABRExtrapolationRightReplicationMethod methodExtrapolation =
         new CouponCMSSABRExtrapolationRightReplicationMethod(CUT_OFF_STRIKE, mu[loopmu]);
     priceCouponExtra[loopmu] =
         methodExtrapolation.presentValue(CMS_COUPON, SABR_MULTICURVES).getAmount(EUR);
     rateCouponExtra[loopmu] =
         priceCouponExtra[loopmu]
             / (CMS_COUPON.getPaymentYearFraction()
                 * CMS_COUPON.getNotional()
                 * MULTICURVES.getDiscountFactor(EUR, CMS_COUPON.getPaymentTime()));
   }
   final double priceCouponNoAdj =
       METHOD_DSC_CPN.presentValue(CMS_COUPON, MULTICURVES).getAmount(EUR);
   final double rateCouponNoAdj =
       priceCouponNoAdj
           / (CMS_COUPON.getPaymentYearFraction()
               * CMS_COUPON.getNotional()
               * MULTICURVES.getDiscountFactor(EUR, CMS_COUPON.getPaymentTime()));
   for (int loopmu = 1; loopmu < nbMu; loopmu++) {
     assertTrue(
         "Extrapolation: comparison with standard method",
         rateCouponExtra[loopmu - 1] > rateCouponExtra[loopmu]);
   }
   assertTrue(
       "Extrapolation: comparison with standard method",
       rateCouponExtra[nbMu - 1] > rateCouponNoAdj);
 }
 @Test
 public void presentValueMarketDiscount() {
   final MultipleCurrencyAmount pvComputed = METHOD_CPN_IBOR.presentValue(CPN_IBOR, MULTICURVES);
   final double forward =
       MULTICURVES.getForwardRate(
           EURIBOR3M,
           CPN_IBOR.getFixingPeriodStartTime(),
           CPN_IBOR.getFixingPeriodEndTime(),
           CPN_IBOR.getFixingAccrualFactor());
   final double df =
       MULTICURVES.getDiscountFactor(EURIBOR3M.getCurrency(), CPN_IBOR.getPaymentTime());
   final double pvExpected = NOTIONAL * ACCRUAL_FACTOR * forward * df;
   assertEquals(
       "CouponIborDiscountingMarketMethod: present value",
       pvExpected,
       pvComputed.getAmount(EURIBOR3M.getCurrency()),
       TOLERANCE_PV);
 }
 /**
  * Test the present value for a CMS coupon with pricing by replication in the SABR with
  * extrapolation framework. The present value is tested against hard-coded value and cap of strike
  * 0.
  */
 public void presentValue() {
   // CMS cap/floor with strike 0 has the same price as a CMS coupon.
   final double priceCouponStd =
       METHOD_STANDARD_CPN.presentValue(CMS_COUPON, SABR_MULTICURVES).getAmount(EUR).getAmount();
   final double rateCouponStd =
       priceCouponStd
           / (CMS_COUPON.getPaymentYearFraction()
               * CMS_COUPON.getNotional()
               * MULTICURVES.getDiscountFactor(EUR, CMS_COUPON.getPaymentTime()));
   final double priceCouponExtra =
       METHOD_EXTRAPOLATION_CPN
           .presentValue(CMS_COUPON, SABR_MULTICURVES)
           .getAmount(EUR)
           .getAmount();
   final double rateCouponExtra =
       priceCouponExtra
           / (CMS_COUPON.getPaymentYearFraction()
               * CMS_COUPON.getNotional()
               * MULTICURVES.getDiscountFactor(EUR, CMS_COUPON.getPaymentTime()));
   final double priceCouponNoAdj =
       METHOD_DSC_CPN.presentValue(CMS_COUPON, MULTICURVES).getAmount(EUR).getAmount();
   final double rateCouponNoAdj =
       priceCouponNoAdj
           / (CMS_COUPON.getPaymentYearFraction()
               * CMS_COUPON.getNotional()
               * MULTICURVES.getDiscountFactor(EUR, CMS_COUPON.getPaymentTime()));
   assertEquals(
       "Extrapolation: comparison with standard method", rateCouponStd > rateCouponExtra, true);
   assertEquals(
       "Extrapolation: comparison with no convexity adjustment",
       rateCouponExtra > rateCouponNoAdj,
       true);
   final double rateCouponExtraExpected = 0.0189864; // From previous run.
   assertEquals("Extrapolation: hard-coded value", rateCouponExtraExpected, rateCouponExtra, 1E-6);
   final double priceCap0Extra =
       METHOD_EXTRAPOLATION_CAP
           .presentValue(CMS_CAP_0, SABR_MULTICURVES)
           .getAmount(EUR)
           .getAmount();
   assertEquals(
       "Extrapolation: CMS coupon vs Cap 0", priceCouponExtra, priceCap0Extra, TOLERANCE_PV);
 }
 @Test
 /** Test the price curve sensitivity versus a finite difference computation. */
 public void priceCurveSensitivity() {
   final SimpleParameterSensitivity pcsExact =
       SPSHWC.calculateSensitivity(ERU2, HW_MULTICURVES, MULTICURVES.getAllNames());
   final SimpleParameterSensitivity pcsFD = SPSHWC_FD.calculateSensitivity(ERU2, HW_MULTICURVES);
   AssertSensitivityObjects.assertEquals(
       "DeliverableSwapFuturesSecurityHullWhiteMethod: priceCurveSensitivity",
       pcsExact,
       pcsFD,
       TOLERANCE_PRICE_DELTA);
 }
 @Test
 public void parSpreadMarketQuoteDiscountingCalculator() {
   final double psmq = SWAP_MULTI_LEG.accept(PSMQDC, MULTICURVES);
   final double pv =
       -MULTICURVES
           .getFxRates()
           .convert(
               SWAP_MULTI_LEG.accept(PVDC, MULTICURVES), SWAP_MULTI_LEG.getLegs()[0].getCurrency())
           .getAmount();
   final double pvbp = SWAP_MULTI_LEG.getLegs()[0].accept(PVMQSC, MULTICURVES);
   assertEquals(
       "SwapMultileg: parSpreadMarketQuoteDiscountingCalculator", psmq, pv / pvbp, TOLERANCE_RATE);
 }
 @Test
 public void parSpreadMarketQuoteCurveSensitivityDiscountingCalculator() {
   final double pv =
       MULTICURVES
           .getFxRates()
           .convert(
               SWAP_MULTI_LEG.accept(PVDC, MULTICURVES), SWAP_MULTI_LEG.getLegs()[0].getCurrency())
           .getAmount();
   final double pvbp = SWAP_MULTI_LEG.getLegs()[0].accept(PVMQSC, MULTICURVES);
   final MulticurveSensitivity pvcs =
       SWAP_MULTI_LEG
           .accept(PVCSDC, MULTICURVES)
           .converted(EUR, MULTICURVES.getFxRates())
           .getSensitivity(EUR);
   final MulticurveSensitivity pvbpcs = SWAP_MULTI_LEG.getLegs()[0].accept(PVMQSCSC, MULTICURVES);
   final MulticurveSensitivity psmqcsExpected =
       pvcs.multipliedBy(-1.0d / pvbp).plus(pvbpcs.multipliedBy(pv / (pvbp * pvbp))).cleaned();
   final MulticurveSensitivity psmqcs = SWAP_MULTI_LEG.accept(PSMQCSDC, MULTICURVES).cleaned();
   AssertSensitivityObjects.assertEquals(
       "SwapMultileg: presentValueCurveSensitivityDiscountingCalculator",
       psmqcs,
       psmqcsExpected,
       TOLERANCE_RATE_DELTA);
 }
 @Override
 protected void buildMessage(
     final FudgeSerializer serializer,
     final MutableFudgeMsg message,
     final MulticurveProviderDiscount object) {
   final Map<Currency, YieldAndDiscountCurve> discountingCurves = object.getDiscountingCurves();
   for (final Map.Entry<Currency, YieldAndDiscountCurve> entry : discountingCurves.entrySet()) {
     message.add(CURRENCY_FIELD, entry.getKey().getCode());
     serializer.addToMessageWithClassHeaders(
         message, DISCOUNTING_CURVE_FIELD, null, entry.getValue());
   }
   final Map<IborIndex, YieldAndDiscountCurve> forwardIborCurves = object.getForwardIborCurves();
   for (final Map.Entry<IborIndex, YieldAndDiscountCurve> entry : forwardIborCurves.entrySet()) {
     serializer.addToMessageWithClassHeaders(message, INDEX_IBOR_FIELD, null, entry.getKey());
     serializer.addToMessageWithClassHeaders(message, INDEX_IBOR_CURVE, null, entry.getValue());
   }
   final Map<IndexON, YieldAndDiscountCurve> forwardONCurves = object.getForwardONCurves();
   for (final Map.Entry<IndexON, YieldAndDiscountCurve> entry : forwardONCurves.entrySet()) {
     serializer.addToMessageWithClassHeaders(message, INDEX_ON_FIELD, null, entry.getKey());
     serializer.addToMessageWithClassHeaders(
         message, OVERNIGHT_CURVE_FIELD, null, entry.getValue());
   }
   serializer.addToMessageWithClassHeaders(message, FX_MATRIX_FIELD, null, object.getFxRates());
 }
 @Test
 /** Test the convexity adjustment */
 public void convexityAdjustment() {
   final double price = METHOD_IRFUT_HW.price(ERU2, HW_MULTICURVES);
   final double forward =
       MULTICURVES.getSimplyCompoundForwardRate(
           EURIBOR3M,
           ERU2.getFixingPeriodStartTime(),
           ERU2.getFixingPeriodEndTime(),
           ERU2.getFixingPeriodAccrualFactor());
   final double convexityAdjustment = METHOD_IRFUT_HW.convexityAdjustment(ERU2, HW_MULTICURVES);
   assertEquals(
       "InterestRateFutureSecurityHullWhiteProviderMethod: convexity adjustment",
       price - (1.0d - forward),
       convexityAdjustment,
       TOLERANCE_PRICE);
   final double caCalculator = ERU2.accept(CAHWC, HW_MULTICURVES);
   assertEquals(
       "DeliverableSwapFuturesSecurityDefinition: convexity adjustment",
       caCalculator,
       convexityAdjustment,
       TOLERANCE_PRICE);
 }
 @Test
 /** Test the price computed from the curves and HW parameters. */
 public void price() {
   final double price = METHOD_IRFUT_HW.price(ERU2, HW_MULTICURVES);
   final double forward =
       MULTICURVES.getSimplyCompoundForwardRate(
           EURIBOR3M,
           ERU2.getFixingPeriodStartTime(),
           ERU2.getFixingPeriodEndTime(),
           ERU2.getFixingPeriodAccrualFactor());
   final double factor =
       MODEL.futuresConvexityFactor(
           MODEL_PARAMETERS,
           ERU2.getTradingLastTime(),
           ERU2.getFixingPeriodStartTime(),
           ERU2.getFixingPeriodEndTime());
   final double expectedPrice =
       1.0 - factor * forward + (1 - factor) / ERU2.getFixingPeriodAccrualFactor();
   assertEquals(
       "InterestRateFutureSecurityHullWhiteProviderMethod: price",
       expectedPrice,
       price,
       TOLERANCE_PRICE);
 }
 @Test(enabled = false)
 /** Tests present value curve sensitivity when the valuation date is on trade date. */
 public void presentValueCurveSensitivityStability() {
   // 5Yx5Y
   final MultipleCurrencyParameterSensitivity pvpsExact =
       PS_HW_C.calculateSensitivity(
           SWAPTION_SHORT_RECEIVER,
           HW_MULTICURVES,
           HW_MULTICURVES.getMulticurveProvider().getAllNames());
   final double derivativeExact = pvpsExact.totalSensitivity(MULTICURVES.getFxRates(), EUR);
   final double startingShift = 1.0E-4;
   final double ratio = Math.sqrt(2.0);
   final int nbShift = 55;
   final double[] eps = new double[nbShift + 1];
   final double[] derivative_FD = new double[nbShift];
   final double[] diff = new double[nbShift];
   eps[0] = startingShift;
   for (int loopshift = 0; loopshift < nbShift; loopshift++) {
     final ParameterSensitivityHullWhiteDiscountInterpolatedFDCalculator fdShift =
         new ParameterSensitivityHullWhiteDiscountInterpolatedFDCalculator(PVHWC, eps[loopshift]);
     final MultipleCurrencyParameterSensitivity pvpsFD =
         fdShift.calculateSensitivity(SWAPTION_SHORT_RECEIVER, HW_MULTICURVES);
     derivative_FD[loopshift] = pvpsFD.totalSensitivity(MULTICURVES.getFxRates(), EUR);
     diff[loopshift] = derivative_FD[loopshift] - derivativeExact;
     eps[loopshift + 1] = eps[loopshift] / ratio;
   }
   // 1Mx5Y
   final Period expirationPeriod =
       Period.ofDays(
           1); // Period.ofDays(1); Period.ofDays(7); Period.ofMonths(1); Period.ofYears(1);
   // Period.ofYears(10);
   final ZonedDateTime expiryDateExp =
       ScheduleCalculator.getAdjustedDate(REFERENCE_DATE, expirationPeriod, EURIBOR6M, CALENDAR);
   final ZonedDateTime settlementDateExp =
       ScheduleCalculator.getAdjustedDate(expiryDateExp, SPOT_LAG, CALENDAR);
   final double ATM = 0.0151; //  1W: 1.52% - 1M: 1.52% - 1Y: 1.51% - 10Y: 1.51%
   final SwapFixedIborDefinition swapExpx5YDefinition =
       SwapFixedIborDefinition.from(
           settlementDateExp, SWAP_TENOR, EUR1YEURIBOR6M, NOTIONAL, ATM, !FIXED_IS_PAYER);
   final SwaptionPhysicalFixedIborDefinition swaptionExpx5YDefinition =
       SwaptionPhysicalFixedIborDefinition.from(EXPIRY_DATE, swapExpx5YDefinition, !IS_LONG);
   final SwaptionPhysicalFixedIbor swaptionExpx5Y =
       swaptionExpx5YDefinition.toDerivative(REFERENCE_DATE);
   //    final double forward = swaptionExpx5Y.getUnderlyingSwap().accept(PRDC, MULTICURVES);
   final MultipleCurrencyParameterSensitivity pvpsExactExp =
       PS_HW_C.calculateSensitivity(
           swaptionExpx5Y, HW_MULTICURVES, HW_MULTICURVES.getMulticurveProvider().getAllNames());
   final double derivativeExactExp = pvpsExactExp.totalSensitivity(MULTICURVES.getFxRates(), EUR);
   final double[] derivative_FDExp = new double[nbShift];
   final double[] diffExp = new double[nbShift];
   for (int loopshift = 0; loopshift < nbShift; loopshift++) {
     final ParameterSensitivityHullWhiteDiscountInterpolatedFDCalculator fdShift =
         new ParameterSensitivityHullWhiteDiscountInterpolatedFDCalculator(PVHWC, eps[loopshift]);
     final MultipleCurrencyParameterSensitivity pvpsFD =
         fdShift.calculateSensitivity(swaptionExpx5Y, HW_MULTICURVES);
     derivative_FDExp[loopshift] = pvpsFD.totalSensitivity(MULTICURVES.getFxRates(), EUR);
     diffExp[loopshift] = derivative_FDExp[loopshift] - derivativeExactExp;
   }
   //    int t = 0;
   //    t++;
 }