Skip to content

Commit

Permalink
Manage interpolation of year-on-year inflation index inside coupons (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lballabio authored Sep 22, 2024
2 parents 4491778 + 8cf8518 commit b2ef988
Show file tree
Hide file tree
Showing 28 changed files with 746 additions and 233 deletions.
1 change: 1 addition & 0 deletions ql/cashflows/capflooredinflationcoupon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace QuantLib {
underlying->fixingDays(),
underlying->yoyIndex(),
underlying->observationLag(),
underlying->interpolation(),
underlying->dayCounter(),
underlying->gearing(),
underlying->spread(),
Expand Down
29 changes: 27 additions & 2 deletions ql/cashflows/capflooredinflationcoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ namespace QuantLib {
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& index,
const Period& observationLag,
const CPI::InterpolationType interpolation,
const DayCounter& dayCounter,
Real gearing = 1.0,
Spread spread = 0.0,
Expand All @@ -87,12 +88,36 @@ namespace QuantLib {
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date())
: YoYInflationCoupon(paymentDate, nominal, startDate, endDate,
fixingDays, index, observationLag, dayCounter,
gearing, spread, refPeriodStart, refPeriodEnd),
fixingDays, index, observationLag, interpolation,
dayCounter, gearing, spread,
refPeriodStart, refPeriodEnd),
isFloored_(false), isCapped_(false) {
setCommon(cap, floor);
}

/*! \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")]]
CappedFlooredYoYInflationCoupon(const Date& paymentDate,
Real nominal,
const Date& startDate,
const Date& endDate,
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& index,
const Period& observationLag,
const DayCounter& dayCounter,
Real gearing = 1.0,
Spread spread = 0.0,
const Rate cap = Null<Rate>(),
const Rate floor = Null<Rate>(),
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date())
: CappedFlooredYoYInflationCoupon(paymentDate, nominal, startDate, endDate,
fixingDays, index, observationLag, CPI::AsIndex,
dayCounter, gearing, spread, cap, floor,
refPeriodStart, refPeriodEnd) {}

//! \name augmented Coupon interface
//@{
//! swap(let) rate
Expand Down
29 changes: 5 additions & 24 deletions ql/cashflows/cpicoupon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,33 +166,14 @@ namespace QuantLib {
}

Real CPICashFlow::baseFixing() const {
return baseFixing_;
if (baseFixing_ != Null<Rate>())
return baseFixing_;
else
return CPI::laggedFixing(cpiIndex(), baseDate(), 0 * Months, interpolation_);
}

Real CPICashFlow::indexFixing() const {
if (observationDate_ != Date()) {
return CPI::laggedFixing(cpiIndex(), observationDate_, observationLag_, interpolation_);
} else {
// we get to this branch when the deprecated constructor was used; it will be phased out
return CPI::laggedFixing(cpiIndex(), fixingDate() + observationLag_, observationLag_,
interpolation_);
}
}

Real CPICashFlow::amount() const {
Rate I0 = baseFixing();

// If BaseFixing is null, use the observed index fixing
if (I0 == Null<Rate>()) {
I0 = IndexedCashFlow::baseFixing();
}

Rate I1 = indexFixing();

if (growthOnly())
return notional() * (I1 / I0 - 1.0);
else
return notional() * (I1 / I0);
return CPI::laggedFixing(cpiIndex(), observationDate_, observationLag_, interpolation_);
}

CPILeg::CPILeg(Schedule schedule,
Expand Down
2 changes: 0 additions & 2 deletions ql/cashflows/cpicoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,6 @@ namespace QuantLib {

Real indexFixing() const override;

Real amount() const override;

protected:
Real baseFixing_;
Date observationDate_;
Expand Down
5 changes: 3 additions & 2 deletions ql/cashflows/indexedcashflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ namespace QuantLib {
Real I1 = indexFixing();

if (growthOnly_)
amount_ = notional_ * (I1 / I0 - 1.0);
amount_ = notional() * (I1 / I0 - 1.0);
else
amount_ = notional_ * (I1 / I0);
amount_ = notional() * (I1 / I0);
}

}
64 changes: 47 additions & 17 deletions ql/cashflows/yoyinflationcoupon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,39 @@ namespace QuantLib {

YoYInflationCoupon::
YoYInflationCoupon(const Date& paymentDate,
Real nominal,
const Date& startDate,
const Date& endDate,
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& yoyIndex,
const Period& observationLag,
const DayCounter& dayCounter,
Real gearing,
Spread spread,
const Date& refPeriodStart,
const Date& refPeriodEnd)
Real nominal,
const Date& startDate,
const Date& endDate,
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& yoyIndex,
const Period& observationLag,
CPI::InterpolationType interpolation,
const DayCounter& dayCounter,
Real gearing,
Spread spread,
const Date& refPeriodStart,
const Date& refPeriodEnd)
: InflationCoupon(paymentDate, nominal, startDate, endDate,
fixingDays, yoyIndex, observationLag,
dayCounter, refPeriodStart, refPeriodEnd),
yoyIndex_(yoyIndex), gearing_(gearing), spread_(spread) {}
fixingDays, yoyIndex, observationLag,
dayCounter, refPeriodStart, refPeriodEnd),
yoyIndex_(yoyIndex), interpolation_(interpolation), gearing_(gearing), spread_(spread) {}

YoYInflationCoupon::
YoYInflationCoupon(const Date& paymentDate,
Real nominal,
const Date& startDate,
const Date& endDate,
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& yoyIndex,
const Period& observationLag,
const DayCounter& dayCounter,
Real gearing,
Spread spread,
const Date& refPeriodStart,
const Date& refPeriodEnd)
: YoYInflationCoupon(paymentDate, nominal, startDate, endDate,
fixingDays, yoyIndex, observationLag, CPI::AsIndex,
dayCounter, gearing, spread, refPeriodStart, refPeriodEnd) {}


void YoYInflationCoupon::accept(AcyclicVisitor& v) {
Expand All @@ -53,20 +71,30 @@ namespace QuantLib {
InflationCoupon::accept(v);
}


bool YoYInflationCoupon::checkPricerImpl(
const ext::shared_ptr<InflationCouponPricer>&pricer) const {
return static_cast<bool>(
ext::dynamic_pointer_cast<YoYInflationCouponPricer>(pricer));
}

Rate YoYInflationCoupon::indexFixing() const {
return CPI::laggedYoYRate(yoyIndex(), accrualEndDate(), observationLag(), interpolation_);
}


yoyInflationLeg::yoyInflationLeg(Schedule schedule,
Calendar paymentCalendar,
ext::shared_ptr<YoYInflationIndex> index,
const Period& observationLag)
const Period& observationLag,
CPI::InterpolationType interpolation)
: schedule_(std::move(schedule)), index_(std::move(index)), observationLag_(observationLag),
paymentCalendar_(std::move(paymentCalendar)) {}
interpolation_(interpolation), paymentCalendar_(std::move(paymentCalendar)) {}

yoyInflationLeg::yoyInflationLeg(Schedule schedule,
Calendar paymentCalendar,
ext::shared_ptr<YoYInflationIndex> index,
const Period& observationLag)
: yoyInflationLeg(schedule, paymentCalendar, index, observationLag, CPI::AsIndex) {}


yoyInflationLeg& yoyInflationLeg::withNotionals(Real notional) {
Expand Down Expand Up @@ -196,6 +224,7 @@ namespace QuantLib {
detail::get(fixingDays_, i, 0),
index_,
observationLag_,
interpolation_,
paymentDayCounter_,
detail::get(gearings_, i, 1.0),
detail::get(spreads_, i, 0.0),
Expand All @@ -208,6 +237,7 @@ namespace QuantLib {
detail::get(fixingDays_, i, 0),
index_,
observationLag_,
interpolation_,
paymentDayCounter_,
detail::get(gearings_, i, 1.0),
detail::get(spreads_, i, 0.0),
Expand Down
69 changes: 51 additions & 18 deletions ql/cashflows/yoyinflationcoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,37 @@ namespace QuantLib {

//! %Coupon paying a YoY-inflation type index
class YoYInflationCoupon : public InflationCoupon {
public:
public:
YoYInflationCoupon(const Date& paymentDate,
Real nominal,
const Date& startDate,
const Date& endDate,
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& index,
const Period& observationLag,
CPI::InterpolationType interpolation,
const DayCounter& dayCounter,
Real gearing = 1.0,
Spread spread = 0.0,
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date());

/*! \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")]]
YoYInflationCoupon(const Date& paymentDate,
Real nominal,
const Date& startDate,
const Date& endDate,
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& index,
const Period& observationLag,
const DayCounter& dayCounter,
Real gearing = 1.0,
Spread spread = 0.0,
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date()
);
Real nominal,
const Date& startDate,
const Date& endDate,
Natural fixingDays,
const ext::shared_ptr<YoYInflationIndex>& index,
const Period& observationLag,
const DayCounter& dayCounter,
Real gearing = 1.0,
Spread spread = 0.0,
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date());

//! \name Inspectors
//@{
Expand All @@ -55,20 +72,23 @@ namespace QuantLib {
//! spread paid over the fixing of the underlying index
Spread spread() const { return spread_; }

Rate indexFixing() const override;

Rate adjustedFixing() const;

const ext::shared_ptr<YoYInflationIndex>& yoyIndex() const;

CPI::InterpolationType interpolation() const;
//@}

//! \name Visitability
//@{
void accept(AcyclicVisitor&) override;
//@}

private:
private:
ext::shared_ptr<YoYInflationIndex> yoyIndex_;
protected:

CPI::InterpolationType interpolation_;
protected:
Real gearing_;
Spread spread_;
bool checkPricerImpl(const ext::shared_ptr<InflationCouponPricer>&) const override;
Expand All @@ -79,6 +99,10 @@ namespace QuantLib {
return yoyIndex_;
}

inline CPI::InterpolationType YoYInflationCoupon::interpolation() const {
return interpolation_;
}

inline Rate YoYInflationCoupon::adjustedFixing() const {
return (rate()-spread())/gearing();
}
Expand All @@ -87,9 +111,17 @@ namespace QuantLib {


//! Helper class building a sequence of capped/floored yoy inflation coupons
//! payoff is: spread + gearing x index
class yoyInflationLeg {
public:
yoyInflationLeg(Schedule schedule,
Calendar cal,
ext::shared_ptr<YoYInflationIndex> index,
const Period& observationLag,
CPI::InterpolationType interpolation);
/*! \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")]]
yoyInflationLeg(Schedule schedule,
Calendar cal,
ext::shared_ptr<YoYInflationIndex> index,
Expand All @@ -113,6 +145,7 @@ namespace QuantLib {
Schedule schedule_;
ext::shared_ptr<YoYInflationIndex> index_;
Period observationLag_;
CPI::InterpolationType interpolation_;
std::vector<Real> notionals_;
DayCounter paymentDayCounter_;
BusinessDayConvention paymentAdjustment_ = ModifiedFollowing;
Expand Down
22 changes: 6 additions & 16 deletions ql/cashflows/zeroinflationcashflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,15 @@ namespace QuantLib {
: IndexedCashFlow(notional, index,
startDate - observationLag, endDate - observationLag,
paymentDate, growthOnly),
zeroInflationIndex_(index), observationInterpolation_(observationInterpolation),
zeroInflationIndex_(index), interpolation_(observationInterpolation),
startDate_(startDate), endDate_(endDate), observationLag_(observationLag) {}

void ZeroInflationCashFlow::performCalculations() const {

Real I0, I1;

if (observationInterpolation_ == CPI::AsIndex) {
I0 = zeroInflationIndex_->fixing(baseDate());
I1 = zeroInflationIndex_->fixing(fixingDate());
} else {
I0 = CPI::laggedFixing(zeroInflationIndex_, startDate_, observationLag_, observationInterpolation_);
I1 = CPI::laggedFixing(zeroInflationIndex_, endDate_, observationLag_, observationInterpolation_);
}
Real ZeroInflationCashFlow::baseFixing() const {
return CPI::laggedFixing(zeroInflationIndex_, startDate_, observationLag_, interpolation_);
}

if (growthOnly())
amount_ = notional() * (I1 / I0 - 1.0);
else
amount_ = notional() * (I1 / I0);
Real ZeroInflationCashFlow::indexFixing() const {
return CPI::laggedFixing(zeroInflationIndex_, endDate_, observationLag_, interpolation_);
}

void ZeroInflationCashFlow::accept(AcyclicVisitor& v) {
Expand Down
10 changes: 6 additions & 4 deletions ql/cashflows/zeroinflationcashflow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,24 @@ namespace QuantLib {
return zeroInflationIndex_;
}
CPI::InterpolationType observationInterpolation() const {
return observationInterpolation_;
return interpolation_;
}
//@}

//! \name CashFlow interface
//! \name ZeroInflationCashFlow interface
//@{
void performCalculations() const override;
Real baseFixing() const override;
Real indexFixing() const override;
//@}

//! \name Visitability
//@{
void accept(AcyclicVisitor&) override;
//@}

private:
ext::shared_ptr<ZeroInflationIndex> zeroInflationIndex_;
CPI::InterpolationType observationInterpolation_;
CPI::InterpolationType interpolation_;
Date startDate_, endDate_;
Period observationLag_;
};
Expand Down
Loading

0 comments on commit b2ef988

Please sign in to comment.