Skip to content

Commit

Permalink
More interpolation passed around
Browse files Browse the repository at this point in the history
  • Loading branch information
lballabio committed Sep 20, 2024
1 parent 322aa3a commit 8cf8518
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 82 deletions.
21 changes: 19 additions & 2 deletions ql/experimental/inflation/yoycapfloortermpricesurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace QuantLib {
Natural fixingDays,
const Period& lag,
const ext::shared_ptr<YoYInflationIndex>& yii,
Rate baseRate,
CPI::InterpolationType interpolation,
Handle<YieldTermStructure> nominal,
const DayCounter& dc,
const Calendar& cal,
Expand All @@ -39,7 +39,7 @@ namespace QuantLib {
: TermStructure(0, cal, dc),
fixingDays_(fixingDays), bdc_(bdc), yoyIndex_(yii), observationLag_(lag), nominalTS_(std::move(nominal)),
cStrikes_(cStrikes), fStrikes_(fStrikes), cfMaturities_(cfMaturities), cPrice_(cPrice),
fPrice_(fPrice), indexIsInterpolated_(yii->interpolated()) {
fPrice_(fPrice), indexIsInterpolated_(detail::CPI::isInterpolated(interpolation, yoyIndex_)) {

// data consistency checking, enough data?
QL_REQUIRE(fStrikes_.size() > 1, "not enough floor strikes");
Expand Down Expand Up @@ -100,6 +100,23 @@ namespace QuantLib {
"cfStrikes not increasing");
}

YoYCapFloorTermPriceSurface::YoYCapFloorTermPriceSurface(
Natural fixingDays,
const Period& yyLag,
const ext::shared_ptr<YoYInflationIndex>& yii,
Rate baseRate,
Handle<YieldTermStructure> nominal,
const DayCounter& dc,
const Calendar& cal,
const BusinessDayConvention& bdc,
const std::vector<Rate>& cStrikes,
const std::vector<Rate>& fStrikes,
const std::vector<Period>& cfMaturities,
const Matrix& cPrice,
const Matrix& fPrice)
: YoYCapFloorTermPriceSurface(fixingDays, yyLag, yii, CPI::AsIndex, nominal, dc, cal, bdc,
cStrikes, fStrikes, cfMaturities, cPrice, fPrice) {}

Date YoYCapFloorTermPriceSurface::yoyOptionDateFromTenor(const Period& p) const
{
return referenceDate() + p;
Expand Down
76 changes: 70 additions & 6 deletions ql/experimental/inflation/yoycapfloortermpricesurface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ namespace QuantLib {
*/
class YoYCapFloorTermPriceSurface : public TermStructure {
public:
YoYCapFloorTermPriceSurface(Natural fixingDays,
const Period& yyLag,
const ext::shared_ptr<YoYInflationIndex>& yii,
CPI::InterpolationType interpolation,
Handle<YieldTermStructure> nominal,
const DayCounter& dc,
const Calendar& cal,
const BusinessDayConvention& bdc,
const std::vector<Rate>& cStrikes,
const std::vector<Rate>& fStrikes,
const std::vector<Period>& cfMaturities,
const Matrix& cPrice,
const Matrix& fPrice);

/*! \deprecated Use the overload that passes an interpolation type instead.
Deprecated in version 1.36.
*/
[[deprecated("Use the overload that passes an interpolation type instead")]]
YoYCapFloorTermPriceSurface(Natural fixingDays,
const Period& yyLag,
const ext::shared_ptr<YoYInflationIndex>& yii,
Expand Down Expand Up @@ -149,6 +167,27 @@ namespace QuantLib {
class InterpolatedYoYCapFloorTermPriceSurface
: public YoYCapFloorTermPriceSurface {
public:
InterpolatedYoYCapFloorTermPriceSurface(
Natural fixingDays,
const Period &yyLag, // observation lag
const ext::shared_ptr<YoYInflationIndex>& yii,
CPI::InterpolationType interpolation,
const Handle<YieldTermStructure> &nominal,
const DayCounter &dc,
const Calendar &cal,
const BusinessDayConvention &bdc,
const std::vector<Rate> &cStrikes,
const std::vector<Rate> &fStrikes,
const std::vector<Period> &cfMaturities,
const Matrix &cPrice,
const Matrix &fPrice,
const Interpolator2D &interpolator2d = Interpolator2D(),
const Interpolator1D &interpolator1d = Interpolator1D());

/*! \deprecated Use the overload that passes an interpolation type instead.
Deprecated in version 1.36.
*/
[[deprecated("Use the overload that passes an interpolation type instead")]]
InterpolatedYoYCapFloorTermPriceSurface(
Natural fixingDays,
const Period &yyLag, // observation lag
Expand Down Expand Up @@ -257,7 +296,7 @@ namespace QuantLib {
Natural fixingDays,
const Period &yyLag,
const ext::shared_ptr<YoYInflationIndex>& yii,
Rate baseRate,
CPI::InterpolationType interpolation,
const Handle<YieldTermStructure> &nominal,
const DayCounter &dc,
const Calendar &cal,
Expand All @@ -270,13 +309,37 @@ namespace QuantLib {
const I2D &interpolator2d,
const I1D &interpolator1d)
: YoYCapFloorTermPriceSurface(fixingDays, yyLag, yii,
baseRate, nominal, dc, cal, bdc,
interpolation, nominal, dc, cal, bdc,
cStrikes, fStrikes, cfMaturities,
cPrice, fPrice),
interpolator2d_(interpolator2d), interpolator1d_(interpolator1d) {
performCalculations();
}

template<class I2D, class I1D>
InterpolatedYoYCapFloorTermPriceSurface<I2D,I1D>::
InterpolatedYoYCapFloorTermPriceSurface(
Natural fixingDays,
const Period &yyLag,
const ext::shared_ptr<YoYInflationIndex>& yii,
Rate baseRate,
const Handle<YieldTermStructure> &nominal,
const DayCounter &dc,
const Calendar &cal,
const BusinessDayConvention &bdc,
const std::vector<Rate> &cStrikes,
const std::vector<Rate> &fStrikes,
const std::vector<Period> &cfMaturities,
const Matrix &cPrice,
const Matrix &fPrice,
const I2D &interpolator2d,
const I1D &interpolator1d)
: InterpolatedYoYCapFloorTermPriceSurface(fixingDays, yyLag, yii, CPI::AsIndex,
nominal, dc, cal, bdc,
cStrikes, fStrikes, cfMaturities,
cPrice, fPrice,
interpolator2d, interpolator1d) {}

#endif

template<class I2D, class I1D>
Expand Down Expand Up @@ -532,12 +595,13 @@ namespace QuantLib {
Date maturity = nominalTS_->referenceDate() + Period(i,Years);
Handle<Quote> quote(ext::shared_ptr<Quote>(
new SimpleQuote( atmYoYSwapRate( maturity ) )));//!
ext::shared_ptr<BootstrapHelper<YoYInflationTermStructure> >
anInstrument(
new YearOnYearInflationSwapHelper(
auto anInstrument =
ext::make_shared<YearOnYearInflationSwapHelper>(
quote, observationLag(), maturity,
calendar(), bdc_, dayCounter(),
yoyIndex(), nominalTS_));
yoyIndex(),
this->indexIsInterpolated() ? CPI::Linear: CPI::Flat,
nominalTS_);
YYhelpers.push_back (anInstrument);
}

Expand Down
19 changes: 19 additions & 0 deletions ql/indexes/inflationindex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,23 @@ namespace QuantLib {
}
}

CPI::InterpolationType
detail::CPI::effectiveInterpolationType(const QuantLib::CPI::InterpolationType& type,
const ext::shared_ptr<YoYInflationIndex>& index) {
if (type == QuantLib::CPI::AsIndex) {
return index->interpolated() ? QuantLib::CPI::Linear : QuantLib::CPI::Flat;
} else {
return type;
}
}

bool detail::CPI::isInterpolated(const QuantLib::CPI::InterpolationType& type) {
return detail::CPI::effectiveInterpolationType(type) == QuantLib::CPI::Linear;
}

bool detail::CPI::isInterpolated(const QuantLib::CPI::InterpolationType& type,
const ext::shared_ptr<YoYInflationIndex>& index) {
return detail::CPI::effectiveInterpolationType(type, index) == QuantLib::CPI::Linear;
}

}
28 changes: 16 additions & 12 deletions ql/indexes/inflationindex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,16 +249,24 @@ namespace QuantLib {


namespace detail::CPI {
// Returns either CPI::Flat or CPI::Linear depending on the combination of index and
// CPI::InterpolationType.
QuantLib::CPI::InterpolationType effectiveInterpolationType(
const QuantLib::CPI::InterpolationType& type = QuantLib::CPI::AsIndex);

// Returns either CPI::Flat or CPI::Linear depending on the combination of index and
// CPI::InterpolationType.
QuantLib::CPI::InterpolationType
effectiveInterpolationType(const QuantLib::CPI::InterpolationType& type);

// checks whether the combination of index and CPI::InterpolationType results
// effectively in CPI::Linear
bool isInterpolated(const QuantLib::CPI::InterpolationType& type = QuantLib::CPI::AsIndex);
}
QuantLib::CPI::InterpolationType
effectiveInterpolationType(const QuantLib::CPI::InterpolationType& type,
const ext::shared_ptr<YoYInflationIndex>& index);

// checks whether the combination of index and CPI::InterpolationType results
// effectively in CPI::Linear
bool isInterpolated(const QuantLib::CPI::InterpolationType& type);

bool isInterpolated(const QuantLib::CPI::InterpolationType& type,
const ext::shared_ptr<YoYInflationIndex>& index);

}


// inline
Expand Down Expand Up @@ -313,10 +321,6 @@ namespace QuantLib {
return yoyInflation_;
}

inline bool detail::CPI::isInterpolated(const QuantLib::CPI::InterpolationType& type) {
return detail::CPI::effectiveInterpolationType(type) == QuantLib::CPI::Linear;
}

}

#endif
68 changes: 38 additions & 30 deletions ql/termstructures/inflation/inflationhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,23 @@ namespace QuantLib {
observationInterpolation_(observationInterpolation),
nominalTermStructure_(std::move(nominalTermStructure)) {

std::pair<Date, Date> limStart = inflationPeriod(maturity_ - swapObsLag_, zii_->frequency());
std::pair<Date, Date> interpolationPeriod = inflationPeriod(maturity, zii_->frequency());
auto fixingPeriod = inflationPeriod(maturity_ - swapObsLag_, zii_->frequency());
auto interpolationPeriod = inflationPeriod(maturity, zii_->frequency());

if ((detail::CPI::effectiveInterpolationType(observationInterpolation_) == CPI::Linear) &&
(maturity > interpolationPeriod.first)) {
if (detail::CPI::isInterpolated(observationInterpolation_) && maturity > interpolationPeriod.first) {
// if interpolated, we need to cover the end of the interpolation period
earliestDate_ = limStart.first;
latestDate_ = limStart.second + 1;
earliestDate_ = fixingPeriod.first;
latestDate_ = fixingPeriod.second + 1;
} else {
// if not interpolated, the date of the initial fixing is enough
earliestDate_ = limStart.first;
latestDate_ = limStart.first;
earliestDate_ = fixingPeriod.first;
latestDate_ = fixingPeriod.first;
}

// check that the observation lag of the swap
// is compatible with the availability lag of the index AND
// it's interpolation (assuming the start day is spot)
if (detail::CPI::effectiveInterpolationType(observationInterpolation_) == CPI::Linear) {
if (detail::CPI::isInterpolated(observationInterpolation_)) {
Period pShift(zii_->frequency());
QL_REQUIRE(swapObsLag_ - pShift >= zii_->availabilityLag(),
"inconsistency between swap observation lag "
Expand Down Expand Up @@ -117,43 +116,53 @@ namespace QuantLib {
BusinessDayConvention paymentConvention,
DayCounter dayCounter,
ext::shared_ptr<YoYInflationIndex> yii,
CPI::InterpolationType interpolation,
Handle<YieldTermStructure> nominalTermStructure)
: BootstrapHelper<YoYInflationTermStructure>(quote), swapObsLag_(swapObsLag),
maturity_(maturity), calendar_(std::move(calendar)), paymentConvention_(paymentConvention),
dayCounter_(std::move(dayCounter)), yii_(std::move(yii)),
dayCounter_(std::move(dayCounter)), yii_(std::move(yii)), interpolation_(interpolation),
nominalTermStructure_(std::move(nominalTermStructure)) {

if (yii_->interpolated()) {
// if interpolated then simple
earliestDate_ = maturity_ - swapObsLag_;
latestDate_ = maturity_ - swapObsLag_;
auto fixingPeriod = inflationPeriod(maturity_ - swapObsLag_, yii_->frequency());
auto interpolationPeriod = inflationPeriod(maturity, yii_->frequency());

if (detail::CPI::isInterpolated(interpolation_, yii_) && maturity > interpolationPeriod.first) {
// if interpolated, we need to cover the end of the interpolation period
earliestDate_ = fixingPeriod.first;
latestDate_ = fixingPeriod.second + 1;
} else {
// but if NOT interpolated then the value is valid
// for every day in an inflation period so you actually
// get an extended validity, however for curve building
// just put the first date because using that convention
// for the base date throughout
std::pair<Date, Date> limStart =
inflationPeriod(maturity_ - swapObsLag_, yii_->frequency());
earliestDate_ = limStart.first;
latestDate_ = limStart.first;
// if not interpolated, the date of the initial fixing is enough
earliestDate_ = fixingPeriod.first;
latestDate_ = fixingPeriod.first;
}

// check that the observation lag of the swap
// is compatible with the availability lag of the index AND
// it's interpolation (assuming the start day is spot)
if (yii_->interpolated()) {
// its interpolation (assuming the start day is spot)
if (detail::CPI::isInterpolated(interpolation_, yii_)) {
Period pShift(yii_->frequency());
QL_REQUIRE(swapObsLag_ - pShift >= yii_->availabilityLag(),
"inconsistency between swap observation lag "
<< swapObsLag_ << ", index period " << pShift << " and index availability "
<< yii_->availabilityLag() << ": need (obsLag-index period) >= availLag");
<< swapObsLag_ << ", index period " << pShift << " and index availability "
<< yii_->availabilityLag() << ": need (obsLag-index period) >= availLag");
}

registerWith(Settings::instance().evaluationDate());
registerWith(nominalTermStructure_);
}

YearOnYearInflationSwapHelper::YearOnYearInflationSwapHelper(
const Handle<Quote>& quote,
const Period& swapObsLag,
const Date& maturity,
Calendar calendar,
BusinessDayConvention paymentConvention,
DayCounter dayCounter,
ext::shared_ptr<YoYInflationIndex> yii,
Handle<YieldTermStructure> nominalTermStructure)
: YearOnYearInflationSwapHelper(quote, swapObsLag, maturity, calendar, paymentConvention,
dayCounter, yii, CPI::AsIndex, nominalTermStructure) {}


Real YearOnYearInflationSwapHelper::impliedQuote() const {
yyiis_->deepUpdate();
Expand Down Expand Up @@ -194,9 +203,8 @@ namespace QuantLib {
Real nominal = 1000000.0; // has to be something but doesn't matter what
yyiis_ = ext::make_shared<YearOnYearInflationSwap>(
Swap::Payer, nominal, fixedSchedule, fixedRate, dayCounter_,
yoySchedule, new_yii, swapObsLag_, spread, dayCounter_,
calendar_, // inflation index does not have a calendar
paymentConvention_);
yoySchedule, new_yii, swapObsLag_, interpolation_,
spread, dayCounter_, calendar_, paymentConvention_);

// The instrument takes a standard discounting swap engine.
// The inflation-related work is done by the coupons.
Expand Down
15 changes: 15 additions & 0 deletions ql/termstructures/inflation/inflationhelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ namespace QuantLib {
//! Year-on-year inflation-swap bootstrap helper
class YearOnYearInflationSwapHelper : public BootstrapHelper<YoYInflationTermStructure> {
public:
YearOnYearInflationSwapHelper(const Handle<Quote>& quote,
const Period& swapObsLag_,
const Date& maturity,
Calendar calendar,
BusinessDayConvention paymentConvention,
DayCounter dayCounter,
ext::shared_ptr<YoYInflationIndex> yii,
CPI::InterpolationType interpolation,
Handle<YieldTermStructure> nominalTermStructure);

/*! \deprecated Use the overload that passes an interpolation type instead.
Deprecated in version 1.36.
*/
[[deprecated("Use the overload that passes an interpolation type instead")]]
YearOnYearInflationSwapHelper(const Handle<Quote>& quote,
const Period& swapObsLag_,
const Date& maturity,
Expand All @@ -84,6 +98,7 @@ namespace QuantLib {
BusinessDayConvention paymentConvention_;
DayCounter dayCounter_;
ext::shared_ptr<YoYInflationIndex> yii_;
CPI::InterpolationType interpolation_;
ext::shared_ptr<YearOnYearInflationSwap> yyiis_;
Handle<YieldTermStructure> nominalTermStructure_;
};
Expand Down
4 changes: 2 additions & 2 deletions test-suite/inflation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ BOOST_AUTO_TEST_CASE(testYYTermStructure) {
// now build the helpers ...
auto makeHelper = [&](const Handle<Quote>& quote, const Date& maturity) {
return ext::make_shared<YearOnYearInflationSwapHelper>(
quote, observationLag, maturity, calendar, bdc, dc, iir,
quote, observationLag, maturity, calendar, bdc, dc, iir, CPI::AsIndex,
Handle<YieldTermStructure>(nominalTS));
};
auto helpers = makeHelpers<YoYInflationTermStructure>(yyData, makeHelper);
Expand Down Expand Up @@ -1278,7 +1278,7 @@ BOOST_AUTO_TEST_CASE(testYYTermStructureWithLag) {
// now build the helpers ...
auto makeHelper = [&](const Handle<Quote>& quote, const Date& maturity) {
return ext::make_shared<YearOnYearInflationSwapHelper>(
quote, observationLag, maturity, calendar, bdc, dc, iir,
quote, observationLag, maturity, calendar, bdc, dc, iir, CPI::AsIndex,
Handle<YieldTermStructure>(nominalTS));
};
auto helpers = makeHelpers<YoYInflationTermStructure>(yyData, makeHelper);
Expand Down
Loading

0 comments on commit 8cf8518

Please sign in to comment.