From 14f08505761328bc60fca232347477ac3fc36197 Mon Sep 17 00:00:00 2001 From: Chris Kent Date: Thu, 27 Jun 2019 10:07:15 +0100 Subject: [PATCH 1/3] Handle observable source when creating lookups --- .../rate/DefaultRatesMarketDataLookup.java | 24 ++++++++ .../measure/rate/RatesMarketDataLookup.java | 5 +- .../DefaultRatesMarketDataLookupTest.java | 59 +++++++++++++++++++ .../rate/RatesMarketDataLookupTest.java | 35 +++++++++++ 4 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java diff --git a/modules/measure/src/main/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookup.java b/modules/measure/src/main/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookup.java index 4b2aabb8cc..bed0d59f28 100644 --- a/modules/measure/src/main/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookup.java +++ b/modules/measure/src/main/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookup.java @@ -10,6 +10,7 @@ import java.io.Serializable; import java.lang.invoke.MethodHandles; +import java.util.Collection; import java.util.Map; import java.util.Set; @@ -18,6 +19,7 @@ import org.joda.beans.MetaBean; import org.joda.beans.TypedMetaBean; import org.joda.beans.gen.BeanDefinition; +import org.joda.beans.gen.ImmutableValidator; import org.joda.beans.gen.PropertyDefinition; import org.joda.beans.impl.light.LightMetaBean; @@ -195,6 +197,27 @@ String msgIndexNotFound(Index index) { return Messages.format("Rates lookup has no forward curve defined for index '{}'", index); } + @ImmutableValidator + private void validate() { + validateObservableSource(forwardCurves.values()); + validateObservableSource(discountCurves.values()); + } + + /** + * Checks that the observable source in this instance matches the source in the IDs. + */ + private void validateObservableSource(Collection curveIds) { + for (CurveId curveId : curveIds) { + if (!curveId.getObservableSource().equals(observableSource)) { + throw new IllegalArgumentException( + Messages.format( + "The observable source '{}' must match the observable source in all curve IDs but found {}", + observableSource, + curveId)); + } + } + } + //------------------------- AUTOGENERATED START ------------------------- /** * The meta-bean for {@code DefaultRatesMarketDataLookup}. @@ -244,6 +267,7 @@ private DefaultRatesMarketDataLookup( this.forwardCurves = ImmutableMap.copyOf(forwardCurves); this.observableSource = observableSource; this.fxRateLookup = fxRateLookup; + validate(); } @Override diff --git a/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesMarketDataLookup.java b/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesMarketDataLookup.java index 2d1162ff12..dd625af540 100644 --- a/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesMarketDataLookup.java +++ b/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesMarketDataLookup.java @@ -165,7 +165,8 @@ public static RatesMarketDataLookup of(RatesCurveGroupDefinition curveGroupDefin * @param fxLookup the lookup used to obtain FX rates * @return the rates lookup based on the specified group */ - public static RatesMarketDataLookup of(RatesCurveGroupDefinition curveGroupDefinition, + public static RatesMarketDataLookup of( + RatesCurveGroupDefinition curveGroupDefinition, ObservableSource observableSource, FxRateLookup fxLookup) { @@ -173,7 +174,7 @@ public static RatesMarketDataLookup of(RatesCurveGroupDefinition curveGroupDefin Map discountCurves = new HashMap<>(); Map forwardCurves = new HashMap<>(); for (RatesCurveGroupEntry entry : curveGroupDefinition.getEntries()) { - CurveId curveId = CurveId.of(groupName, entry.getCurveName()); + CurveId curveId = CurveId.of(groupName, entry.getCurveName(), observableSource); entry.getDiscountCurrencies().forEach(ccy -> discountCurves.put(ccy, curveId)); entry.getIndices().forEach(idx -> forwardCurves.put(idx, curveId)); } diff --git a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java new file mode 100644 index 0000000000..05f6e5b386 --- /dev/null +++ b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 - present by OpenGamma Inc. and the OpenGamma group of companies + * + * Please see distribution for license. + */ + +package com.opengamma.strata.measure.rate; + +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +import java.util.Map; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.opengamma.strata.basics.currency.Currency; +import com.opengamma.strata.basics.index.IborIndex; +import com.opengamma.strata.basics.index.IborIndices; +import com.opengamma.strata.calc.runner.FxRateLookup; +import com.opengamma.strata.data.ObservableSource; +import com.opengamma.strata.market.curve.CurveGroupName; +import com.opengamma.strata.market.curve.CurveId; +import com.opengamma.strata.market.curve.CurveName; + +@Test +public class DefaultRatesMarketDataLookupTest { + + /** + * Validates the observable source in the curve IDs match the observable source passed in. + */ + public void validateObservableSourceDiscountCurves() { + ObservableSource observableSource = ObservableSource.of("source"); + CurveId curveId = CurveId.of(CurveGroupName.of("group"), CurveName.of("curves"), observableSource); + Map curveMap = ImmutableMap.of(Currency.USD, curveId); + // This should complete successfully + DefaultRatesMarketDataLookup.of(curveMap, ImmutableMap.of(), observableSource, FxRateLookup.ofRates()); + // This should blow up because the source in the IDs doesn't match the source passed to the method + assertThatIllegalArgumentException() + .isThrownBy(() -> + DefaultRatesMarketDataLookup.of(curveMap, ImmutableMap.of(), ObservableSource.NONE, FxRateLookup.ofRates())) + .withMessageContaining("must match the observable source in all curve IDs"); + } + + /** + * Validates the observable source in the curve IDs match the observable source passed in. + */ + public void validateObservableSourceForwardCurves() { + ObservableSource observableSource = ObservableSource.of("source"); + CurveId curveId = CurveId.of(CurveGroupName.of("group"), CurveName.of("curves"), observableSource); + Map curveMap = ImmutableMap.of(IborIndices.AUD_BBSW_1M, curveId); + // This should complete successfully + DefaultRatesMarketDataLookup.of(ImmutableMap.of(), curveMap, observableSource, FxRateLookup.ofRates()); + // This should blow up because the source in the IDs doesn't match the source passed to the method + assertThatIllegalArgumentException() + .isThrownBy(() -> + DefaultRatesMarketDataLookup.of(ImmutableMap.of(), curveMap, ObservableSource.NONE, FxRateLookup.ofRates())) + .withMessageContaining("must match the observable source in all curve IDs"); + } +} diff --git a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java index 3dd629fccd..301bbf60b7 100644 --- a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java +++ b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java @@ -25,6 +25,7 @@ import static org.testng.Assert.assertEquals; import java.time.LocalDate; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -32,6 +33,7 @@ import org.joda.beans.ser.JodaBeanSer; import org.testng.annotations.Test; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.opengamma.strata.basics.currency.Currency; @@ -53,10 +55,13 @@ 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.CurveGroupName; 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.curve.RatesCurveGroup; +import com.opengamma.strata.market.curve.RatesCurveGroupDefinition; +import com.opengamma.strata.market.curve.RatesCurveGroupEntry; import com.opengamma.strata.market.observable.IndexQuoteId; import com.opengamma.strata.measure.curve.TestMarketDataMap; import com.opengamma.strata.pricer.SimpleDiscountFactors; @@ -146,6 +151,36 @@ public void test_of_curveGroup() { assertThrowsIllegalArg(() -> test.getForwardMarketDataIds(GBP_LIBOR_3M)); } + public void test_of_curveGroupDefinition_and_observableSource() { + RatesCurveGroupEntry entry1 = RatesCurveGroupEntry.builder() + .curveName(CURVE_ID_DSC.getCurveName()) + .discountCurrencies(USD) + .build(); + + RatesCurveGroupEntry entry2 = RatesCurveGroupEntry.builder() + .curveName(CURVE_ID_FWD.getCurveName()) + .indices(USD_LIBOR_3M) + .build(); + + List entries = ImmutableList.of(entry1, entry2); + CurveGroupName groupName = CURVE_ID_DSC.getCurveGroupName(); + ObservableSource observableSource = ObservableSource.of("foo"); + RatesCurveGroupDefinition groupDefinition = RatesCurveGroupDefinition.of(groupName, entries, ImmutableList.of()); + + // The lookup should contain curve IDs with the non-default ObservableSource + CurveId dscId = CurveId.of(CURVE_ID_DSC.getCurveGroupName(), CURVE_ID_DSC.getCurveName(), observableSource); + CurveId fwdId = CurveId.of(CURVE_ID_FWD.getCurveGroupName(), CURVE_ID_FWD.getCurveName(), observableSource); + + RatesMarketDataLookup test = RatesMarketDataLookup.of(groupDefinition, observableSource, FxRateLookup.ofRates()); + assertEquals(test.queryType(), RatesMarketDataLookup.class); + assertEquals(test.getDiscountCurrencies(), ImmutableSet.of(USD)); + assertEquals(test.getDiscountMarketDataIds(USD), ImmutableSet.of(dscId)); + assertEquals(test.getForwardIndices(), ImmutableSet.of(USD_LIBOR_3M)); + assertEquals(test.getForwardMarketDataIds(USD_LIBOR_3M), ImmutableSet.of(fwdId)); + assertThrowsIllegalArg(() -> test.getDiscountMarketDataIds(GBP)); + assertThrowsIllegalArg(() -> test.getForwardMarketDataIds(GBP_LIBOR_3M)); + } + //------------------------------------------------------------------------- public void test_marketDataView() { ImmutableMap discounts = ImmutableMap.of(USD, CURVE_ID_DSC); From aeaf4b1f14ade4d057eb7583addf90464b24cdd2 Mon Sep 17 00:00:00 2001 From: Chris Kent Date: Thu, 27 Jun 2019 10:41:47 +0100 Subject: [PATCH 2/3] Fix test --- .../strata/measure/rate/RatesMarketDataLookupTest.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java index 301bbf60b7..3c56c66339 100644 --- a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java +++ b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesMarketDataLookupTest.java @@ -164,14 +164,13 @@ public void test_of_curveGroupDefinition_and_observableSource() { List entries = ImmutableList.of(entry1, entry2); CurveGroupName groupName = CURVE_ID_DSC.getCurveGroupName(); - ObservableSource observableSource = ObservableSource.of("foo"); RatesCurveGroupDefinition groupDefinition = RatesCurveGroupDefinition.of(groupName, entries, ImmutableList.of()); // The lookup should contain curve IDs with the non-default ObservableSource - CurveId dscId = CurveId.of(CURVE_ID_DSC.getCurveGroupName(), CURVE_ID_DSC.getCurveName(), observableSource); - CurveId fwdId = CurveId.of(CURVE_ID_FWD.getCurveGroupName(), CURVE_ID_FWD.getCurveName(), observableSource); + CurveId dscId = CurveId.of(CURVE_ID_DSC.getCurveGroupName(), CURVE_ID_DSC.getCurveName(), OBS_SOURCE); + CurveId fwdId = CurveId.of(CURVE_ID_FWD.getCurveGroupName(), CURVE_ID_FWD.getCurveName(), OBS_SOURCE); - RatesMarketDataLookup test = RatesMarketDataLookup.of(groupDefinition, observableSource, FxRateLookup.ofRates()); + RatesMarketDataLookup test = RatesMarketDataLookup.of(groupDefinition, OBS_SOURCE, FxRateLookup.ofRates()); assertEquals(test.queryType(), RatesMarketDataLookup.class); assertEquals(test.getDiscountCurrencies(), ImmutableSet.of(USD)); assertEquals(test.getDiscountMarketDataIds(USD), ImmutableSet.of(dscId)); @@ -278,7 +277,7 @@ public void coverage() { ImmutableMap discounts2 = ImmutableMap.of(GBP, CURVE_ID_DSC); ImmutableMap forwards2 = ImmutableMap.of(GBP_LIBOR_3M, CURVE_ID_FWD); DefaultRatesMarketDataLookup test2 = - DefaultRatesMarketDataLookup.of(discounts2, forwards2, OBS_SOURCE, FxRateLookup.ofRates(EUR)); + DefaultRatesMarketDataLookup.of(discounts2, forwards2, ObservableSource.NONE, FxRateLookup.ofRates(EUR)); coverBeanEquals(test, test2); // related coverage From 6aff33b0b08a4a88a2ba058081aeff9f7bf54089 Mon Sep 17 00:00:00 2001 From: Chris Kent Date: Thu, 27 Jun 2019 10:50:03 +0100 Subject: [PATCH 3/3] Remove blank line --- .../strata/measure/rate/DefaultRatesMarketDataLookupTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java index 05f6e5b386..4b0eeaf559 100644 --- a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java +++ b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/DefaultRatesMarketDataLookupTest.java @@ -3,7 +3,6 @@ * * Please see distribution for license. */ - package com.opengamma.strata.measure.rate; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;