QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
subperiodcoupon.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 Toyin Akin
5 Copyright (C) 2021 Marcin Rybacki
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21#include <ql/cashflows/subperiodcoupon.hpp>
22#include <ql/cashflows/cashflowvectors.hpp>
23#include <ql/time/schedule.hpp>
24#include <ql/indexes/iborindex.hpp>
25#include <ql/termstructures/yieldtermstructure.hpp>
26#include <cmath>
27
28namespace QuantLib {
29
31 Real nominal,
32 const Date& startDate,
33 const Date& endDate,
34 Natural fixingDays,
35 const ext::shared_ptr<IborIndex>& index,
36 Real gearing,
37 Rate couponSpread,
38 Rate rateSpread,
39 const Date& refPeriodStart,
40 const Date& refPeriodEnd,
41 const DayCounter& dayCounter,
42 const Date& exCouponDate)
43 : FloatingRateCoupon(paymentDate, nominal, startDate, endDate,
44 fixingDays, index, gearing, couponSpread,
45 refPeriodStart, refPeriodEnd, dayCounter,
46 false, exCouponDate),
47 rateSpread_(rateSpread) {
49 .from(startDate)
50 .to(endDate)
51 .withTenor(index->tenor())
52 .withCalendar(index->fixingCalendar())
53 .withConvention(index->businessDayConvention())
54 .backwards()
55 .endOfMonth(index->endOfMonth());
56 valueDates_ = sch.dates();
57
58 // fixing dates
59 n_ = valueDates_.size() - 1;
60 if (fixingDays_ == 0) {
61 fixingDates_ = std::vector<Date>(valueDates_.begin(), valueDates_.end() - 1);
62 } else {
63 fixingDates_.resize(n_);
64 for (Size i = 0; i < n_; ++i)
66 }
67
68 // accrual of sub-periods
69 dt_.resize(n_);
70 const DayCounter& dc = index->dayCounter();
71 for (Size i = 0; i < n_; ++i)
72 dt_[i] = dc.yearFraction(valueDates_[i], valueDates_[i + 1]);
73 }
74
76 auto* v1 = dynamic_cast<Visitor<SubPeriodsCoupon>*>(&v);
77 if (v1 != nullptr)
78 v1->visit(*this);
79 else
81 }
82
83 Date SubPeriodsCoupon::fixingDate(const Date& valueDate) const {
85 index_->fixingCalendar().advance(valueDate, -static_cast<Integer>(fixingDays_), Days);
86 return fixingDate;
87 }
88
90 coupon_ = dynamic_cast<const SubPeriodsCoupon*>(&coupon);
91 QL_REQUIRE(coupon_, "sub-periods coupon required");
92
93 ext::shared_ptr<IborIndex> index = ext::dynamic_pointer_cast<IborIndex>(coupon_->index());
94 if (!index) {
95 // coupon was right, index is not
96 QL_FAIL("IborIndex required");
97 }
98
99 QL_REQUIRE(coupon_->accrualPeriod() != 0.0, "null accrual period");
100
101 const std::vector<Date>& fixingDates = coupon_->fixingDates();
102 Size n = fixingDates.size();
103 subPeriodFixings_.resize(n);
104
105 for (Size i = 0; i < n; i++) {
106 subPeriodFixings_[i] = index->fixing(fixingDates[i]) + coupon_->rateSpread();
107 }
108 }
109
111 QL_FAIL("SubPeriodsPricer::swapletPrice not implemented");
112 }
113
115 QL_FAIL("SubPeriodsPricer::capletPrice not implemented");
116 }
117
119 QL_FAIL("SubPeriodsPricer::capletRate not implemented");
120 }
121
123 QL_FAIL("SubPeriodsPricer::floorletPrice not implemented");
124 }
125
127 QL_FAIL("SubPeriodsPricer::floorletRate not implemented");
128 }
129
131 // past or future fixing is managed in InterestRateIndex::fixing()
132
133 Size nCount = subPeriodFixings_.size();
134 const std::vector<Time>& subPeriodFractions = coupon_->dt();
135 Real aggregateFactor = 0.0;
136 for (Size i = 0; i < nCount; i++) {
137 aggregateFactor += subPeriodFixings_[i] * subPeriodFractions[i];
138 }
139
140 Real rate = aggregateFactor / coupon_->accrualPeriod();
141 return coupon_->gearing() * rate + coupon_->spread();
142 }
143
145 // past or future fixing is managed in InterestRateIndex::fixing()
146
147 Real compoundFactor = 1.0;
148 const std::vector<Time>& subPeriodFractions = coupon_->dt();
149 Size nCount = subPeriodFixings_.size();
150 for (Size i = 0; i < nCount; i++) {
151 compoundFactor *= (1.0 + subPeriodFixings_[i] * subPeriodFractions[i]);
152 }
153
154 Real rate = (compoundFactor - 1.0) / coupon_->accrualPeriod();
155 return coupon_->gearing() * rate + coupon_->spread();
156 }
157
158 SubPeriodsLeg::SubPeriodsLeg(const Schedule& schedule, ext::shared_ptr<IborIndex> i)
159 : schedule_(schedule), index_(std::move(i)), paymentCalendar_(schedule.calendar()) {
160 QL_REQUIRE(index_, "no index provided");
161 }
162
164 notionals_ = std::vector<Real>(1, notional);
165 return *this;
166 }
167
168 SubPeriodsLeg& SubPeriodsLeg::withNotionals(const std::vector<Real>& notionals) {
169 notionals_ = notionals;
170 return *this;
171 }
172
175 return *this;
176 }
177
179 paymentAdjustment_ = convention;
180 return *this;
181 }
182
184 paymentCalendar_ = cal;
185 return *this;
186 }
187
189 paymentLag_ = lag;
190 return *this;
191 }
192
194 fixingDays_ = std::vector<Natural>(1, fixingDays);
195 return *this;
196 }
197
198 SubPeriodsLeg& SubPeriodsLeg::withFixingDays(const std::vector<Natural>& fixingDays) {
199 fixingDays_ = fixingDays;
200 return *this;
201 }
202
204 gearings_ = std::vector<Real>(1, gearing);
205 return *this;
206 }
207
208 SubPeriodsLeg& SubPeriodsLeg::withGearings(const std::vector<Real>& gearings) {
209 gearings_ = gearings;
210 return *this;
211 }
212
214 couponSpreads_ = std::vector<Spread>(1, spread);
215 return *this;
216 }
217
218 SubPeriodsLeg& SubPeriodsLeg::withCouponSpreads(const std::vector<Spread>& spreads) {
219 couponSpreads_ = spreads;
220 return *this;
221 }
222
224 rateSpreads_ = std::vector<Spread>(1, spread);
225 return *this;
226 }
227
228 SubPeriodsLeg& SubPeriodsLeg::withRateSpreads(const std::vector<Spread>& spreads) {
229 rateSpreads_ = spreads;
230 return *this;
231 }
232
234 averagingMethod_ = averagingMethod;
235 return *this;
236 }
237
239 const Calendar& cal,
240 BusinessDayConvention convention,
241 bool endOfMonth) {
242 exCouponPeriod_ = period;
243 exCouponCalendar_ = cal;
244 exCouponAdjustment_ = convention;
245 exCouponEndOfMonth_ = endOfMonth;
246 return *this;
247 }
248
249 SubPeriodsLeg::operator Leg() const {
250 Leg cashflows;
251 Calendar calendar = schedule_.calendar();
252 Date refStart, start, refEnd, end, exCouponDate;
253 Date paymentDate;
254
255 Size n = schedule_.size() - 1;
256 QL_REQUIRE(!notionals_.empty(), "no notional given");
257 QL_REQUIRE(notionals_.size() <= n,
258 "too many nominals (" << notionals_.size() << "), only " << n << " required");
259 QL_REQUIRE(gearings_.size() <= n,
260 "too many gearings (" << gearings_.size() << "), only " << n << " required");
261 QL_REQUIRE(couponSpreads_.size() <= n,
262 "too many coupon spreads (" << couponSpreads_.size() << "), only " << n << " required");
263 QL_REQUIRE(rateSpreads_.size() <= n,
264 "too many rate spreads (" << rateSpreads_.size() << "), only " << n << " required");
265 QL_REQUIRE(fixingDays_.size() <= n,
266 "too many fixing days (" << fixingDays_.size() << "), only " << n << " required");
267
268 for (Size i = 0; i < n; ++i) {
269 refStart = start = schedule_.date(i);
270 refEnd = end = schedule_.date(i + 1);
271 paymentDate = paymentCalendar_.advance(end, paymentLag_, Days, paymentAdjustment_);
272
273 if (i == 0 && schedule_.hasIsRegular() && !schedule_.isRegular(i + 1))
274 refStart = calendar.adjust(end - schedule_.tenor(), paymentAdjustment_);
275 if (i == n - 1 && schedule_.hasIsRegular() && !schedule_.isRegular(i + 1))
276 refEnd = calendar.adjust(start + schedule_.tenor(), paymentAdjustment_);
277 if (exCouponPeriod_ != Period()) {
278 if (exCouponCalendar_.empty()) {
279 exCouponDate = calendar.advance(paymentDate, -exCouponPeriod_,
280 exCouponAdjustment_, exCouponEndOfMonth_);
281 } else {
282 exCouponDate = exCouponCalendar_.advance(
283 paymentDate, -exCouponPeriod_, exCouponAdjustment_, exCouponEndOfMonth_);
284 }
285 }
286 cashflows.push_back(ext::shared_ptr<CashFlow>(new SubPeriodsCoupon(
287 paymentDate, detail::get(notionals_, i, notionals_.back()), start, end,
288 detail::get(fixingDays_, i, index_->fixingDays()), index_,
289 detail::get(gearings_, i, 1.0), detail::get(couponSpreads_, i, 0.0),
290 detail::get(rateSpreads_, i, 0.0), refStart, refEnd, paymentDayCounter_,
291 exCouponDate)));
292 }
293
294 switch (averagingMethod_) {
296 setCouponPricer(cashflows,
297 ext::shared_ptr<FloatingRateCouponPricer>(new AveragingRatePricer));
298 break;
300 setCouponPricer(cashflows, ext::shared_ptr<FloatingRateCouponPricer>(
302 break;
303 default:
304 QL_FAIL("unknown compounding convention (" << Integer(averagingMethod_) << ")");
305 }
306 return cashflows;
307 }
308}
309
degenerate base class for the Acyclic Visitor pattern
Definition: visitor.hpp:33
Real swapletRate() const override
calendar class
Definition: calendar.hpp:61
Date adjust(const Date &, BusinessDayConvention convention=Following) const
Definition: calendar.cpp:84
Date advance(const Date &, Integer n, TimeUnit unit, BusinessDayConvention convention=Following, bool endOfMonth=false) const
Definition: calendar.cpp:130
Real swapletRate() const override
Time accrualPeriod() const
accrual period as fraction of year
Definition: coupon.cpp:44
Concrete date class.
Definition: date.hpp:125
static Date advance(const Date &d, Integer units, TimeUnit)
Definition: date.cpp:139
day counter class
Definition: daycounter.hpp:44
Time yearFraction(const Date &, const Date &, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date()) const
Returns the period between two dates as a fraction of year.
Definition: daycounter.hpp:128
base floating-rate coupon class
ext::shared_ptr< InterestRateIndex > index_
void accept(AcyclicVisitor &) override
Real gearing() const
index gearing, i.e. multiplicative coefficient for the index
const ext::shared_ptr< InterestRateIndex > & index() const
floating index
Spread spread() const
spread paid over the fixing of the underlying index
MakeSchedule & withConvention(BusinessDayConvention)
Definition: schedule.cpp:557
MakeSchedule & backwards()
Definition: schedule.cpp:578
MakeSchedule & to(const Date &terminationDate)
Definition: schedule.cpp:537
MakeSchedule & withTenor(const Period &)
Definition: schedule.cpp:542
MakeSchedule & from(const Date &effectiveDate)
Definition: schedule.cpp:532
MakeSchedule & endOfMonth(bool flag=true)
Definition: schedule.cpp:583
MakeSchedule & withCalendar(const Calendar &)
Definition: schedule.cpp:552
Payment schedule.
Definition: schedule.hpp:40
const std::vector< Date > & dates() const
Definition: schedule.hpp:75
std::vector< Date > fixingDates_
Spread rateSpread() const
rate spread
void accept(AcyclicVisitor &) override
SubPeriodsCoupon(const Date &paymentDate, Real nominal, const Date &startDate, const Date &endDate, Natural fixingDays, const ext::shared_ptr< IborIndex > &index, Real gearing=1.0, Rate couponSpread=0.0, Rate rateSpread=0.0, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date(), const DayCounter &dayCounter=DayCounter(), const Date &exCouponDate=Date())
std::vector< Date > valueDates_
const std::vector< Time > & dt() const
accrual (compounding) periods
const std::vector< Date > & fixingDates() const
fixing dates for the rates to be compounded
Date fixingDate() const override
the date when the coupon is fully determined
helper class building a sequence of overnight coupons
SubPeriodsLeg & withAveragingMethod(RateAveraging::Type averagingMethod)
SubPeriodsLeg & withExCouponPeriod(const Period &, const Calendar &, BusinessDayConvention, bool endOfMonth=false)
BusinessDayConvention paymentAdjustment_
BusinessDayConvention exCouponAdjustment_
SubPeriodsLeg & withPaymentLag(Natural lag)
std::vector< Spread > couponSpreads_
SubPeriodsLeg(const Schedule &schedule, ext::shared_ptr< IborIndex > index)
SubPeriodsLeg & withNotionals(Real notional)
std::vector< Real > notionals_
RateAveraging::Type averagingMethod_
SubPeriodsLeg & withRateSpreads(Spread spread)
std::vector< Natural > fixingDays_
std::vector< Spread > rateSpreads_
SubPeriodsLeg & withCouponSpreads(Spread spread)
SubPeriodsLeg & withGearings(Real gearing)
SubPeriodsLeg & withFixingDays(Natural fixingDays)
SubPeriodsLeg & withPaymentAdjustment(BusinessDayConvention)
SubPeriodsLeg & withPaymentDayCounter(const DayCounter &)
std::vector< Real > gearings_
SubPeriodsLeg & withPaymentCalendar(const Calendar &)
ext::shared_ptr< IborIndex > index_
Real capletPrice(Rate effectiveCap) const override
Rate floorletRate(Rate effectiveFloor) const override
std::vector< Real > subPeriodFixings_
const SubPeriodsCoupon * coupon_
void initialize(const FloatingRateCoupon &coupon) override
Real floorletPrice(Rate effectiveFloor) const override
Rate swapletPrice() const override
Rate capletRate(Rate effectiveCap) const override
Visitor for a specific class
Definition: visitor.hpp:40
virtual void visit(T &)=0
BusinessDayConvention
Business Day conventions.
QL_REAL Real
real number
Definition: types.hpp:50
unsigned QL_INTEGER Natural
positive integer
Definition: types.hpp:43
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Real Spread
spreads on interest rates
Definition: types.hpp:74
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
T get(const std::vector< T > &v, Size i, U defaultValue)
Definition: vectors.hpp:35
Definition: any.hpp:35
void setCouponPricer(const Leg &leg, const ext::shared_ptr< FloatingRateCouponPricer > &pricer)
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:78
STL namespace.