/** * Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.measure.rate; import static com.opengamma.strata.basics.currency.Currency.EUR; import static com.opengamma.strata.basics.currency.Currency.GBP; import static com.opengamma.strata.basics.currency.Currency.USD; import static com.opengamma.strata.basics.date.DayCounts.ACT_360; import static com.opengamma.strata.basics.index.IborIndices.GBP_LIBOR_3M; import static com.opengamma.strata.basics.index.IborIndices.USD_LIBOR_3M; import static com.opengamma.strata.basics.index.OvernightIndices.GBP_SONIA; import static com.opengamma.strata.basics.index.OvernightIndices.USD_FED_FUND; import static com.opengamma.strata.basics.index.PriceIndices.US_CPI_U; import static com.opengamma.strata.collect.TestHelper.assertSerialization; import static com.opengamma.strata.collect.TestHelper.assertThrows; import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg; import static com.opengamma.strata.collect.TestHelper.coverBeanEquals; import static com.opengamma.strata.collect.TestHelper.coverImmutableBean; import static com.opengamma.strata.collect.TestHelper.date; import static org.mockito.Mockito.mock; import static org.testng.Assert.assertEquals; import java.time.LocalDate; import java.util.Map; import java.util.Optional; import org.joda.beans.ImmutableBean; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.opengamma.strata.basics.currency.Currency; import com.opengamma.strata.basics.currency.FxRate; import com.opengamma.strata.basics.currency.FxRateProvider; import com.opengamma.strata.basics.index.Index; import com.opengamma.strata.calc.runner.FunctionRequirements; import com.opengamma.strata.data.FxRateId; import com.opengamma.strata.data.ImmutableMarketData; import com.opengamma.strata.data.MarketData; import com.opengamma.strata.data.MarketDataFxRateProvider; import com.opengamma.strata.data.MarketDataId; import com.opengamma.strata.data.MarketDataNotFoundException; import com.opengamma.strata.data.ObservableSource; import com.opengamma.strata.data.scenario.ScenarioMarketData; import com.opengamma.strata.market.curve.ConstantCurve; import com.opengamma.strata.market.curve.Curve; import com.opengamma.strata.market.curve.CurveGroup; import com.opengamma.strata.market.curve.CurveId; import com.opengamma.strata.market.curve.CurveName; import com.opengamma.strata.market.curve.Curves; import com.opengamma.strata.market.observable.IndexQuoteId; import com.opengamma.strata.measure.curve.TestMarketDataMap; import com.opengamma.strata.pricer.SimpleDiscountFactors; import com.opengamma.strata.pricer.rate.DiscountIborIndexRates; import com.opengamma.strata.pricer.rate.DiscountOvernightIndexRates; import com.opengamma.strata.pricer.rate.ImmutableRatesProvider; import com.opengamma.strata.pricer.rate.RatesProvider; /** * Test {@link RatesMarketDataLookup}. */ @Test public class RatesMarketDataLookupTest { private static final CurveId CURVE_ID_DSC = CurveId.of("Group", "USD-DSC"); private static final CurveId CURVE_ID_FWD = CurveId.of("Group", "USD-L3M"); private static final ObservableSource OBS_SOURCE = ObservableSource.of("Vendor"); private static final MarketData MOCK_MARKET_DATA = mock(MarketData.class); private static final ScenarioMarketData MOCK_CALC_MARKET_DATA = mock(ScenarioMarketData.class); //------------------------------------------------------------------------- public void test_of_map() { ImmutableMap<Currency, CurveId> discounts = ImmutableMap.of(USD, CURVE_ID_DSC); ImmutableMap<Index, CurveId> forwards = ImmutableMap.of(USD_LIBOR_3M, CURVE_ID_FWD); RatesMarketDataLookup test = RatesMarketDataLookup.of(discounts, forwards); assertEquals(test.queryType(), RatesMarketDataLookup.class); assertEquals(test.getDiscountCurrencies(), ImmutableSet.of(USD)); assertEquals(test.getDiscountMarketDataIds(USD), ImmutableSet.of(CURVE_ID_DSC)); assertEquals(test.getForwardIndices(), ImmutableSet.of(USD_LIBOR_3M)); assertEquals(test.getForwardMarketDataIds(USD_LIBOR_3M), ImmutableSet.of(CURVE_ID_FWD)); assertThrowsIllegalArg(() -> test.getDiscountMarketDataIds(GBP)); assertThrowsIllegalArg(() -> test.getForwardMarketDataIds(GBP_LIBOR_3M)); assertEquals( test.requirements(USD), FunctionRequirements.builder().valueRequirements(CURVE_ID_DSC).outputCurrencies(USD).build()); assertEquals( test.requirements(USD, USD_LIBOR_3M), FunctionRequirements.builder() .valueRequirements(CURVE_ID_DSC, CURVE_ID_FWD) .timeSeriesRequirements(IndexQuoteId.of(USD_LIBOR_3M)) .outputCurrencies(USD) .build()); assertEquals( test.requirements(ImmutableSet.of(USD), ImmutableSet.of(USD_LIBOR_3M)), FunctionRequirements.builder() .valueRequirements(CURVE_ID_DSC, CURVE_ID_FWD) .timeSeriesRequirements(IndexQuoteId.of(USD_LIBOR_3M)) .outputCurrencies(USD) .build()); assertThrowsIllegalArg(() -> test.requirements(ImmutableSet.of(USD), ImmutableSet.of(GBP_LIBOR_3M))); assertEquals( test.ratesProvider(MOCK_MARKET_DATA), DefaultLookupRatesProvider.of((DefaultRatesMarketDataLookup) test, MOCK_MARKET_DATA)); } public void test_of_groupNameAndMap() { ImmutableMap<Currency, CurveName> discounts = ImmutableMap.of(USD, CURVE_ID_DSC.getCurveName()); ImmutableMap<Index, CurveName> forwards = ImmutableMap.of(USD_LIBOR_3M, CURVE_ID_FWD.getCurveName()); RatesMarketDataLookup test = RatesMarketDataLookup.of(CURVE_ID_DSC.getCurveGroupName(), discounts, forwards); assertEquals(test.queryType(), RatesMarketDataLookup.class); assertEquals(test.getDiscountCurrencies(), ImmutableSet.of(USD)); assertEquals(test.getDiscountMarketDataIds(USD), ImmutableSet.of(CURVE_ID_DSC)); assertEquals(test.getForwardIndices(), ImmutableSet.of(USD_LIBOR_3M)); assertEquals(test.getForwardMarketDataIds(USD_LIBOR_3M), ImmutableSet.of(CURVE_ID_FWD)); assertThrowsIllegalArg(() -> test.getDiscountMarketDataIds(GBP)); assertThrowsIllegalArg(() -> test.getForwardMarketDataIds(GBP_LIBOR_3M)); } public void test_of_curveGroup() { ImmutableMap<Currency, Curve> discounts = ImmutableMap.of(USD, ConstantCurve.of(CURVE_ID_DSC.getCurveName(), 1)); ImmutableMap<Index, Curve> forwards = ImmutableMap.of(USD_LIBOR_3M, ConstantCurve.of(CURVE_ID_FWD.getCurveName(), 1)); CurveGroup group = CurveGroup.of(CURVE_ID_DSC.getCurveGroupName(), discounts, forwards); RatesMarketDataLookup test = RatesMarketDataLookup.of(group); assertEquals(test.queryType(), RatesMarketDataLookup.class); assertEquals(test.getDiscountCurrencies(), ImmutableSet.of(USD)); assertEquals(test.getDiscountMarketDataIds(USD), ImmutableSet.of(CURVE_ID_DSC)); assertEquals(test.getForwardIndices(), ImmutableSet.of(USD_LIBOR_3M)); assertEquals(test.getForwardMarketDataIds(USD_LIBOR_3M), ImmutableSet.of(CURVE_ID_FWD)); assertThrowsIllegalArg(() -> test.getDiscountMarketDataIds(GBP)); assertThrowsIllegalArg(() -> test.getForwardMarketDataIds(GBP_LIBOR_3M)); } //------------------------------------------------------------------------- public void test_marketDataView() { ImmutableMap<Currency, CurveId> discounts = ImmutableMap.of(USD, CURVE_ID_DSC); ImmutableMap<Index, CurveId> forwards = ImmutableMap.of(USD_LIBOR_3M, CURVE_ID_FWD); RatesMarketDataLookup test = RatesMarketDataLookup.of(discounts, forwards); LocalDate valDate = date(2015, 6, 30); ScenarioMarketData md = new TestMarketDataMap(valDate, ImmutableMap.of(), ImmutableMap.of()); RatesScenarioMarketData multiScenario = test.marketDataView(md); assertEquals(multiScenario.getLookup(), test); assertEquals(multiScenario.getMarketData(), md); assertEquals(multiScenario.getScenarioCount(), 1); RatesMarketData scenario = multiScenario.scenario(0); assertEquals(scenario.getLookup(), test); assertEquals(scenario.getMarketData(), md.scenario(0)); assertEquals(scenario.getValuationDate(), valDate); } public void test_ratesProvider() { ImmutableMap<Currency, CurveId> discounts = ImmutableMap.of(USD, CURVE_ID_DSC); ImmutableMap<Index, CurveId> forwards = ImmutableMap.of(USD_FED_FUND, CURVE_ID_DSC, USD_LIBOR_3M, CURVE_ID_FWD, US_CPI_U, CURVE_ID_FWD); RatesMarketDataLookup test = RatesMarketDataLookup.of(discounts, forwards); LocalDate valDate = date(2015, 6, 30); Curve dscCurve = ConstantCurve.of(Curves.discountFactors(CURVE_ID_DSC.getCurveName(), ACT_360), 1d); Curve fwdCurve = ConstantCurve.of(Curves.discountFactors(CURVE_ID_FWD.getCurveName(), ACT_360), 2d); MarketData md = ImmutableMarketData.of(valDate, ImmutableMap.of(CURVE_ID_DSC, dscCurve, CURVE_ID_FWD, fwdCurve)); RatesProvider ratesProvider = test.ratesProvider(md); assertEquals(ratesProvider.getValuationDate(), valDate); assertEquals(ratesProvider.findData(CURVE_ID_DSC.getCurveName()), Optional.of(dscCurve)); assertEquals(ratesProvider.findData(CURVE_ID_FWD.getCurveName()), Optional.of(fwdCurve)); assertEquals(ratesProvider.findData(CurveName.of("Rubbish")), Optional.empty()); // check discount factors SimpleDiscountFactors df = (SimpleDiscountFactors) ratesProvider.discountFactors(USD); assertEquals(df.getCurve().getName(), dscCurve.getName()); assertThrowsIllegalArg(() -> ratesProvider.discountFactors(GBP)); // check Ibor DiscountIborIndexRates ibor = (DiscountIborIndexRates) ratesProvider.iborIndexRates(USD_LIBOR_3M); SimpleDiscountFactors iborDf = (SimpleDiscountFactors) ibor.getDiscountFactors(); assertEquals(iborDf.getCurve().getName(), fwdCurve.getName()); assertThrowsIllegalArg(() -> ratesProvider.iborIndexRates(GBP_LIBOR_3M)); // check Overnight DiscountOvernightIndexRates on = (DiscountOvernightIndexRates) ratesProvider.overnightIndexRates(USD_FED_FUND); SimpleDiscountFactors onDf = (SimpleDiscountFactors) on.getDiscountFactors(); assertEquals(onDf.getCurve().getName(), dscCurve.getName()); assertThrowsIllegalArg(() -> ratesProvider.overnightIndexRates(GBP_SONIA)); // check price curve must be interpolated assertThrowsIllegalArg(() -> ratesProvider.priceIndexValues(US_CPI_U)); // to immutable ImmutableRatesProvider expectedImmutable = ImmutableRatesProvider.builder(valDate) .fxRateProvider(MarketDataFxRateProvider.of(md)) .discountCurve(USD, dscCurve) .indexCurve(USD_FED_FUND, dscCurve) .indexCurve(USD_LIBOR_3M, fwdCurve) .indexCurve(US_CPI_U, fwdCurve) .build(); assertEquals(ratesProvider.toImmutableRatesProvider(), expectedImmutable); } public void test_fxProvider() { RatesMarketDataLookup test = RatesMarketDataLookup.of(ImmutableMap.of(), ImmutableMap.of()); LocalDate valDate = date(2015, 6, 30); FxRateId gbpUsdId = FxRateId.of(GBP, USD); FxRate gbpUsdRate = FxRate.of(GBP, USD, 1.6); MarketData md = ImmutableMarketData.of(valDate, ImmutableMap.of(gbpUsdId, gbpUsdRate)); FxRateProvider fxProvider = test.fxRateProvider(md); assertEquals(fxProvider.fxRate(GBP, USD), 1.6); assertEquals(test.marketDataView(md).fxRateProvider().fxRate(GBP, USD), 1.6); assertThrows(() -> fxProvider.fxRate(EUR, USD), MarketDataNotFoundException.class); } //------------------------------------------------------------------------- public void coverage() { ImmutableMap<Currency, CurveId> discounts = ImmutableMap.of(USD, CURVE_ID_DSC); ImmutableMap<Index, CurveId> forwards = ImmutableMap.of(USD_LIBOR_3M, CURVE_ID_FWD); DefaultRatesMarketDataLookup test = DefaultRatesMarketDataLookup.of(discounts, forwards, ObservableSource.NONE, FxRateLookup.ofRates()); coverImmutableBean(test); ImmutableMap<Currency, CurveId> discounts2 = ImmutableMap.of(GBP, CURVE_ID_DSC); ImmutableMap<Index, CurveId> forwards2 = ImmutableMap.of(GBP_LIBOR_3M, CURVE_ID_FWD); DefaultRatesMarketDataLookup test2 = DefaultRatesMarketDataLookup.of(discounts2, forwards2, OBS_SOURCE, FxRateLookup.ofRates(EUR)); coverBeanEquals(test, test2); // related coverage coverImmutableBean((ImmutableBean) test.marketDataView(MOCK_CALC_MARKET_DATA)); DefaultRatesScenarioMarketData.meta(); coverImmutableBean((ImmutableBean) test.marketDataView(MOCK_MARKET_DATA)); DefaultRatesMarketData.meta(); coverImmutableBean((ImmutableBean) test.marketDataView(MOCK_MARKET_DATA).ratesProvider()); DefaultLookupRatesProvider.meta(); } public void test_serialization() { ImmutableMap<Currency, CurveId> discounts = ImmutableMap.of(USD, CURVE_ID_DSC); ImmutableMap<Index, CurveId> forwards = ImmutableMap.of(USD_LIBOR_3M, CURVE_ID_FWD); DefaultRatesMarketDataLookup test = DefaultRatesMarketDataLookup.of(discounts, forwards, ObservableSource.NONE, FxRateLookup.ofRates()); assertSerialization(test); Curve curve = ConstantCurve.of(Curves.discountFactors("DSC", ACT_360), 0.99); Map<? extends MarketDataId<?>, ?> valuesMap = ImmutableMap.of( CURVE_ID_DSC, curve, CURVE_ID_FWD, curve); MarketData md = MarketData.of(date(2016, 6, 30), valuesMap); assertSerialization(test.marketDataView(md)); assertSerialization(test.ratesProvider(md)); } }