### Question:
DiscountingFxNdfProductPricer { public CurrencyAmount presentValue(ResolvedFxNdf ndf, RatesProvider provider) { Currency ccySettle = ndf.getSettlementCurrency(); if (provider.getValuationDate().isAfter(ndf.getPaymentDate())) { return CurrencyAmount.zero(ccySettle); } Currency ccyOther = ndf.getNonDeliverableCurrency(); CurrencyAmount notionalSettle = ndf.getSettlementCurrencyNotional(); double agreedRate = ndf.getAgreedFxRate().fxRate(ccySettle, ccyOther); double forwardRate = provider.fxIndexRates(ndf.getIndex()).rate(ndf.getObservation(), ccySettle); double dfSettle = provider.discountFactor(ccySettle, ndf.getPaymentDate()); return notionalSettle.multipliedBy(dfSettle * (1d - agreedRate / forwardRate)); } DiscountingFxNdfProductPricer(); CurrencyAmount presentValue(ResolvedFxNdf ndf, RatesProvider provider); PointSensitivities presentValueSensitivity(ResolvedFxNdf ndf, RatesProvider provider); MultiCurrencyAmount currencyExposure(ResolvedFxNdf ndf, RatesProvider provider); CurrencyAmount currentCash(ResolvedFxNdf ndf, RatesProvider provider); FxRate forwardFxRate(ResolvedFxNdf ndf, RatesProvider provider); static final DiscountingFxNdfProductPricer DEFAULT; }### Answer:
@Test public void test_presentValue() { CurrencyAmount computed = PRICER.presentValue(NDF, PROVIDER); double dscUsd = PROVIDER.discountFactor(USD, NDF.getPaymentDate()); double dscKrw = PROVIDER.discountFactor(KRW, NDF.getPaymentDate()); double expected = NOMINAL_USD * (dscUsd - dscKrw * FX_RATE / PROVIDER.fxRate(CurrencyPair.of(USD, KRW))); assertThat(computed.getCurrency()).isEqualTo(USD); assertThat(computed.getAmount()).isCloseTo(expected, offset(NOMINAL_USD * TOL)); }
@Test public void test_presentValue_inverse() { CurrencyAmount computed = PRICER.presentValue(NDF_INVERSE, PROVIDER); double dscUsd = PROVIDER.discountFactor(USD, NDF_INVERSE.getPaymentDate()); double dscKrw = PROVIDER.discountFactor(KRW, NDF_INVERSE.getPaymentDate()); double expected = NOMINAL_USD * FX_RATE * (dscKrw - dscUsd * 1 / FX_RATE / PROVIDER.fxRate(CurrencyPair.of(KRW, USD))); assertThat(computed.getCurrency()).isEqualTo(KRW); assertThat(computed.getAmount()).isCloseTo(expected, offset(NOMINAL_USD * FX_RATE * TOL)); }
@Test public void test_presentValue_ended() { ResolvedFxNdf ndf = ResolvedFxNdf.builder() .settlementCurrencyNotional(CURRENCY_NOTIONAL) .agreedFxRate(FxRate.of(USD, KRW, FX_RATE)) .observation(FxIndexObservation.of(INDEX, FIXING_DATE_PAST, REF_DATA)) .paymentDate(PAYMENT_DATE_PAST) .build(); CurrencyAmount computed = PRICER.presentValue(ndf, PROVIDER); assertThat(computed.getAmount()).isEqualTo(0d); }
@Test public void test_presentValueVsForex() { CurrencyAmount pvNDF = PRICER.presentValue(NDF, PROVIDER); MultiCurrencyAmount pvFX = PRICER_FX.presentValue(FOREX, PROVIDER); assertThat(pvNDF.getAmount()).isCloseTo(pvFX.getAmount(USD).getAmount() + pvFX.getAmount(KRW).getAmount() * FX_MATRIX.fxRate(KRW, USD), offset(NOMINAL_USD * TOL)); }