/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.impl.swap;
import static com.opengamma.strata.basics.currency.Currency.GBP;
import static com.opengamma.strata.basics.date.DayCounts.ACT_ACT_ISDA;
import static com.opengamma.strata.pricer.swap.SwapDummyData.NOTIONAL_EXCHANGE_REC_GBP;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Test;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.basics.date.DayCount;
import com.opengamma.strata.basics.date.DayCounts;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.market.curve.Curve;
import com.opengamma.strata.market.curve.Curves;
import com.opengamma.strata.market.curve.InterpolatedNodalCurve;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolator;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolators;
import com.opengamma.strata.market.explain.ExplainKey;
import com.opengamma.strata.market.explain.ExplainMap;
import com.opengamma.strata.market.explain.ExplainMapBuilder;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
import com.opengamma.strata.pricer.DiscountFactors;
import com.opengamma.strata.pricer.ZeroRateSensitivity;
import com.opengamma.strata.pricer.rate.ImmutableRatesProvider;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.pricer.rate.SimpleRatesProvider;
import com.opengamma.strata.product.swap.NotionalExchange;
/**
* Test.
*/
@Test
public class DiscountingNotionalExchangePricerTest {
private static final LocalDate VAL_DATE = NOTIONAL_EXCHANGE_REC_GBP.getPaymentDate().minusDays(90);
private static final DayCount DAY_COUNT = DayCounts.ACT_360;
private static final double DISCOUNT_FACTOR = 0.98d;
private static final double TOLERANCE = 1.0e-10;
private static final CurveInterpolator INTERPOLATOR = CurveInterpolators.DOUBLE_QUADRATIC;
private static final Curve DISCOUNT_CURVE_GBP;
static {
DoubleArray time_gbp = DoubleArray.of(0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0);
DoubleArray rate_gbp = DoubleArray.of(0.0160, 0.0135, 0.0160, 0.0185, 0.0185, 0.0195, 0.0200, 0.0210);
DISCOUNT_CURVE_GBP = InterpolatedNodalCurve.of(
Curves.zeroRates("GBP-Discount", ACT_ACT_ISDA), time_gbp, rate_gbp, INTERPOLATOR);
}
//-------------------------------------------------------------------------
public void test_presentValue() {
SimpleRatesProvider prov = createProvider(NOTIONAL_EXCHANGE_REC_GBP);
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
double calculated = test.presentValue(NOTIONAL_EXCHANGE_REC_GBP, prov);
assertEquals(calculated, NOTIONAL_EXCHANGE_REC_GBP.getPaymentAmount().getAmount() * DISCOUNT_FACTOR, 0d);
}
public void test_forecastValue() {
SimpleRatesProvider prov = createProvider(NOTIONAL_EXCHANGE_REC_GBP);
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
double calculated = test.forecastValue(NOTIONAL_EXCHANGE_REC_GBP, prov);
assertEquals(calculated, NOTIONAL_EXCHANGE_REC_GBP.getPaymentAmount().getAmount(), 0d);
}
//-------------------------------------------------------------------------
public void test_presentValueSensitivity() {
SimpleRatesProvider prov = createProvider(NOTIONAL_EXCHANGE_REC_GBP);
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
PointSensitivities senseComputed = test.presentValueSensitivity(NOTIONAL_EXCHANGE_REC_GBP, prov).build();
double eps = 1.0e-7;
PointSensitivities senseExpected = PointSensitivities.of(dscSensitivityFD(prov, NOTIONAL_EXCHANGE_REC_GBP, eps));
assertTrue(senseComputed.equalWithTolerance(
senseExpected, NOTIONAL_EXCHANGE_REC_GBP.getPaymentAmount().getAmount() * eps));
}
public void test_forecastValueSensitivity() {
SimpleRatesProvider prov = createProvider(NOTIONAL_EXCHANGE_REC_GBP);
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
PointSensitivities senseComputed = test.forecastValueSensitivity(NOTIONAL_EXCHANGE_REC_GBP, prov).build();
double eps = 1.0e-12;
PointSensitivities senseExpected = PointSensitivities.empty();
assertTrue(senseComputed.equalWithTolerance(
senseExpected, NOTIONAL_EXCHANGE_REC_GBP.getPaymentAmount().getAmount() * eps));
}
private List<ZeroRateSensitivity> dscSensitivityFD(RatesProvider provider, NotionalExchange event, double eps) {
Currency currency = event.getCurrency();
LocalDate paymentDate = event.getPaymentDate();
double discountFactor = provider.discountFactor(currency, paymentDate);
double paymentTime = DAY_COUNT.relativeYearFraction(VAL_DATE, paymentDate);
RatesProvider provUp = mock(RatesProvider.class);
RatesProvider provDw = mock(RatesProvider.class);
when(provUp.getValuationDate()).thenReturn(VAL_DATE);
when(provUp.discountFactor(currency, paymentDate)).thenReturn(discountFactor * Math.exp(-eps * paymentTime));
when(provDw.getValuationDate()).thenReturn(VAL_DATE);
when(provDw.discountFactor(currency, paymentDate)).thenReturn(discountFactor * Math.exp(eps * paymentTime));
DiscountingNotionalExchangePricer pricer = DiscountingNotionalExchangePricer.DEFAULT;
double pvUp = pricer.presentValue(event, provUp);
double pvDw = pricer.presentValue(event, provDw);
double res = 0.5 * (pvUp - pvDw) / eps;
List<ZeroRateSensitivity> zeroRateSensi = new ArrayList<>();
zeroRateSensi.add(ZeroRateSensitivity.of(currency, paymentTime, res));
return zeroRateSensi;
}
//-------------------------------------------------------------------------
public void test_explainPresentValue() {
SimpleRatesProvider prov = createProvider(NOTIONAL_EXCHANGE_REC_GBP);
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
ExplainMapBuilder builder = ExplainMap.builder();
test.explainPresentValue(NOTIONAL_EXCHANGE_REC_GBP, prov, builder);
ExplainMap explain = builder.build();
Currency currency = NOTIONAL_EXCHANGE_REC_GBP.getCurrency();
CurrencyAmount notional = NOTIONAL_EXCHANGE_REC_GBP.getPaymentAmount();
assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "NotionalExchange");
assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), NOTIONAL_EXCHANGE_REC_GBP.getPaymentDate());
assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), currency);
assertEquals(explain.get(ExplainKey.TRADE_NOTIONAL).get().getCurrency(), currency);
assertEquals(explain.get(ExplainKey.TRADE_NOTIONAL).get().getAmount(), notional.getAmount(), TOLERANCE);
assertEquals(explain.get(ExplainKey.DISCOUNT_FACTOR).get(), DISCOUNT_FACTOR, TOLERANCE);
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), currency);
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), notional.getAmount(), TOLERANCE);
assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getCurrency(), currency);
assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), notional.getAmount() * DISCOUNT_FACTOR, TOLERANCE);
}
public void test_explainPresentValue_paymentDateInPast() {
SimpleRatesProvider prov = createProvider(NOTIONAL_EXCHANGE_REC_GBP);
prov.setValuationDate(VAL_DATE.plusYears(1));
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
ExplainMapBuilder builder = ExplainMap.builder();
test.explainPresentValue(NOTIONAL_EXCHANGE_REC_GBP, prov, builder);
ExplainMap explain = builder.build();
Currency currency = NOTIONAL_EXCHANGE_REC_GBP.getCurrency();
CurrencyAmount notional = NOTIONAL_EXCHANGE_REC_GBP.getPaymentAmount();
assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "NotionalExchange");
assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), NOTIONAL_EXCHANGE_REC_GBP.getPaymentDate());
assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), currency);
assertEquals(explain.get(ExplainKey.TRADE_NOTIONAL).get().getCurrency(), currency);
assertEquals(explain.get(ExplainKey.TRADE_NOTIONAL).get().getAmount(), notional.getAmount(), TOLERANCE);
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), currency);
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), 0d, TOLERANCE);
assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getCurrency(), currency);
assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), 0d * DISCOUNT_FACTOR, TOLERANCE);
}
//-------------------------------------------------------------------------
public void test_currencyExposure() {
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE)
.discountCurve(GBP, DISCOUNT_CURVE_GBP)
.build();
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
MultiCurrencyAmount computed = test.currencyExposure(NOTIONAL_EXCHANGE_REC_GBP, prov);
PointSensitivities point = test.presentValueSensitivity(NOTIONAL_EXCHANGE_REC_GBP, prov).build();
MultiCurrencyAmount expected = prov.currencyExposure(point).plus(
CurrencyAmount.of(NOTIONAL_EXCHANGE_REC_GBP.getCurrency(), test.presentValue(NOTIONAL_EXCHANGE_REC_GBP, prov)));
assertEquals(computed, expected);
}
public void test_currentCash_zero() {
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE)
.discountCurve(GBP, DISCOUNT_CURVE_GBP)
.build();
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
double computed = test.currentCash(NOTIONAL_EXCHANGE_REC_GBP, prov);
assertEquals(computed, 0d);
}
public void test_currentCash_onPayment() {
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(NOTIONAL_EXCHANGE_REC_GBP.getPaymentDate())
.discountCurve(GBP, DISCOUNT_CURVE_GBP)
.build();
DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT;
double notional = NOTIONAL_EXCHANGE_REC_GBP.getPaymentAmount().getAmount();
double computed = test.currentCash(NOTIONAL_EXCHANGE_REC_GBP, prov);
assertEquals(computed, notional);
}
//-------------------------------------------------------------------------
// creates a simple provider
private SimpleRatesProvider createProvider(NotionalExchange ne) {
LocalDate paymentDate = ne.getPaymentDate();
double paymentTime = DAY_COUNT.relativeYearFraction(VAL_DATE, paymentDate);
Currency currency = ne.getCurrency();
DiscountFactors mockDf = mock(DiscountFactors.class);
when(mockDf.discountFactor(paymentDate)).thenReturn(DISCOUNT_FACTOR);
ZeroRateSensitivity sens = ZeroRateSensitivity.of(currency, paymentTime, -DISCOUNT_FACTOR * paymentTime);
when(mockDf.zeroRatePointSensitivity(paymentDate)).thenReturn(sens);
SimpleRatesProvider prov = new SimpleRatesProvider(VAL_DATE, mockDf);
prov.setDayCount(DAY_COUNT);
return prov;
}
}