276 {
277
278
279 QL_REQUIRE(!
data_->calibrationBaskets().empty(),
"No calibration basket provided in inflation DK model data.");
280 const CalibrationBasket& cb =
data_->calibrationBaskets()[0];
281 const auto& ci = cb.instruments();
282
283 QL_REQUIRE(ci.size() ==
optionActive_.size(),
"Expected the option active vector size to equal the "
284 << "number of calibration instruments");
286
288 Date lastRefCalDate = Date::minDate();
289 std::vector<Date> referenceCalibrationDates;
292
293 QuantLib::ext::shared_ptr<QuantExt::CPICapFloorEngine> engine;
294
296 if (isLogNormalVol) {
297 engine = QuantLib::ext::make_shared<QuantExt::CPIBlackCapFloorEngine>(
rateCurve_,
infVol_);
298 } else {
299 engine = QuantLib::ext::make_shared<QuantExt::CPIBachelierCapFloorEngine>(
rateCurve_,
infVol_);
300 }
301
303 Date baseDate =
inflationIndex_->zeroInflationTermStructure()->baseDate();
305 BusinessDayConvention bdc =
infVol_->businessDayConvention();
306 Period lag =
infVol_->observationLag();
308 Date startDate = Settings::instance().evaluationDate();
309 bool useInterpolatedCPIFixings =
infVol_->indexIsInterpolated();
310 Real nominal = 1.0;
311 vector<Time> expiryTimes;
313 for (Size j = 0; j < ci.size(); j++) {
314
315 auto cpiCapFloor = QuantLib::ext::dynamic_pointer_cast<CpiCapFloor>(ci[j]);
316 QL_REQUIRE(cpiCapFloor, "Expected CpiCapFloor calibration instruments in DK inflation model data.");
317
319
320
321 auto refCalDate =
322 std::lower_bound(referenceCalibrationDates.begin(), referenceCalibrationDates.end(), expiryDate);
323 if (refCalDate == referenceCalibrationDates.end() || *refCalDate > lastRefCalDate) {
325 Option::Type capfloor = cpiCapFloor->type() == CapFloor::Cap ? Option::Call : Option::Put;
326 QuantLib::ext::shared_ptr<CPICapFloor> cf =
327 QuantLib::ext::make_shared<CPICapFloor>(capfloor, nominal, startDate, baseCPI, expiryDate, fixCalendar, bdc,
329 cf->setPricingEngine(engine);
330 Real tte = inflationYearFraction(
inflationIndex_->frequency(), useInterpolatedCPIFixings,
332 cf->fixingDate());
333
334 Real tteFromBase =
infVol_->timeFromBase(expiryDate);
335
336 Real marketPrem;
338 marketPrem = 0.1;
339 else if (tte <= 0 || tteFromBase <= 0)
340 marketPrem = 0.00;
341 else
342 marketPrem = cf->NPV();
343
344 QuantLib::ext::shared_ptr<QuantExt::CpiCapFloorHelper>
helper =
345 QuantLib::ext::make_shared<QuantExt::CpiCapFloorHelper>(capfloor, baseCPI, expiryDate, fixCalendar, bdc,
346 fixCalendar, bdc, strikeValue, hIndex, lag,
347 marketPrem);
348
349
350 if (marketPrem > 0.0 && tte > 0 && tteFromBase > 0 &&
351 std::find_if(expiryTimes.begin(), expiryTimes.end(),
352 [tte](Real x) { return QuantLib::close_enough(x, tte); }) == expiryTimes.end()) {
354 helper->performCalculations();
355 expiryTimes.push_back(tte);
356 DLOG(
"Added InflationOptionHelper index="
357 <<
data_->index() <<
", type=" << (capfloor == Option::Type::Call ?
"Cap" :
"Floor") <<
", expiry="
358 << QuantLib::io::iso_date(expiryDate) << ", baseCPI=" << baseCPI << ", strike=" << strikeValue
359 << ", lag=" << lag << ", marketPremium=" << marketPrem << ", tte=" << tte);
361 if (refCalDate != referenceCalibrationDates.end())
362 lastRefCalDate = *refCalDate;
363 } else {
364 if (
data_->ignoreDuplicateCalibrationExpiryTimes()) {
365 DLOG(
"Skipped InflationOptionHelper index="
366 <<
data_->index() <<
", type=" << (capfloor == Option::Type::Call ?
"Cap" :
"Floor")
367 << ", expiry=" << QuantLib::io::iso_date(expiryDate) << ", baseCPI=" << baseCPI
368 << ", strike=" << strikeValue << ", lag=" << lag << ", marketPremium=" << marketPrem
369 << ", tte=" << tte << " since we already have a helper with the same expiry time.");
370 } else {
371 QL_FAIL("InfDkBuilder: a CPI cap floor calibration instrument with the expiry time, "
372 << tte << ", was already added.");
373 }
374 }
375 }
376 }
377
378 std::sort(expiryTimes.begin(), expiryTimes.end());
379 auto itExpiryTime = unique(expiryTimes.begin(), expiryTimes.end());
380 expiryTimes.resize(distance(expiryTimes.begin(), itExpiryTime));
381
383 for (Size j = 0; j < expiryTimes.size(); j++)
385}
Real optionStrikeValue(const Size j) const
bool isCPIVolSurfaceLogNormal(const boost::shared_ptr< QuantLib::CPIVolatilitySurface > &surface)
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper