@@ -196,13 +196,15 @@ LgmBuilder::LgmBuilder(const boost::shared_ptr<ore::data::Market>& market, const
196196 swapIndex_ = market_->swapIndex (market_->swapIndexBase (data_->qualifier (), configuration_), configuration_);
197197 // see the comment for dinscountCurve() in the interface
198198 modelDiscountCurve_ = RelinkableHandle<YieldTermStructure>(*swapIndex_->discountingTermStructure ());
199+ calibrationDiscountCurve_ = Handle<YieldTermStructure>(*swapIndex_->discountingTermStructure ());
199200 } catch (const std::exception& e) {
200201 StructuredModelErrorMessage (
201202 " Error when retrieving swap index base for qualifier '" + data_->qualifier () +
202203 " '. Use market discount curve instead of swap index discount curve as a fallback." ,
203204 e.what (), id_)
204205 .log ();
205206 modelDiscountCurve_ = RelinkableHandle<YieldTermStructure>(*market_->discountCurve (currency_, configuration_));
207+ calibrationDiscountCurve_ = Handle<YieldTermStructure>(*swapIndex_->discountingTermStructure ());
206208 }
207209
208210 if (requiresCalibration_) {
@@ -212,6 +214,7 @@ LgmBuilder::LgmBuilder(const boost::shared_ptr<ore::data::Market>& market, const
212214 marketObserver_->addObservable (shortSwapIndex_->discountingTermStructure ());
213215 }
214216 marketObserver_->addObservable (modelDiscountCurve_);
217+ marketObserver_->addObservable (calibrationDiscountCurve_);
215218 registerWith (marketObserver_);
216219 // notify observers of all market data changes, not only when not calculated
217220 alwaysForwardNotifications ();
@@ -322,16 +325,18 @@ bool LgmBuilder::requiresRecalibration() const {
322325void LgmBuilder::performCalculations () const {
323326
324327 DLOG (" Recalibrate LGM model for qualifier " << data_->qualifier () << " currency " << currency_);
328+ std::cout << " reaclibrate model ... " << std::flush;
325329
326330 if (!requiresRecalibration ()) {
327331 DLOG (" Skipping calibration as nothing has changed" );
332+ std::cout << " skipped." << std::endl;
328333 return ;
329334 }
330335
331336 // reset lgm observer's updated flag
332337 marketObserver_->hasUpdated (true );
333338
334- if (swaptionBasketRefDate_ != modelDiscountCurve_ ->referenceDate ()) {
339+ if (swaptionBasketRefDate_ != calibrationDiscountCurve_ ->referenceDate ()) {
335340 // build swaption basket if required, i.e. if reference date has changed since last build
336341 buildSwaptionBasket ();
337342 volSurfaceChanged (true );
@@ -343,8 +348,7 @@ void LgmBuilder::performCalculations() const {
343348 }
344349
345350 for (Size j = 0 ; j < swaptionBasket_.size (); j++) {
346- auto engine =
347- boost::make_shared<QuantExt::AnalyticLgmSwaptionEngine>(model_, modelDiscountCurve_);
351+ auto engine = boost::make_shared<QuantExt::AnalyticLgmSwaptionEngine>(model_, calibrationDiscountCurve_);
348352 engine->enableCache (!data_->calibrateH (), !data_->calibrateA ());
349353 swaptionBasket_[j]->setPricingEngine (engine);
350354 // necessary if notifications are disabled (observation mode = Disable)
@@ -459,6 +463,9 @@ void LgmBuilder::performCalculations() const {
459463 DLOG (" Apply scaling " << data_->scaling () << " to the " << data_->qualifier () << " LGM model" );
460464 parametrization_->scaling () = data_->scaling ();
461465 }
466+
467+ std::cout << " done." << std::endl;
468+
462469} // performCalculations()
463470
464471void LgmBuilder::getExpiryAndTerm (const Size j, Period& expiryPb, Period& termPb, Date& expiryDb, Date& termDb,
@@ -607,32 +614,28 @@ void LgmBuilder::buildSwaptionBasket() const {
607614
608615 if (expiryDateBased && termDateBased) {
609616 Real shift = svts_->volatilityType () == ShiftedLognormal ? svts_->shift (expiryDb, termT) : 0.0 ;
610- std::tie (helper, updatedStrike) =
611- createSwaptionHelper (expiryDb, termDb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter,
612- floatDayCounter, modelDiscountCurve_, calibrationErrorType_,
613- strikeValue, shift, settlementDays, averagingMethod);
617+ std::tie (helper, updatedStrike) = createSwaptionHelper (
618+ expiryDb, termDb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter, floatDayCounter,
619+ calibrationDiscountCurve_, calibrationErrorType_, strikeValue, shift, settlementDays, averagingMethod);
614620 }
615621 if (expiryDateBased && !termDateBased) {
616622 Real shift = svts_->volatilityType () == ShiftedLognormal ? svts_->shift (expiryDb, termPb) : 0.0 ;
617- std::tie (helper, updatedStrike) =
618- createSwaptionHelper (expiryDb, termPb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter,
619- floatDayCounter, modelDiscountCurve_, calibrationErrorType_,
620- strikeValue, shift, settlementDays, averagingMethod);
623+ std::tie (helper, updatedStrike) = createSwaptionHelper (
624+ expiryDb, termPb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter, floatDayCounter,
625+ calibrationDiscountCurve_, calibrationErrorType_, strikeValue, shift, settlementDays, averagingMethod);
621626 }
622627 if (!expiryDateBased && termDateBased) {
623628 Date expiry = svts_->optionDateFromTenor (expiryPb);
624629 Real shift = svts_->volatilityType () == ShiftedLognormal ? svts_->shift (expiryPb, termT) : 0.0 ;
625- std::tie (helper, updatedStrike) =
626- createSwaptionHelper (expiry, termDb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter,
627- floatDayCounter, modelDiscountCurve_, calibrationErrorType_,
628- strikeValue, shift, settlementDays, averagingMethod);
630+ std::tie (helper, updatedStrike) = createSwaptionHelper (
631+ expiry, termDb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter, floatDayCounter,
632+ calibrationDiscountCurve_, calibrationErrorType_, strikeValue, shift, settlementDays, averagingMethod);
629633 }
630634 if (!expiryDateBased && !termDateBased) {
631635 Real shift = svts_->volatilityType () == ShiftedLognormal ? svts_->shift (expiryPb, termPb) : 0.0 ;
632- std::tie (helper, updatedStrike) =
633- createSwaptionHelper (expiryPb, termPb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter,
634- floatDayCounter, modelDiscountCurve_, calibrationErrorType_,
635- strikeValue, shift, settlementDays, averagingMethod);
636+ std::tie (helper, updatedStrike) = createSwaptionHelper (
637+ expiryPb, termPb, svts_, vol, iborIndex, fixedLegTenor, fixedDayCounter, floatDayCounter,
638+ calibrationDiscountCurve_, calibrationErrorType_, strikeValue, shift, settlementDays, averagingMethod);
636639 }
637640
638641 // check if we want to keep the helper when a reference calibration grid is given
@@ -644,10 +647,10 @@ void LgmBuilder::buildSwaptionBasket() const {
644647 swaptionBasketVols_.push_back (volQuote);
645648 swaptionBasket_.push_back (helper);
646649 swaptionStrike_.push_back (updatedStrike);
647- expiryTimes.push_back (modelDiscountCurve_ ->timeFromReference (expiryDate));
650+ expiryTimes.push_back (calibrationDiscountCurve_ ->timeFromReference (expiryDate));
648651 Date matDate = helper->underlyingSwap () ? helper->underlyingSwap ()->maturityDate ()
649652 : helper->underlyingOvernightIndexedSwap ()->maturityDate ();
650- maturityTimes.push_back (modelDiscountCurve_ ->timeFromReference (matDate));
653+ maturityTimes.push_back (calibrationDiscountCurve_ ->timeFromReference (matDate));
651654 if (refCalDate != referenceCalibrationDates.end ())
652655 lastRefCalDate = *refCalDate;
653656 }
@@ -669,7 +672,7 @@ void LgmBuilder::buildSwaptionBasket() const {
669672 for (Size j = 0 ; j < maturityTimes.size (); j++)
670673 swaptionMaturities_[j] = maturityTimes[j];
671674
672- swaptionBasketRefDate_ = modelDiscountCurve_ ->referenceDate ();
675+ swaptionBasketRefDate_ = calibrationDiscountCurve_ ->referenceDate ();
673676}
674677
675678std::string LgmBuilder::getBasketDetails (LgmCalibrationInfo& info) const {
@@ -680,7 +683,7 @@ std::string LgmBuilder::getBasketDetails(LgmCalibrationInfo& info) const {
680683 info.swaptionData .clear ();
681684 for (Size j = 0 ; j < swaptionBasket_.size (); ++j) {
682685 auto swp = boost::static_pointer_cast<SwaptionHelper>(swaptionBasket_[j])->swaption ();
683- auto sd = swaptionData (swp, modelDiscountCurve_ , svts_);
686+ auto sd = swaptionData (swp, calibrationDiscountCurve_ , svts_);
684687 log << std::right << std::setw (3 ) << j << std::setw (16 ) << sd.timeToExpiry << std::setw (16 ) << sd.swapLength
685688 << std::setw (16 ) << sd.strike << std::setw (16 ) << sd.atmForward << std::setw (16 ) << sd.annuity
686689 << std::setw (16 ) << sd.vega << std::setw (16 ) << std::setw (16 ) << sd.stdDev / std::sqrt (sd.timeToExpiry )
0 commit comments