diff --git a/OREAnalytics/test/testmarket.cpp b/OREAnalytics/test/testmarket.cpp index bdf8ab33b..c9681933d 100644 --- a/OREAnalytics/test/testmarket.cpp +++ b/OREAnalytics/test/testmarket.cpp @@ -436,8 +436,7 @@ TestMarket::TestMarket(Date asof, bool swapVolCube) : MarketImpl(false) { euii->addFixing(fixingDatesEUHICPXT[i], fixingRatesEUHICPXT[i], true); }; - vector datesZCII = {asof_, - asof_ + 1 * Years, + vector datesZCII = {asof_ + 1 * Years, asof_ + 2 * Years, asof_ + 3 * Years, asof_ + 4 * Years, @@ -451,7 +450,7 @@ TestMarket::TestMarket(Date asof, bool swapVolCube) : MarketImpl(false) { asof_ + 15 * Years, asof_ + 20 * Years}; - vector ratesZCII = {2.825, 2.9425, 2.975, 2.983, 3.0, 3.01, 3.008, + vector ratesZCII = {2.9425, 2.975, 2.983, 3.0, 3.01, 3.008, 3.009, 3.013, 3.0445, 3.044, 3.09, 3.109, 3.108}; zeroInflationIndices_[make_pair(Market::defaultConfiguration, "EUHICPXT")] = @@ -579,8 +578,17 @@ Handle TestMarket::makeZeroInflationIndex(string index, vect for (Size i = 0; i < dates.size(); i++) { Handle quote(QuantLib::ext::shared_ptr(new SimpleQuote(rates[i] / 100.0))); QuantLib::ext::shared_ptr> anInstrument(new ZeroCouponInflationSwapHelper( - quote, Period(2, Months), dates[i], TARGET(), ModifiedFollowing, ActualActual(ActualActual::ISDA), ii, CPI::AsIndex, yts)); - anInstrument->unregisterWith(Settings::instance().evaluationDate()); + quote, Period(2, Months), dates[i], TARGET(), ModifiedFollowing, ActualActual(ActualActual::ISDA), ii, CPI::AsIndex, yts, asof_)); + + // Remove the helper's observation of the inflation index. This has the effect that the + // PiecewiseZeroInflationCurve created below will also not observe the index. It will only get recalculated + // if the initial market quotes change or if the initial nominal yield curve changes. Observation of the index + // was interfering with scenario generation. The PiecewiseZeroInflationCurve was getting recalculated on the + // first time grid date t_1 i.e. was not using the t_0 calculated curve. + anInstrument->unregisterWithAll(); + anInstrument->registerWith(yts); + anInstrument->registerWith(quote); + instruments.push_back(anInstrument); }; // we can use historical or first ZCIIS for this @@ -593,7 +601,6 @@ Handle TestMarket::makeZeroInflationIndex(string index, vect pCPIts->recalculate(); cpiTS = QuantLib::ext::dynamic_pointer_cast(pCPIts); cpiTS->enableExtrapolation(true); - cpiTS->unregisterWith(Settings::instance().evaluationDate()); return Handle(parseZeroInflationIndex(index, Handle(cpiTS))); } @@ -608,8 +615,24 @@ Handle TestMarket::makeYoYInflationIndex(string index, vector Handle quote(QuantLib::ext::shared_ptr(new SimpleQuote(rates[i] / 100.0))); QL_DEPRECATED_DISABLE_WARNING QuantLib::ext::shared_ptr> anInstrument(new YearOnYearInflationSwapHelper( - quote, Period(2, Months), dates[i], TARGET(), ModifiedFollowing, ActualActual(ActualActual::ISDA), ii, yts)); + quote, Period(2, Months), dates[i], TARGET(), ModifiedFollowing, ActualActual(ActualActual::ISDA), ii, yts, asof_)); QL_DEPRECATED_ENABLE_WARNING + + // Remove the helper's observation of the inflation index. This has the effect that the + // PiecewiseYoYInflationCurve created below will also not observe the index. It will only get recalculated + // if the initial market quotes change or if the initial nominal yield curve changes. + // Note: QuantLib needs a change so that if swap start is provided in the helper above then updateDates_ on + // the RelativeDateBootstrapHelper should be false and hence the helper does not observe Settings + // evaluationDate. Without this fix, the unregister here does this also. + // These changes are needed to allow ObservationModeTest/testDefer to pass. Without them + // YearOnYearInflationSwapHelper::initializeDates() gets called due to evaluation date changes, the yyiis_ + // member gets reassigned but the original value is still in the deferredObervers_. The testDefer test then + // crashes when deferredObserver->update(); is called in ObservableSettings::enableUpdates() with + // deferredObserver null. + anInstrument->unregisterWithAll(); + anInstrument->registerWith(yts); + anInstrument->registerWith(quote); + instruments.push_back(anInstrument); }; // we can use historical or first ZCIIS for this diff --git a/OREData/ored/marketdata/inflationcurve.cpp b/OREData/ored/marketdata/inflationcurve.cpp index cdc56af10..3550a9726 100644 --- a/OREData/ored/marketdata/inflationcurve.cpp +++ b/OREData/ored/marketdata/inflationcurve.cpp @@ -281,7 +281,12 @@ InflationCurve::CurveBuildResults zcq->quote(), convention->observationLag(), maturity, convention->fixCalendar(), convention->fixConvention(), convention->dayCounter(), index, observationInterpolation, nominalTs, swapStart); - instrument->unregisterWith(Settings::instance().evaluationDate()); + + // Unregister with inflation index. See PR #326 for details. + instrument->unregisterWithAll(); + instrument->registerWith(nominalTs); + instrument->registerWith(zcq->quote()); + helpers.push_back(instrument); } } @@ -377,8 +382,13 @@ InflationCurve::CurveBuildResults QuantLib::ext::make_shared( quote, convention->observationLag(), maturity, convention->fixCalendar(), convention->fixConvention(), convention->dayCounter(), index, nominalTs, swapStart); - instrument->unregisterWith(Settings::instance().evaluationDate()); results.pillarDates.push_back(instrument->pillarDate()); + + // Unregister with inflation index (and evaluationDate). See PR #326 for details. + instrument->unregisterWithAll(); + instrument->registerWith(nominalTs); + instrument->registerWith(quote); + helpers.push_back(instrument); } }