26#include <ql/math/solvers1d/brent.hpp>
55template <
class InterpolatorStrike,
class InterpolatorTime>
60 const QuantLib::Calendar& cal,
61 const QuantLib::BusinessDayConvention& bdc,
const QuantLib::DayCounter& dc,
62 const QuantLib::ext::shared_ptr<QuantLib::ZeroInflationIndex> index,
63 QuantLib::Handle<QuantLib::YieldTermStructure> yts,
64 const std::vector<QuantLib::Rate>& cStrikes,
const std::vector<QuantLib::Rate>& fStrikes,
65 const std::vector<QuantLib::Period>& cfMaturities,
const QuantLib::Matrix& cPrice,
66 const QuantLib::Matrix& fPrice,
const QuantLib::ext::shared_ptr<QuantExt::CPICapFloorEngine>& engine,
67 const bool quotedInstrumentsAreInterpolated =
false,
69 bool ignoreMissingPrices =
false,
70 bool lowerStrikeConstExtrap =
true,
bool upperStrikeConstExtrap =
true,
71 const QuantLib::VolatilityType& volType = QuantLib::ShiftedLognormal,
const double displacement = 0.0,
79 const QuantLib::Period& observationLag,
80 const QuantLib::Calendar& cal,
81 const QuantLib::BusinessDayConvention& bdc,
82 const QuantLib::DayCounter& dc,
83 const QuantLib::ext::shared_ptr<QuantLib::ZeroInflationIndex> index,
84 QuantLib::Handle<QuantLib::YieldTermStructure> yts,
85 const std::vector<QuantLib::Rate>& cStrikes,
const std::vector<QuantLib::Rate>& fStrikes,
86 const std::vector<QuantLib::Period>& cfMaturities,
const QuantLib::Matrix& cPrice,
87 const QuantLib::Matrix& fPrice,
88 const QuantLib::ext::shared_ptr<QuantExt::CPICapFloorEngine>& engine,
90 bool ignoreMissingPrices =
false,
91 bool lowerStrikeConstExtrap =
true,
bool upperStrikeConstExtrap =
true,
92 const QuantLib::VolatilityType& volType = QuantLib::ShiftedLognormal,
const double displacement = 0.0,
103 CPIVolatilitySurface::update();
104 QuantLib::LazyObject::update();
110 QuantLib::Real
minStrike()
const override;
112 QuantLib::Real
maxStrike()
const override;
114 QuantLib::Date
maxDate()
const override;
146 double atmGrowth(QuantLib::Period& tenor)
const;
148 double atmGrowth(
const QuantLib::Date& date)
const;
150 QuantLib::Real
atmStrike(
const QuantLib::Date& maturity,
151 const QuantLib::Period& obsLag = QuantLib::Period(-1, QuantLib::Days))
const override;
160 double priceFromPutCallParity(
double price,
bool isCapPrice,
double atm,
double strikeGrowth,
double df)
const;
163 double floorPrice(
double strike,
size_t tenorIdx,
double atm,
double strikeGrowth,
double df)
const;
166 double capPrice(
double strike,
size_t tenorIdx,
double atm,
double strikeGrowth,
double df)
const;
168 QuantLib::Volatility
volatilityImpl(QuantLib::Time length, QuantLib::Rate strike)
const override;
171 bool chooseFloor(QuantLib::Real strike, QuantLib::Real atmRate)
const;
174 double implyVol(
double strike,
const QuantLib::Date& maturity,
double price,
bool isFloor)
const;
177 QuantLib::ext::shared_ptr<QuantLib::ZeroInflationIndex>
index_;
178 QuantLib::Handle<QuantLib::YieldTermStructure>
yts_;
182 QuantLib::ext::shared_ptr<QuantExt::CPICapFloorEngine>
engine_;
200 mutable QuantLib::ext::shared_ptr<QuantExt::OptionInterpolator2d<InterpolatorStrike, InterpolatorTime>>
volSurface_;
205template <
class InterpolatorStrike,
class InterpolatorTime>
208 const QuantLib::Calendar& cal,
209 const QuantLib::BusinessDayConvention& bdc,
const QuantLib::DayCounter& dc,
210 const QuantLib::ext::shared_ptr<QuantLib::ZeroInflationIndex> index, QuantLib::Handle<QuantLib::YieldTermStructure> yts,
211 const std::vector<QuantLib::Rate>& cStrikes,
const std::vector<QuantLib::Rate>& fStrikes,
212 const std::vector<QuantLib::Period>& cfMaturities,
const QuantLib::Matrix& cPrice,
const QuantLib::Matrix& fPrice,
213 const QuantLib::ext::shared_ptr<QuantExt::CPICapFloorEngine>& engine,
const bool quotedInstrumentsAreInterpolated,
214 const QuantLib::Date& capFloorStartDate,
215 bool ignoreMissingPrices,
216 bool lowerStrikeConstExtrap,
bool upperStrikeConstExtrap,
const QuantLib::VolatilityType& volType,
217 const double displacement,
const QuantLib::Real& upperVolBound,
const QuantLib::Real& lowerVolBound,
218 const QuantLib::Real& solverTolerance)
220 capFloorStartDate, volType, displacement),
221 preference_(type), index_(index), yts_(yts), capStrikes_(cStrikes), floorStrikes_(fStrikes),
engine_(engine),
222 ignoreMissingPrices_(ignoreMissingPrices), lowerStrikeConstExtrap_(lowerStrikeConstExtrap),
223 upperStrikeConstExtrap_(upperStrikeConstExtrap), upperVolBound_(upperVolBound), lowerVolBound_(lowerVolBound),
224 solverTolerance_(solverTolerance), expiries_(cfMaturities), capPrices_(cPrice), floorPrices_(fPrice) {
227 QL_REQUIRE(!yts.empty(),
"DiscountCurve not provided");
228 QL_REQUIRE(engine,
"PricingEngine not provided");
229 QL_REQUIRE(index,
"PricingEngine not provided");
234QL_DEPRECATED_DISABLE_WARNING
235template <
class InterpolatorStrike,
class InterpolatorTime>
238 const QuantLib::Period& observationLag,
239 const QuantLib::Calendar& cal,
240 const QuantLib::BusinessDayConvention& bdc,
241 const QuantLib::DayCounter& dc,
242 const QuantLib::ext::shared_ptr<QuantLib::ZeroInflationIndex> index,
243 QuantLib::Handle<QuantLib::YieldTermStructure> yts,
244 const std::vector<QuantLib::Rate>& cStrikes,
const std::vector<QuantLib::Rate>& fStrikes,
245 const std::vector<QuantLib::Period>& cfMaturities,
const QuantLib::Matrix& cPrice,
const QuantLib::Matrix& fPrice,
246 const QuantLib::ext::shared_ptr<QuantExt::CPICapFloorEngine>& engine,
247 const QuantLib::Date& capFloorStartDate,
248 bool ignoreMissingPrices,
249 bool lowerStrikeConstExtrap,
bool upperStrikeConstExtrap,
250 const QuantLib::VolatilityType& volType,
const double displacement,
const QuantLib::Real& upperVolBound,
251 const QuantLib::Real& lowerVolBound,
const QuantLib::Real& solverTolerance)
253 capFloorStartDate, volType, displacement),
254 preference_(type), index_(index), yts_(yts), capStrikes_(cStrikes), floorStrikes_(fStrikes),
engine_(engine),
255 ignoreMissingPrices_(ignoreMissingPrices), lowerStrikeConstExtrap_(lowerStrikeConstExtrap),
256 upperStrikeConstExtrap_(upperStrikeConstExtrap), upperVolBound_(upperVolBound), lowerVolBound_(lowerVolBound),
257 solverTolerance_(solverTolerance), expiries_(cfMaturities), capPrices_(cPrice), floorPrices_(fPrice) {
260 QL_REQUIRE(!yts.empty(),
"DiscountCurve not provided");
261 QL_REQUIRE(engine,
"PricingEngine not provided");
262 QL_REQUIRE(index,
"PricingEngine not provided");
266QL_DEPRECATED_ENABLE_WARNING
268template <
class InterpolatorStrike,
class InterpolatorTime>
270 volData_ = QuantLib::Matrix(strikes_.size(), expiries_.size(), QuantLib::Null<QuantLib::Real>());
271 missingPrices_ = std::vector<std::vector<bool>>(strikes_.size(), std::vector<bool>(expiries_.size(),
false));
272 failedPrices_ = std::vector<std::vector<bool>>(strikes_.size(), std::vector<bool>(expiries_.size(),
false));
275 std::vector<QuantLib::Date> dates;
277 std::vector<double> vols;
279 for (QuantLib::Size tenorIdx = 0; tenorIdx < expiries_.size(); tenorIdx++) {
280 QuantLib::Date maturityDate = optionDateFromTenor(expiries_[tenorIdx]);
281 QuantLib::Date fixingDate =
283 double atm = atmGrowth(maturityDate);
284 double df = yts_->discount(fixingDate);
286 QuantLib::inflationYearFraction(frequency(), indexIsInterpolated(), dayCounter(), baseDate(), fixingDate);
287 fixingDates_.push_back(fixingDate);
288 double atmAvgRate = std::pow(atm, 1.0 / ttm) - 1.0;
289 for (QuantLib::Size strikeIdx = 0; strikeIdx < strikes_.size(); strikeIdx++) {
290 double strike = strikes_[strikeIdx];
291 double strikeGrowth = std::pow(1.0 + strike, ttm);
292 bool useFloor = chooseFloor(strike, atmAvgRate);
293 double vol = QuantLib::Null<QuantLib::Real>();
294 QuantLib::Real priceToMatch = useFloor ? floorPrice(strike, tenorIdx, atm, strikeGrowth, df)
295 : capPrice(strike, tenorIdx, atm, strikeGrowth, df);
296 if (priceToMatch != QuantLib::Null<QuantLib::Real>()) {
298 vol = implyVol(strike, maturityDate, priceToMatch, useFloor);
299 }
catch (
const std::exception&) {
301 vol = QuantLib::Null<QuantLib::Real>();
302 failedPrices_[strikeIdx][tenorIdx] =
true;
305 missingPrices_[strikeIdx][tenorIdx] =
true;
306 QL_REQUIRE(ignoreMissingPrices_,
"Missing price for cpi capfloor vol for tenor "
307 << expiries_[tenorIdx] <<
" and strike " << strike);
309 if (vol != QuantLib::Null<QuantLib::Real>()) {
310 dates.push_back(fixingDate);
317 volSurface_ = QuantLib::ext::make_shared<QuantExt::OptionInterpolator2d<InterpolatorStrike, InterpolatorTime>>(
318 referenceDate(), dayCounter(), dates,
strikes, vols, lowerStrikeConstExtrap_, upperStrikeConstExtrap_,
319 InterpolatorStrike(), InterpolatorTime(), baseDate());
321 for (QuantLib::Size strikeIdx = 0; strikeIdx < strikes_.size(); strikeIdx++) {
322 for (QuantLib::Size tenorIdx = 0; tenorIdx < expiries_.size(); tenorIdx++) {
323 volData_[strikeIdx][tenorIdx] = volSurface_->getValue(fixingDates_[tenorIdx], strikes_[strikeIdx]);
328template <
class InterpolatorStrike,
class InterpolatorTime>
330 QuantLib::Real atmRate)
const {
331 if (floorStrikes_.empty()) {
335 if (capStrikes_.empty()) {
339 if (preference_ ==
Floor) {
340 if (strike <= floorStrikes_.back())
346 if (preference_ ==
Cap) {
347 if (strike < capStrikes_.front())
357 if (strike <= floorStrikes_.back() && strike < capStrikes_.front())
360 else if (strike > floorStrikes_.back() && strike >= capStrikes_.front())
363 else if (strike <= floorStrikes_.back() && strike >= capStrikes_.front()) {
365 if (strike < atmRate)
371 }
else if (strike > floorStrikes_.back() && strike < capStrikes_.front()) {
373 if (strike < atmRate)
378 QL_FAIL(
"case not covered in StrippedCPIVolatilitySurface: strike="
379 << strike <<
" maxFloorStrike=" << floorStrikes_.back() <<
" minCapStrike=" << capStrikes_.front()
380 <<
" atm=" << atmRate);
385template <
class InterpolatorStrike,
class InterpolatorTime>
387 return strikes_.front() - QL_EPSILON;
390template <
class InterpolatorStrike,
class InterpolatorTime>
392 return strikes_.back() + QL_EPSILON;
395template <
class InterpolatorStrike,
class InterpolatorTime>
397 return optionDateFromTenor(expiries_.back());
400template <
class InterpolatorStrike,
class InterpolatorTime>
403 QuantLib::Rate strike)
const {
405 return volSurface_->getValue(length, strike);
408template <
class InterpolatorStrike,
class InterpolatorTime>
413template <
class InterpolatorStrike,
class InterpolatorTime>
415 return atmGrowth(optionDateFromTenor(tenor));
418template <
class InterpolatorStrike,
class InterpolatorTime>
423template <
class InterpolatorStrike,
class InterpolatorTime>
425 QL_REQUIRE(!expiries_.empty(),
"Need at least one tenor");
426 QL_REQUIRE(!floorStrikes_.empty() || !capStrikes_.empty(),
"cap and floor strikes can not be both empty");
427 QL_REQUIRE(capPrices_.rows() == capStrikes_.size() && capPrices_.columns() == (capStrikes_.empty() ? 0 : expiries_.size()),
428 "mismatch between cap price matrix dimension and number of strikes and tenors");
429 QL_REQUIRE(floorPrices_.rows() == floorStrikes_.size() &&
430 floorPrices_.columns() == (floorStrikes_.empty() ? 0 : expiries_.size()),
431 "mismatch between cap price matrix dimension and number of strikes and tenors");
434 for (
size_t tenorIdx = 0; tenorIdx < capPrices_.columns(); ++tenorIdx) {
435 double prevPrice = std::numeric_limits<double>::max();
436 for (
size_t strikeIdx = 0; strikeIdx < capPrices_.rows(); ++strikeIdx) {
437 double currentPrice = capPrices_[strikeIdx][tenorIdx];
438 QL_REQUIRE(ignoreMissingPrices_ || currentPrice != QuantLib::Null<QuantLib::Real>(),
439 "Input prices can not be null");
440 QL_REQUIRE(!QuantLib::close_enough(0.0, currentPrice) && currentPrice > 0.0,
"No zero cap prices allowd");
441 if (currentPrice != QuantLib::Null<Real>()) {
442 QL_REQUIRE(currentPrice <= prevPrice,
"Non decreasing cap prices");
443 prevPrice = currentPrice;
448 for (
size_t tenorIdx = 0; tenorIdx < floorPrices_.columns(); ++tenorIdx) {
449 double prevPrice = QL_EPSILON;
450 for (
size_t strikeIdx = 0; strikeIdx < floorPrices_.rows(); ++strikeIdx) {
451 double currentPrice = floorPrices_[strikeIdx][tenorIdx];
452 QL_REQUIRE(ignoreMissingPrices_ || currentPrice != QuantLib::Null<QuantLib::Real>(),
453 "Input prices can not be null");
454 QL_REQUIRE(!QuantLib::close_enough(0.0, currentPrice) && currentPrice > 0.0,
"No zero cap prices allowd");
455 if (currentPrice != QuantLib::Null<Real>()) {
456 QL_REQUIRE(currentPrice >= prevPrice,
"Non increasing floor prices");
457 prevPrice = currentPrice;
463template <
class InterpolatorStrike,
class InterpolatorTime>
466 std::set<double> uniqueStrikes(floorStrikes_.begin(), floorStrikes_.end());
467 uniqueStrikes.insert(capStrikes_.begin(), capStrikes_.end());
468 std::unique_copy(uniqueStrikes.begin(), uniqueStrikes.end(), std::back_inserter(strikes_),
469 [](
double a,
double b) { return QuantLib::close_enough(a, b); });
473template <
class InterpolatorStrike,
class InterpolatorTime>
475 double price,
bool isCapPrice,
double atm,
double strikeGrowth,
double df)
const {
477 return price + atm - strikeGrowth * df;
479 return price + strikeGrowth * df - atm;
484template <
class InterpolatorStrike,
class InterpolatorTime>
486 double atm,
double strikeGrowth,
488 auto close_enough = [&strike](
const double& x) {
return QuantLib::close_enough(strike, x); };
489 auto itCap = std::find_if(capStrikes_.begin(), capStrikes_.end(),
close_enough);
490 auto itFloor = std::find_if(floorStrikes_.begin(), floorStrikes_.end(),
close_enough);
491 if (itFloor != floorStrikes_.end()) {
492 size_t floorPriceIdx = std::distance(floorStrikes_.begin(), itFloor);
493 return floorPrices_[floorPriceIdx][tenorIdx];
494 }
else if (itCap != capStrikes_.end()) {
495 size_t capPriceIdx = std::distance(capStrikes_.begin(), itCap);
496 double capPrice = capPrices_[capPriceIdx][tenorIdx];
497 return priceFromPutCallParity(capPrice,
true, atm, strikeGrowth, df);
499 return QuantLib::Null<double>();
504template <
class InterpolatorStrike,
class InterpolatorTime>
506 double atm,
double strikeGrowth,
508 auto close_enough = [&strike](
const double& x) {
return QuantLib::close_enough(strike, x); };
509 auto itCap = std::find_if(capStrikes_.begin(), capStrikes_.end(),
close_enough);
510 auto itFloor = std::find_if(floorStrikes_.begin(), floorStrikes_.end(),
close_enough);
511 if (itCap != capStrikes_.end()) {
512 size_t capPriceIdx = std::distance(capStrikes_.begin(), itCap);
513 return capPrices_[capPriceIdx][tenorIdx];
514 }
else if (itFloor != floorStrikes_.end()) {
515 size_t floorPriceIdx = std::distance(floorStrikes_.begin(), itFloor);
516 double floorPrice = floorPrices_[floorPriceIdx][tenorIdx];
517 return priceFromPutCallParity(floorPrice,
false, atm, strikeGrowth, df);
519 return QuantLib::Null<double>();
523template <
class InterpolatorStrike,
class InterpolatorTime>
525 const QuantLib::Date& maturity,
526 double price,
bool isFloor)
const {
527 QuantLib::Date startDate = capFloorStartDate();
528 QuantLib::Calendar cal = calendar();
529 auto bdc = businessDayConvention();
530 auto dc = dayCounter();
532 auto freq = frequency();
533 auto obsLag = observationLag();
535 QuantLib::CPICapFloor capFloor(isFloor ? QuantLib::Option::Put : QuantLib::Option::Call,
537 capFloorStartDate(), baseCPI(), maturity, calendar(), businessDayConvention(),
538 calendar(), businessDayConvention(), strike,
539 index_, observationLag(),
540 indexIsInterpolated() ? QuantLib::CPI::Linear : QuantLib::CPI::Flat);
542 QuantLib::ext::shared_ptr<QuantExt::CPICapFloorEngine> engine =
engine_;
544 bool interpolated = indexIsInterpolated();
545 capFloor.setPricingEngine(engine);
547 auto targetFunction = [&engine, &cal, &dc, &bdc, &startDate, &obsLag, &freq, &price,
548 &capFloor, &interpolated](
const double& guess) {
549 QuantLib::ext::shared_ptr<QuantExt::ConstantCPIVolatility> vol = QuantLib::ext::make_shared<QuantExt::ConstantCPIVolatility>(
550 guess, 0, cal, bdc, dc, obsLag, freq, interpolated, startDate);
552 engine->setVolatility(QuantLib::Handle<QuantLib::CPIVolatilitySurface>(vol));
554 QuantLib::Real npv = capFloor.NPV();
557 QuantLib::Brent solver;
558 QuantLib::Real guess = (upperVolBound_ + lowerVolBound_) / 2.0;
559 return solver.solve(targetFunction, solverTolerance_, guess, lowerVolBound_, upperVolBound_);
562template <
class InterpolatorStrike,
class InterpolatorTime>
565 const QuantLib::Period& obsLag)
const {
566 QuantLib::Period lag = obsLag == -1 * QuantLib::Days ? observationLag() : obsLag;
569 double atm = forwardCPI / baseCPI();
571 QuantLib::inflationYearFraction(frequency(), indexIsInterpolated(), dayCounter(), baseDate(), fixingDate);
572 return std::pow(atm, 1.0 / ttm) - 1.0;
QuantLib::ext::shared_ptr< PricingEngine > engine_
Stripped zero inflation volatility structure.
bool ignoreMissingPrices_
void performCalculations() const override
QuantLib::Matrix volData_
virtual void initializeStrikes() const
bool upperStrikeConstExtrap_
double priceFromPutCallParity(double price, bool isCapPrice, double atm, double strikeGrowth, double df) const
Computes a cap price from a floor price using the put-call parity and vice-versa.
const std::vector< QuantLib::Period > & maturities()
Returns the tenors.
const std::vector< QuantLib::Real > & strikes()
Returns the strikes.
const std::vector< std::vector< bool > > & pricesFailedToConvert() const
std::vector< std::vector< bool > > failedPrices_
QuantLib::Matrix capPrices_
QuantLib::Matrix floorPrices_
QuantLib::Real minStrike() const override
the minimum strike for which the term structure can return vols
QuantLib::Real solverTolerance_
std::vector< QuantLib::Rate > strikes_
virtual void validateInputParameters() const
QuantLib::ext::shared_ptr< QuantExt::OptionInterpolator2d< InterpolatorStrike, InterpolatorTime > > volSurface_
const QuantLib::Matrix & volData() const
bool chooseFloor(QuantLib::Real strike, QuantLib::Real atmRate) const
std::vector< double > capStrikes_
QuantLib::Real upperVolBound_
double atmGrowth(QuantLib::Period &tenor) const
QuantLib::Real maxStrike() const override
the maximum strike for which the term structure can return vols
QuantLib::Real lowerVolBound_
const std::vector< std::vector< bool > > & missingValues() const
PriceQuotePreference preference_
QuantLib::Date maxDate() const override
maximum date for which the term structure can return vols
QuantLib::ext::shared_ptr< QuantLib::ZeroInflationIndex > index_
std::vector< QuantLib::Date > fixingDates_
double capPrice(double strike, size_t tenorIdx, double atm, double strikeGrowth, double df) const
Returns cap price for strike level (average annual inflation) and maturity index.
double baseCPI() const
CPI fixing on the baseDate of the surface.
CPIPriceVolatilitySurface(PriceQuotePreference type, const QuantLib::Period &observationLag, const QuantLib::Calendar &cal, const QuantLib::BusinessDayConvention &bdc, const QuantLib::DayCounter &dc, const QuantLib::ext::shared_ptr< QuantLib::ZeroInflationIndex > index, QuantLib::Handle< QuantLib::YieldTermStructure > yts, const std::vector< QuantLib::Rate > &cStrikes, const std::vector< QuantLib::Rate > &fStrikes, const std::vector< QuantLib::Period > &cfMaturities, const QuantLib::Matrix &cPrice, const QuantLib::Matrix &fPrice, const QuantLib::ext::shared_ptr< QuantExt::CPICapFloorEngine > &engine, const bool quotedInstrumentsAreInterpolated=false, const QuantLib::Date &capFloorStartDate=QuantLib::Date(), bool ignoreMissingPrices=false, bool lowerStrikeConstExtrap=true, bool upperStrikeConstExtrap=true, const QuantLib::VolatilityType &volType=QuantLib::ShiftedLognormal, const double displacement=0.0, const QuantLib::Real &upperVolBound=CPIPriceVolatilitySurfaceDefaultValues::upperVolBound, const QuantLib::Real &lowerVolBound=CPIPriceVolatilitySurfaceDefaultValues::lowerVolBound, const QuantLib::Real &solverTolerance=CPIPriceVolatilitySurfaceDefaultValues::solverTolerance)
QuantLib::ext::shared_ptr< QuantExt::CPICapFloorEngine > engine_
QuantLib::Handle< QuantLib::YieldTermStructure > yts_
double floorPrice(double strike, size_t tenorIdx, double atm, double strikeGrowth, double df) const
Returns floor price for strike level (average annual inflation) and maturity index.
std::vector< double > floorStrikes_
bool lowerStrikeConstExtrap_
std::vector< std::vector< bool > > missingPrices_
std::vector< QuantLib::Period > expiries_
QuantLib::Volatility volatilityImpl(QuantLib::Time length, QuantLib::Rate strike) const override
double implyVol(double strike, const QuantLib::Date &maturity, double price, bool isFloor) const
QuantLib::Real atmStrike(const QuantLib::Date &maturity, const QuantLib::Period &obsLag=QuantLib::Period(-1, QuantLib::Days)) const override
double displacement() const
Returns the displacement for lognormal volatilities.
QuantLib::Date capFloorStartDate() const
Constant CPI Volatility Surface.
CPI cap/floor engine using the Black pricing formula and interpreting the volatility data as lognorma...
interpolated correlation term structure
some inflation related utilities.
QuantLib::Date fixingDate(const QuantLib::Date &d, const QuantLib::Period obsLag, const QuantLib::Frequency freq, bool interpolated)
QuantLib::Rate cpiFixing(const QuantLib::ext::shared_ptr< QuantLib::ZeroInflationIndex > &index, const QuantLib::Date &maturity, const QuantLib::Period &obsLag, bool interpolated)
Computes a CPI fixing giving an zeroIndex, with interpolation if needed.
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
zero inflation volatility structure implied from a cpi cap/floor price surface
static constexpr QuantLib::Real upperVolBound
static constexpr QuantLib::Real lowerVolBound
static constexpr QuantLib::Real solverTolerance