/**
   * Test for the case where publication lag=1, effective offset=0 (USD conventions) and no cutoff
   * period.
   */
  public void rateFedFundNoCutOff() {
    OvernightIndexRates mockRates = mock(OvernightIndexRates.class);
    when(mockRates.getIndex()).thenReturn(USD_FED_FUND);
    SimpleRatesProvider simpleProv = new SimpleRatesProvider(mockRates);

    for (int i = 0; i < FIXING_DATES.length; i++) {
      when(mockRates.rate(FIXING_DATES[i])).thenReturn(FIXING_RATES[i]);
    }
    OvernightAveragedRateObservation ro =
        OvernightAveragedRateObservation.of(USD_FED_FUND, FIXING_START_DATE, FIXING_END_DATE, 0);
    // Accrual dates = fixing dates
    ForwardOvernightAveragedRateObservationFn obsFn =
        ForwardOvernightAveragedRateObservationFn.DEFAULT;
    double accrualFactorTotal = 0.0d;
    double accruedRate = 0.0d;
    int indexLast = 5; // Fixing in the observation period are from 1 to 5 (inclusive)
    for (int i = 1; i <= indexLast; i++) {
      LocalDate endDate = USD_FED_FUND.calculateMaturityFromEffective(FIXING_DATES[i]);
      double af = USD_FED_FUND.getDayCount().yearFraction(FIXING_DATES[i], endDate);
      accrualFactorTotal += af;
      accruedRate += FIXING_RATES[i] * af;
    }
    double rateExpected = accruedRate / accrualFactorTotal;
    double rateComputed =
        obsFn.rate(ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, simpleProv);
    assertEquals(rateExpected, rateComputed, TOLERANCE_RATE);

    // explain
    ExplainMapBuilder builder = ExplainMap.builder();
    double explainedRate =
        obsFn.explainRate(
            ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, simpleProv, builder);
    assertEquals(explainedRate, rateExpected, TOLERANCE_RATE);

    ExplainMap built = builder.build();
    assertEquals(built.get(ExplainKey.OBSERVATIONS).isPresent(), false);
    assertEquals(
        built.get(ExplainKey.COMBINED_RATE).get().doubleValue(), rateExpected, TOLERANCE_RATE);
  }
  /** Test explain. */
  public void test_explainPresentValue_ISDA() {
    ExpandedFra fraExp = FRA.expand();
    SimpleRatesProvider prov = createProvider(fraExp);

    DiscountingFraProductPricer test = DiscountingFraProductPricer.DEFAULT;
    CurrencyAmount fvExpected = test.forecastValue(fraExp, prov);
    CurrencyAmount pvExpected = test.presentValue(fraExp, prov);

    ExplainMap explain = test.explainPresentValue(fraExp, prov);
    Currency currency = fraExp.getCurrency();
    int daysBetween = (int) DAYS.between(fraExp.getStartDate(), fraExp.getEndDate());
    assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "FRA");
    assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), fraExp.getPaymentDate());
    assertEquals(explain.get(ExplainKey.START_DATE).get(), fraExp.getStartDate());
    assertEquals(explain.get(ExplainKey.END_DATE).get(), fraExp.getEndDate());
    assertEquals(explain.get(ExplainKey.ACCRUAL_YEAR_FRACTION).get(), fraExp.getYearFraction());
    assertEquals(explain.get(ExplainKey.ACCRUAL_DAYS).get(), (Integer) (int) daysBetween);
    assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), currency);
    assertEquals(
        explain.get(ExplainKey.NOTIONAL).get().getAmount(), fraExp.getNotional(), TOLERANCE);
    assertEquals(
        explain.get(ExplainKey.TRADE_NOTIONAL).get().getAmount(), fraExp.getNotional(), TOLERANCE);

    assertEquals(explain.get(ExplainKey.OBSERVATIONS).get().size(), 1);
    ExplainMap explainObs = explain.get(ExplainKey.OBSERVATIONS).get().get(0);
    IborRateObservation floatingRate = (IborRateObservation) fraExp.getFloatingRate();
    assertEquals(explainObs.get(ExplainKey.INDEX).get(), floatingRate.getIndex());
    assertEquals(explainObs.get(ExplainKey.FIXING_DATE).get(), floatingRate.getFixingDate());
    assertEquals(explainObs.get(ExplainKey.INDEX_VALUE).get(), FORWARD_RATE, TOLERANCE);
    assertEquals(explain.get(ExplainKey.DISCOUNT_FACTOR).get(), DISCOUNT_FACTOR, TOLERANCE);
    assertEquals(explain.get(ExplainKey.FIXED_RATE).get(), fraExp.getFixedRate(), TOLERANCE);
    assertEquals(explain.get(ExplainKey.PAY_OFF_RATE).get(), FORWARD_RATE, TOLERANCE);
    assertEquals(explain.get(ExplainKey.COMBINED_RATE).get(), FORWARD_RATE, TOLERANCE);
    assertEquals(
        explain.get(ExplainKey.UNIT_AMOUNT).get(),
        fvExpected.getAmount() / fraExp.getNotional(),
        TOLERANCE);
    assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), currency);
    assertEquals(
        explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(),
        fvExpected.getAmount(),
        TOLERANCE);
    assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getCurrency(), currency);
    assertEquals(
        explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), pvExpected.getAmount(), TOLERANCE);
  }