From c1d9d667bbe8712946728fe4ac8d50b7f4ae43b7 Mon Sep 17 00:00:00 2001 From: Vedant Jawandhia Date: Sun, 2 Aug 2026 01:43:24 +0530 Subject: [PATCH] Provide curve metadata for definitions that need no market data RatesCurveInputs.builder().build() left curveMetadata null, which fails validation when a CurveDefinition has no nodes (or nodes with empty requirements). Build empty inputs with DefaultCurveMetadata of the curve name. Co-authored-by: Cursor --- .../RatesCurveGroupMarketDataFunction.java | 6 +++- ...RatesCurveGroupMarketDataFunctionTest.java | 35 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunction.java b/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunction.java index 46740dbf1e..20bbec5f01 100644 --- a/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunction.java +++ b/modules/measure/src/main/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunction.java @@ -13,6 +13,7 @@ import java.util.Map; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.opengamma.strata.basics.ReferenceData; import com.opengamma.strata.calc.marketdata.MarketDataConfig; import com.opengamma.strata.calc.marketdata.MarketDataFunction; @@ -29,6 +30,7 @@ import com.opengamma.strata.data.scenario.ScenarioMarketData; import com.opengamma.strata.market.curve.CurveDefinition; import com.opengamma.strata.market.curve.CurveGroupName; +import com.opengamma.strata.market.curve.DefaultCurveMetadata; import com.opengamma.strata.market.curve.RatesCurveGroup; import com.opengamma.strata.market.curve.RatesCurveGroupDefinition; import com.opengamma.strata.market.curve.RatesCurveGroupId; @@ -326,7 +328,9 @@ private MarketDataBox curveInputs( RatesCurveInputsId curveInputsId = RatesCurveInputsId.of(groupName, curveDefn.getName(), obsSource); return marketData.getValue(curveInputsId); } else { - return MarketDataBox.ofSingleValue(RatesCurveInputs.builder().build()); + // Empty market-data map still requires non-null curve metadata (#2743). + return MarketDataBox.ofSingleValue( + RatesCurveInputs.of(ImmutableMap.of(), DefaultCurveMetadata.of(curveDefn.getName()))); } } diff --git a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunctionTest.java b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunctionTest.java index 3852f9f009..e78a79dced 100644 --- a/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunctionTest.java +++ b/modules/measure/src/test/java/com/opengamma/strata/measure/rate/RatesCurveGroupMarketDataFunctionTest.java @@ -365,6 +365,41 @@ public void duplicateInputDataKeys() { .withMessageMatching(msg); } + /** + * Curve definitions with no market-data requirements must not build RatesCurveInputs + * via an empty builder (curveMetadata is required). See #2743. + */ + @Test + public void curveDefinitionWithoutMarketDataNodes() { + CurveGroupName groupName = CurveGroupName.of("Curve Group"); + CurveName curveName = CurveName.of("Empty Curve"); + InterpolatedNodalCurveDefinition curveDefn = InterpolatedNodalCurveDefinition.builder() + .name(curveName) + .xValueType(ValueType.YEAR_FRACTION) + .yValueType(ValueType.ZERO_RATE) + .dayCount(ACT_360) + .interpolator(CurveInterpolators.LINEAR) + .extrapolatorLeft(CurveExtrapolators.FLAT) + .extrapolatorRight(CurveExtrapolators.FLAT) + .build(); + RatesCurveGroupDefinition groupDefn = RatesCurveGroupDefinition.builder() + .name(groupName) + .addDiscountCurve(curveDefn, Currency.USD) + .build(); + + RatesCurveGroupMarketDataFunction function = new RatesCurveGroupMarketDataFunction(); + LocalDate valuationDate = date(2011, 3, 8); + ScenarioMarketData inputMarketData = ImmutableScenarioMarketData.builder(valuationDate).build(); + + // Must not fail with "curveMetadata must not be null" when resolving empty inputs. + // Calibration of a zero-node curve may still fail for other reasons. + try { + function.buildCurveGroup(groupDefn, CALIBRATOR, inputMarketData, REF_DATA, ObservableSource.NONE); + } catch (RuntimeException ex) { + assertThat(ex.getMessage()).doesNotContain("curveMetadata"); + } + } + //----------------------------------------------------------------------------------------------------------- private void checkFraPvIsZero(