Skip to content

Commit

Permalink
Make cashflow lazy (#1757)
Browse files Browse the repository at this point in the history
  • Loading branch information
lballabio authored Aug 4, 2023
2 parents 9a9d429 + a765cb4 commit 82597fe
Show file tree
Hide file tree
Showing 14 changed files with 48 additions and 30 deletions.
7 changes: 6 additions & 1 deletion ql/cashflow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <ql/event.hpp>
#include <ql/math/comparison.hpp>
#include <ql/optional.hpp>
#include <ql/patterns/lazyobject.hpp>
#include <vector>

namespace QuantLib {
Expand All @@ -36,7 +37,7 @@ namespace QuantLib {
/*! This class is purely virtual and acts as a base class for the
actual cash flow implementations.
*/
class CashFlow : public Event {
class CashFlow : public Event, public LazyObject {
public:
~CashFlow() override = default;
//! \name Event interface
Expand All @@ -50,6 +51,10 @@ namespace QuantLib {
bool hasOccurred(const Date& refDate = Date(),
ext::optional<bool> includeRefDate = ext::nullopt) const override;
//@}
//! \name LazyObject interface
//@{
void performCalculations() const override {}
//@}
//! \name CashFlow interface
//@{
//! returns the amount of the cash flow
Expand Down
3 changes: 1 addition & 2 deletions ql/cashflows/digitalcoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ namespace QuantLib {
Position::Type putPosition = Position::Long,
bool isPutITMIncluded = false,
Rate putDigitalPayoff = Null<Rate>(),
const ext::shared_ptr<DigitalReplication>& replication =
ext::shared_ptr<DigitalReplication>(),
const ext::shared_ptr<DigitalReplication>& replication = {},
bool nakedOption = false);

//@}
Expand Down
12 changes: 8 additions & 4 deletions ql/cashflows/fixedratecoupon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,14 @@ namespace QuantLib {
rate_(std::move(interestRate)) {}

Real FixedRateCoupon::amount() const {
return nominal()*(rate_.compoundFactor(accrualStartDate_,
accrualEndDate_,
refPeriodStart_,
refPeriodEnd_) - 1.0);
calculate();
return amount_;
}

void FixedRateCoupon::performCalculations() const {
amount_ = nominal() * (rate_.compoundFactor(accrualStartDate_, accrualEndDate_,
refPeriodStart_, refPeriodEnd_) -
1.0);
}

Real FixedRateCoupon::accruedAmount(const Date& d) const {
Expand Down
5 changes: 5 additions & 0 deletions ql/cashflows/fixedratecoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ namespace QuantLib {
const Date& refPeriodEnd = Date(),
const Date& exCouponDate = Date());
//@}
//! \name LazyObject interface
//@{
void performCalculations() const override;
//@}
//! \name CashFlow interface
//@{
Real amount() const override;
Expand All @@ -77,6 +81,7 @@ namespace QuantLib {
//@}
private:
InterestRate rate_;
mutable Real amount_;
};


Expand Down
2 changes: 1 addition & 1 deletion ql/cashflows/floatingratecoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace QuantLib {
class FloatingRateCouponPricer;

//! base floating-rate coupon class
class FloatingRateCoupon : public Coupon, public LazyObject {
class FloatingRateCoupon : public Coupon {
public:
FloatingRateCoupon(const Date& paymentDate,
Real nominal,
Expand Down
10 changes: 7 additions & 3 deletions ql/cashflows/indexedcashflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ namespace QuantLib {
}

Real IndexedCashFlow::amount() const {
calculate();
return amount_;
}

void IndexedCashFlow::performCalculations() const {
Real I0 = baseFixing();
Real I1 = indexFixing();

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

}
8 changes: 4 additions & 4 deletions ql/cashflows/indexedcashflow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ namespace QuantLib {
growthOnly = false means i(T)/i(0), which is a bond-type setting.
growthOnly = true means i(T)/i(0) - 1, which is a swap-type setting.
*/
class IndexedCashFlow : public CashFlow,
public Observer {
class IndexedCashFlow : public CashFlow {
public:
IndexedCashFlow(Real notional,
ext::shared_ptr<Index> index,
Expand All @@ -70,15 +69,16 @@ namespace QuantLib {
//@{
void accept(AcyclicVisitor&) override;
//@}
//! \name Observer interface
//! \name LazyObject interface
//@{
void update() override { notifyObservers(); }
void performCalculations() const override;
//@}
private:
Real notional_;
ext::shared_ptr<Index> index_;
Date baseDate_, fixingDate_, paymentDate_;
bool growthOnly_;
mutable Real amount_;
};


Expand Down
7 changes: 6 additions & 1 deletion ql/cashflows/inflationcoupon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,16 @@ namespace QuantLib {


Rate InflationCoupon::rate() const {
calculate();
return rate_;
}

void InflationCoupon::performCalculations() const {
QL_REQUIRE(pricer_, "pricer not set");
// we know it is the correct type because checkPricerImpl checks on setting
// in general pricer_ will be a derived class, as will *this on calling
pricer_->initialize(*this);
return pricer_->swapletRate();
rate_ = pricer_->swapletRate();
}


Expand Down
8 changes: 4 additions & 4 deletions ql/cashflows/inflationcoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ namespace QuantLib {
\note inflation indices do not contain day counters or calendars.
*/
class InflationCoupon : public Coupon,
public Observer {
class InflationCoupon : public Coupon {
public:
InflationCoupon(const Date& paymentDate,
Real nominal,
Expand Down Expand Up @@ -85,9 +84,9 @@ namespace QuantLib {
virtual Rate indexFixing() const;
//@}

//! \name Observer interface
//! \name LazyObject interface
//@{
void update() override { notifyObservers(); }
void performCalculations() const override;
//@}

//! \name Visitability
Expand All @@ -103,6 +102,7 @@ namespace QuantLib {
Period observationLag_;
DayCounter dayCounter_;
Natural fixingDays_;
mutable Real rate_;

//! makes sure you were given the correct type of pricer
// this can also done in external pricer setter classes via
Expand Down
2 changes: 1 addition & 1 deletion ql/experimental/inflation/yoyoptionlethelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ namespace QuantLib {


Real YoYOptionletHelper::impliedQuote() const {
yoyCapFloor_->recalculate();
yoyCapFloor_->deepUpdate();
return yoyCapFloor_->NPV();
}

Expand Down
4 changes: 1 addition & 3 deletions ql/instruments/bond.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,7 @@ namespace QuantLib {

void Bond::deepUpdate() {
for (auto& cashflow : cashflows_) {
if(auto lazy = ext::dynamic_pointer_cast<LazyObject>(cashflow)) {
lazy->deepUpdate();
}
cashflow->deepUpdate();
}
update();
}
Expand Down
3 changes: 1 addition & 2 deletions ql/instruments/capfloor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,7 @@ namespace QuantLib {

void CapFloor::deepUpdate() {
for (auto& i : floatingLeg_) {
if(auto lazy = ext::dynamic_pointer_cast<LazyObject>(i))
lazy->deepUpdate();
i->deepUpdate();
}
update();
}
Expand Down
3 changes: 1 addition & 2 deletions ql/instruments/swap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ namespace QuantLib {
void Swap::deepUpdate() {
for (auto& leg : legs_) {
for (auto& k : leg) {
if (auto lazy = ext::dynamic_pointer_cast<LazyObject>(k))
lazy->deepUpdate();
k->deepUpdate();
}
}
update();
Expand Down
4 changes: 2 additions & 2 deletions ql/termstructures/inflation/inflationhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ namespace QuantLib {


Real ZeroCouponInflationSwapHelper::impliedQuote() const {
zciis_->recalculate();
zciis_->deepUpdate();
return zciis_->fairRate();
}

Expand Down Expand Up @@ -155,7 +155,7 @@ namespace QuantLib {


Real YearOnYearInflationSwapHelper::impliedQuote() const {
yyiis_->recalculate();
yyiis_->deepUpdate();
return yyiis_->fairRate();
}

Expand Down

0 comments on commit 82597fe

Please sign in to comment.