@Test
 /** Tests the present value: Method vs Calculator. */
 public void presentValueMethodVsCalculator() {
   final MultipleCurrencyAmount pvMethod = METHOD.presentValue(ZERO_COUPON_CAP, BLACK_INFLATION);
   final MultipleCurrencyAmount pvCalculator = ZERO_COUPON_CAP.accept(PVIC, BLACK_INFLATION);
   assertEquals("Zero-coupon inflation DiscountingMethod: Present value", pvMethod, pvCalculator);
 }
 @Test
 /** Tests the present value. */
 public void presentValueNoNotional() {
   final MultipleCurrencyAmount pv = METHOD.presentValue(ZERO_COUPON_CAP, BLACK_INFLATION);
   final double timeToMaturity =
       ZERO_COUPON_CAP.getReferenceEndTime() - ZERO_COUPON_CAP.getLastKnownFixingTime();
   final double df =
       MARKET
           .getCurve(ZERO_COUPON_CAP.getCurrency())
           .getDiscountFactor(ZERO_COUPON_CAP.getPaymentTime());
   final double finalIndex =
       MARKET.getCurve(PRICE_INDEX_EUR).getPriceIndex(ZERO_COUPON_CAP.getReferenceEndTime());
   final double forward = finalIndex / INDEX_1MAY_2008;
   final EuropeanVanillaOption option =
       new EuropeanVanillaOption(
           Math.pow(1 + ZERO_COUPON_CAP.getStrike(), ZERO_COUPON_CAP.getMaturity()),
           timeToMaturity,
           ZERO_COUPON_CAP.isCap());
   final double volatility =
       BLACK_INFLATION
           .getBlackParameters()
           .getVolatility(ZERO_COUPON_CAP.getReferenceEndTime(), ZERO_COUPON_CAP.getStrike());
   final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatility);
   final Function1D<BlackFunctionData, Double> func = BLACK_FUNCTION.getPriceFunction(option);
   final double pvExpected =
       df
           * func.evaluate(dataBlack)
           * ZERO_COUPON_CAP.getNotional()
           * ZERO_COUPON_CAP.getPaymentYearFraction();
   assertEquals(
       "Zero-coupon inflation DiscountingMethod: Present value",
       pvExpected,
       pv.getAmount(ZERO_COUPON_CAP.getCurrency()),
       TOLERANCE_PV);
 }
 @Test
 public void presentValueMarketSensitivityMethodVsCalculator() {
   final MultipleCurrencyInflationSensitivity pvcisMethod =
       METHOD.presentValueCurveSensitivity(ZERO_COUPON_CAP, BLACK_INFLATION);
   final MultipleCurrencyInflationSensitivity pvcisCalculator =
       ZERO_COUPON_CAP.accept(PVCSDC, BLACK_INFLATION);
   AssertSensivityObjects.assertEquals(
       "Zero-coupon inflation DiscountingMethod: presentValueMarketSensitivity",
       pvcisMethod,
       pvcisCalculator,
       TOLERANCE_PV_DELTA);
 }
/**
 * Tests the present value and its sensitivities for zero-coupon cap/floor with reference index on
 * the first of the month.
 */
public class CapFloorInflationZeroCouponMonthlyBlackSmileMethodTest {
  private static final InflationIssuerProviderDiscount MARKET =
      MulticurveProviderDiscountDataSets.createMarket1();
  private static final IndexPrice[] PRICE_INDEXES =
      MARKET.getPriceIndexes().toArray(new IndexPrice[MARKET.getPriceIndexes().size()]);
  private static final IndexPrice PRICE_INDEX_EUR = PRICE_INDEXES[0];
  private static final Calendar CALENDAR_EUR = MulticurveProviderDiscountDataSets.getEURCalendar();
  private static final BusinessDayConvention BUSINESS_DAY =
      BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention("Modified Following");
  private static final ZonedDateTime START_DATE = DateUtils.getUTCDate(2008, 8, 18);
  private static final int MATURITY = 10;
  private static final Period COUPON_TENOR = Period.ofYears(MATURITY);
  private static final ZonedDateTime PAYMENT_DATE =
      ScheduleCalculator.getAdjustedDate(START_DATE, COUPON_TENOR, BUSINESS_DAY, CALENDAR_EUR);
  private static final double NOTIONAL = 98765432;
  private static final int MONTH_LAG = 3;
  private static final double INDEX_1MAY_2008 =
      108.23; // 3 m before Aug: May / 1 May index = May index: 108.23

  private static final double STRIKE = .02;
  private static final boolean IS_CAP = true;
  private static final ZonedDateTime LAST_KNOWN_FIXING_DATE = DateUtils.getUTCDate(2008, 7, 01);

  private static final double SHIFT_FD = 1.0E-7;
  private static final double TOLERANCE_PV = 1.0E-2;
  private static final double TOLERANCE_PV_DELTA = 1.0E+2;

  private static final InterpolatedDoublesSurface BLACK_SURF =
      TestsDataSetsBlack.createBlackSurfaceExpiryStrike();
  private static final BlackSmileCapInflationZeroCouponParameters BLACK_PARAM =
      new BlackSmileCapInflationZeroCouponParameters(BLACK_SURF, PRICE_INDEX_EUR);
  private static final BlackSmileCapInflationZeroCouponProviderDiscount BLACK_INFLATION =
      new BlackSmileCapInflationZeroCouponProviderDiscount(
          MARKET.getInflationProvider(), BLACK_PARAM);

  private static final ZonedDateTime PRICING_DATE = DateUtils.getUTCDate(2011, 8, 3);
  private static final CouponInflationZeroCouponMonthlyDefinition ZERO_COUPON_DEFINITION =
      CouponInflationZeroCouponMonthlyDefinition.from(
          START_DATE,
          PAYMENT_DATE,
          NOTIONAL,
          PRICE_INDEX_EUR,
          INDEX_1MAY_2008,
          MONTH_LAG,
          MONTH_LAG,
          false);
  private static final CapFloorInflationZeroCouponMonthlyDefinition ZERO_COUPON_DEFINITION_CAP =
      CapFloorInflationZeroCouponMonthlyDefinition.from(
          ZERO_COUPON_DEFINITION, LAST_KNOWN_FIXING_DATE, MATURITY, STRIKE, IS_CAP);
  private static final CapFloorInflationZeroCouponMonthly ZERO_COUPON_CAP =
      ZERO_COUPON_DEFINITION_CAP.toDerivative(PRICING_DATE, "not used");

  private static final CapFloorInflationZeroCouponMonthlyBlackSmileMethod METHOD =
      CapFloorInflationZeroCouponMonthlyBlackSmileMethod.getInstance();
  private static final PresentValueBlackSmileInflationZeroCouponCalculator PVIC =
      PresentValueBlackSmileInflationZeroCouponCalculator.getInstance();
  private static final PresentValueCurveSensitivityBlackSmileInflationZeroCouponCalculator PVCSDC =
      PresentValueCurveSensitivityBlackSmileInflationZeroCouponCalculator.getInstance();
  private static final ParameterInflationSensitivityParameterCalculator<
          BlackSmileCapInflationZeroCouponProviderInterface>
      PSC = new ParameterInflationSensitivityParameterCalculator<>(PVCSDC);
  private static final ParameterSensitivityBlackSmileZeroCouponCapDiscountInterpolatedFDCalculator
      PS_PV_FDC =
          new ParameterSensitivityBlackSmileZeroCouponCapDiscountInterpolatedFDCalculator(
              PVIC, SHIFT_FD);

  /** The Black function used in the pricing. */
  private static final BlackPriceFunction BLACK_FUNCTION = new BlackPriceFunction();

  @Test
  /** Tests the present value. */
  public void presentValueNoNotional() {
    final MultipleCurrencyAmount pv = METHOD.presentValue(ZERO_COUPON_CAP, BLACK_INFLATION);
    final double timeToMaturity =
        ZERO_COUPON_CAP.getReferenceEndTime() - ZERO_COUPON_CAP.getLastKnownFixingTime();
    final double df =
        MARKET
            .getCurve(ZERO_COUPON_CAP.getCurrency())
            .getDiscountFactor(ZERO_COUPON_CAP.getPaymentTime());
    final double finalIndex =
        MARKET.getCurve(PRICE_INDEX_EUR).getPriceIndex(ZERO_COUPON_CAP.getReferenceEndTime());
    final double forward = finalIndex / INDEX_1MAY_2008;
    final EuropeanVanillaOption option =
        new EuropeanVanillaOption(
            Math.pow(1 + ZERO_COUPON_CAP.getStrike(), ZERO_COUPON_CAP.getMaturity()),
            timeToMaturity,
            ZERO_COUPON_CAP.isCap());
    final double volatility =
        BLACK_INFLATION
            .getBlackParameters()
            .getVolatility(ZERO_COUPON_CAP.getReferenceEndTime(), ZERO_COUPON_CAP.getStrike());
    final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatility);
    final Function1D<BlackFunctionData, Double> func = BLACK_FUNCTION.getPriceFunction(option);
    final double pvExpected =
        df
            * func.evaluate(dataBlack)
            * ZERO_COUPON_CAP.getNotional()
            * ZERO_COUPON_CAP.getPaymentYearFraction();
    assertEquals(
        "Zero-coupon inflation DiscountingMethod: Present value",
        pvExpected,
        pv.getAmount(ZERO_COUPON_CAP.getCurrency()),
        TOLERANCE_PV);
  }

  @Test
  /** Tests the present value: Method vs Calculator. */
  public void presentValueMethodVsCalculator() {
    final MultipleCurrencyAmount pvMethod = METHOD.presentValue(ZERO_COUPON_CAP, BLACK_INFLATION);
    final MultipleCurrencyAmount pvCalculator = ZERO_COUPON_CAP.accept(PVIC, BLACK_INFLATION);
    assertEquals("Zero-coupon inflation DiscountingMethod: Present value", pvMethod, pvCalculator);
  }

  @Test
  /** Test the present value curves sensitivity. */
  public void presentValueCurveSensitivity() {

    final MultipleCurrencyParameterSensitivity pvicsFD =
        PS_PV_FDC.calculateSensitivity(ZERO_COUPON_CAP, BLACK_INFLATION);
    final MultipleCurrencyParameterSensitivity pvicsExact =
        PSC.calculateSensitivity(ZERO_COUPON_CAP, BLACK_INFLATION, MARKET.getAllNames());

    AssertSensivityObjects.assertEquals(
        "Zero-coupon inflation DiscountingMethod: presentValueCurveSensitivity ",
        pvicsExact,
        pvicsFD,
        TOLERANCE_PV_DELTA);
  }

  @Test
  public void presentValueMarketSensitivityMethodVsCalculator() {
    final MultipleCurrencyInflationSensitivity pvcisMethod =
        METHOD.presentValueCurveSensitivity(ZERO_COUPON_CAP, BLACK_INFLATION);
    final MultipleCurrencyInflationSensitivity pvcisCalculator =
        ZERO_COUPON_CAP.accept(PVCSDC, BLACK_INFLATION);
    AssertSensivityObjects.assertEquals(
        "Zero-coupon inflation DiscountingMethod: presentValueMarketSensitivity",
        pvcisMethod,
        pvcisCalculator,
        TOLERANCE_PV_DELTA);
  }
}