@@ -150,7 +150,8 @@ void CrossAssetModelBuilder::performCalculations() const {
150150 }
151151}
152152
153- void CrossAssetModelBuilder::resetModelParams (const AssetType t, const Size param, const Size index, const Size i) const {
153+ void CrossAssetModelBuilder::resetModelParams (const CrossAssetModel::AssetType t, const Size param, const Size index,
154+ const Size i) const {
154155 auto mp = model_->MoveParameter (t, param, index, i);
155156 for (Size idx = 0 ; idx < mp.size (); ++idx) {
156157 if (!mp[idx]) {
@@ -226,8 +227,11 @@ void CrossAssetModelBuilder::buildModel() const {
226227 std::vector<std::string> currencies, regions, crNames, eqNames, infIndices, comNames;
227228 std::vector<boost::shared_ptr<LgmBuilder>> lgmBuilder;
228229 std::vector<boost::shared_ptr<HwBuilder>> hwBuilder;
230+ std::vector<boost::shared_ptr<FxBsBuilder>> fxBuilder;
231+ std::vector<boost::shared_ptr<EqBsBuilder>> eqBuilder;
229232 std::vector<boost::shared_ptr<CommoditySchwartzModelBuilder>> csBuilder;
230233
234+ std::set<std::string> recalibratedCurrencies;
231235 for (Size i = 0 ; i < config_->irConfigs ().size (); i++) {
232236 auto irConfig = config_->irConfigs ()[i];
233237 DLOG (" IR Parametrization " << i << " qualifier " << irConfig->qualifier ());
@@ -239,10 +243,12 @@ void CrossAssetModelBuilder::buildModel() const {
239243 referenceCalibrationGrid_, false , id_);
240244 }
241245 auto builder = boost::dynamic_pointer_cast<LgmBuilder>(subBuilders_[CrossAssetModel::AssetType::IR][i]);
242- if (dontCalibrate_)
243- builder->freeze ();
244246 lgmBuilder.push_back (builder);
245247 auto parametrization = builder->parametrization ();
248+ if (builder->requiresRecalibration ())
249+ recalibratedCurrencies.insert (parametrization->currency ().code ());
250+ if (dontCalibrate_)
251+ builder->freeze ();
246252 swaptionBaskets_[i] = builder->swaptionBasket ();
247253 QL_REQUIRE (std::find (currencies.begin (), currencies.end (), parametrization->currency ().code ()) ==
248254 currencies.end (),
@@ -263,10 +269,12 @@ void CrossAssetModelBuilder::buildModel() const {
263269 config_->bootstrapTolerance (), continueOnError_, referenceCalibrationGrid_, setCalibrationInfo);
264270 }
265271 auto builder = boost::dynamic_pointer_cast<HwBuilder>(subBuilders_[CrossAssetModel::AssetType::IR][i]);
266- if (dontCalibrate_)
267- builder->freeze ();
268272 hwBuilder.push_back (builder);
269273 auto parametrization = builder->parametrization ();
274+ if (builder->requiresRecalibration ())
275+ recalibratedCurrencies.insert (parametrization->currency ().code ());
276+ if (dontCalibrate_)
277+ builder->freeze ();
270278 swaptionBaskets_[i] = builder->swaptionBasket ();
271279 QL_REQUIRE (std::find (currencies.begin (), currencies.end (), parametrization->currency ().code ()) ==
272280 currencies.end (),
@@ -306,6 +314,7 @@ void CrossAssetModelBuilder::buildModel() const {
306314 boost::make_shared<FxBsBuilder>(market_, fx, configurationFxCalibration_, referenceCalibrationGrid_);
307315 }
308316 auto builder = boost::dynamic_pointer_cast<FxBsBuilder>(subBuilders_[CrossAssetModel::AssetType::FX][i]);
317+ fxBuilder.push_back (builder);
309318
310319 boost::shared_ptr<QuantExt::FxBsParametrization> parametrization = builder->parametrization ();
311320
@@ -331,6 +340,7 @@ void CrossAssetModelBuilder::buildModel() const {
331340 }
332341 boost::shared_ptr<EqBsBuilder> builder =
333342 boost::dynamic_pointer_cast<EqBsBuilder>(subBuilders_[CrossAssetModel::AssetType::EQ][i]);
343+ eqBuilder.push_back (builder);
334344 boost::shared_ptr<QuantExt::EqBsParametrization> parametrization = builder->parametrization ();
335345 eqOptionBaskets_[i] = builder->optionBasket ();
336346 eqParametrizations.push_back (parametrization);
@@ -525,6 +535,16 @@ void CrossAssetModelBuilder::buildModel() const {
525535 continue ;
526536 }
527537
538+ if (!fxBuilder[i]->requiresRecalibration () &&
539+ recalibratedCurrencies.find (fx->foreignCcy ()) == recalibratedCurrencies.end () &&
540+ recalibratedCurrencies.find (fx->domesticCcy ()) == recalibratedCurrencies.end ()) {
541+ DLOG (" FX Calibration "
542+ << i << " skipped, since neither fx builder nor ir models in dom / for ccy were recalibrated." );
543+ continue ;
544+ }
545+
546+ std::cout << " calibrate fx " << fx->foreignCcy () << std::endl;
547+
528548 DLOG (" FX Calibration " << i);
529549
530550 // attach pricing engines to helpers
@@ -593,6 +613,14 @@ void CrossAssetModelBuilder::buildModel() const {
593613 DLOG (" EQ Calibration " << i << " skipped" );
594614 continue ;
595615 }
616+
617+ if (!eqBuilder[i]->requiresRecalibration () &&
618+ recalibratedCurrencies.find (eq->currency ()) == recalibratedCurrencies.end ()) {
619+ DLOG (" EQ Calibration "
620+ << i << " skipped, since neither eq builder nor ir model in eq ccy were recalibrated." );
621+ continue ;
622+ }
623+
596624 DLOG (" EQ Calibration " << i);
597625 // attach pricing engines to helpers
598626 Currency eqCcy = eqParametrizations[i]->currency ();
@@ -665,12 +693,26 @@ void CrossAssetModelBuilder::buildModel() const {
665693 QL_REQUIRE (dkParam, " Expected DK model data to have given a DK parameterisation." );
666694 const auto & builder = subBuilders_.at (CrossAssetModel::AssetType::INF).at (i);
667695 const auto & dkBuilder = boost::dynamic_pointer_cast<InfDkBuilder>(builder);
696+ if (!dkBuilder->requiresRecalibration () &&
697+ recalibratedCurrencies.find (infParameterizations[i]->currency ().code ()) ==
698+ recalibratedCurrencies.end ()) {
699+ DLOG (" Skipping inf dk calibration "
700+ << i << " since neither inf builder nor ir model in inf ccy were recalibrated." );
701+ continue ;
702+ }
668703 calibrateInflation (*dkData, i, dkBuilder->optionBasket (), dkParam);
669704 } else if (auto jyData = boost::dynamic_pointer_cast<InfJyData>(imData)) {
670705 auto jyParam = boost::dynamic_pointer_cast<InfJyParameterization>(infParameterizations[i]);
671706 QL_REQUIRE (jyParam, " Expected JY model data to have given a JY parameterisation." );
672707 const auto & builder = subBuilders_.at (CrossAssetModel::AssetType::INF).at (i);
673708 const auto & jyBuilder = boost::dynamic_pointer_cast<InfJyBuilder>(builder);
709+ if (!jyBuilder->requiresRecalibration () &&
710+ recalibratedCurrencies.find (infParameterizations[i]->currency ().code ()) ==
711+ recalibratedCurrencies.end ()) {
712+ DLOG (" Skipping inf jy calibration "
713+ << i << " since neither inf builder nor ir model in inf ccy were recalibrated." );
714+ continue ;
715+ }
674716 calibrateInflation (*jyData, i, jyBuilder, jyParam);
675717 } else {
676718 QL_FAIL (" CrossAssetModelBuilder expects either DK or JY inflation model data." );
0 commit comments