Coverage Report

Created: 2026-03-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/cashflows/yoyinflationcoupon.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2009 Chris Kenyon
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
 */
19
20
21
#include <ql/cashflows/capflooredinflationcoupon.hpp>
22
#include <ql/cashflows/cashflowvectors.hpp>
23
#include <ql/cashflows/inflationcoupon.hpp>
24
#include <ql/cashflows/inflationcouponpricer.hpp>
25
#include <utility>
26
27
namespace QuantLib {
28
29
    YoYInflationCoupon::
30
    YoYInflationCoupon(const Date& paymentDate,
31
                       Real nominal,
32
                       const Date& startDate,
33
                       const Date& endDate,
34
                       Natural fixingDays,
35
                       const ext::shared_ptr<YoYInflationIndex>& yoyIndex,
36
                       const Period& observationLag,
37
                       CPI::InterpolationType interpolation,
38
                       const DayCounter& dayCounter,
39
                       Real gearing,
40
                       Spread spread,
41
                       const Date& refPeriodStart,
42
                       const Date& refPeriodEnd)
43
0
    : InflationCoupon(paymentDate, nominal, startDate, endDate,
44
0
                      fixingDays, yoyIndex, observationLag,
45
0
                      dayCounter, refPeriodStart, refPeriodEnd),
46
0
      yoyIndex_(yoyIndex), interpolation_(interpolation), gearing_(gearing), spread_(spread) {}
Unexecuted instantiation: QuantLib::YoYInflationCoupon::YoYInflationCoupon(QuantLib::Date const&, double, QuantLib::Date const&, QuantLib::Date const&, unsigned int, boost::shared_ptr<QuantLib::YoYInflationIndex> const&, QuantLib::Period const&, QuantLib::CPI::InterpolationType, QuantLib::DayCounter const&, double, double, QuantLib::Date const&, QuantLib::Date const&)
Unexecuted instantiation: QuantLib::YoYInflationCoupon::YoYInflationCoupon(QuantLib::Date const&, double, QuantLib::Date const&, QuantLib::Date const&, unsigned int, boost::shared_ptr<QuantLib::YoYInflationIndex> const&, QuantLib::Period const&, QuantLib::CPI::InterpolationType, QuantLib::DayCounter const&, double, double, QuantLib::Date const&, QuantLib::Date const&)
47
48
0
    void YoYInflationCoupon::accept(AcyclicVisitor& v) {
49
0
        auto* v1 = dynamic_cast<Visitor<YoYInflationCoupon>*>(&v);
50
0
        if (v1 != nullptr)
51
0
            v1->visit(*this);
52
0
        else
53
0
            InflationCoupon::accept(v);
54
0
    }
55
56
    bool YoYInflationCoupon::checkPricerImpl(
57
0
            const ext::shared_ptr<InflationCouponPricer>&pricer) const {
58
0
        return static_cast<bool>(
59
0
               ext::dynamic_pointer_cast<YoYInflationCouponPricer>(pricer));
60
0
    }
61
62
0
    Rate YoYInflationCoupon::indexFixing() const {
63
0
        return CPI::laggedYoYRate(yoyIndex(), accrualEndDate(), observationLag(), interpolation_);
64
0
    }
65
66
67
    yoyInflationLeg::yoyInflationLeg(Schedule schedule,
68
                                     Calendar paymentCalendar,
69
                                     ext::shared_ptr<YoYInflationIndex> index,
70
                                     const Period& observationLag,
71
                                     CPI::InterpolationType interpolation)
72
0
    : schedule_(std::move(schedule)), index_(std::move(index)), observationLag_(observationLag),
73
0
      interpolation_(interpolation), paymentCalendar_(std::move(paymentCalendar)) {}
74
75
0
    yoyInflationLeg& yoyInflationLeg::withNotionals(Real notional) {
76
0
        notionals_ = std::vector<Real>(1,notional);
77
0
        return *this;
78
0
    }
79
80
0
    yoyInflationLeg& yoyInflationLeg::withNotionals(const std::vector<Real>& notionals) {
81
0
        notionals_ = notionals;
82
0
        return *this;
83
0
    }
84
85
0
    yoyInflationLeg& yoyInflationLeg::withPaymentDayCounter(const DayCounter& dayCounter) {
86
0
        paymentDayCounter_ = dayCounter;
87
0
        return *this;
88
0
    }
89
90
0
    yoyInflationLeg& yoyInflationLeg::withPaymentAdjustment(BusinessDayConvention convention) {
91
0
        paymentAdjustment_ = convention;
92
0
        return *this;
93
0
    }
94
95
0
    yoyInflationLeg& yoyInflationLeg::withFixingDays(Natural fixingDays) {
96
0
        fixingDays_ = std::vector<Natural>(1,fixingDays);
97
0
        return *this;
98
0
    }
99
100
0
    yoyInflationLeg& yoyInflationLeg::withFixingDays(const std::vector<Natural>& fixingDays) {
101
0
        fixingDays_ = fixingDays;
102
0
        return *this;
103
0
    }
104
105
0
    yoyInflationLeg& yoyInflationLeg::withGearings(Real gearing) {
106
0
        gearings_ = std::vector<Real>(1,gearing);
107
0
        return *this;
108
0
    }
109
110
0
    yoyInflationLeg& yoyInflationLeg::withGearings(const std::vector<Real>& gearings) {
111
0
        gearings_ = gearings;
112
0
        return *this;
113
0
    }
114
115
0
    yoyInflationLeg& yoyInflationLeg::withSpreads(Spread spread) {
116
0
        spreads_ = std::vector<Spread>(1,spread);
117
0
        return *this;
118
0
    }
119
120
0
    yoyInflationLeg& yoyInflationLeg::withSpreads(const std::vector<Spread>& spreads) {
121
0
        spreads_ = spreads;
122
0
        return *this;
123
0
    }
124
125
0
    yoyInflationLeg& yoyInflationLeg::withCaps(Rate cap) {
126
0
        caps_ = std::vector<Rate>(1,cap);
127
0
        return *this;
128
0
    }
129
130
0
    yoyInflationLeg& yoyInflationLeg::withCaps(const std::vector<Rate>& caps) {
131
0
        caps_ = caps;
132
0
        return *this;
133
0
    }
134
135
0
    yoyInflationLeg& yoyInflationLeg::withFloors(Rate floor) {
136
0
        floors_ = std::vector<Rate>(1,floor);
137
0
        return *this;
138
0
    }
139
140
0
    yoyInflationLeg& yoyInflationLeg::withFloors(const std::vector<Rate>& floors) {
141
0
        floors_ = floors;
142
0
        return *this;
143
0
    }
144
145
146
0
    yoyInflationLeg::operator Leg() const {
147
148
0
        Size n = schedule_.size()-1;
149
0
        QL_REQUIRE(!paymentDayCounter_.empty(), "no payment daycounter given");
150
0
        QL_REQUIRE(!notionals_.empty(), "no notional given");
151
0
        QL_REQUIRE(notionals_.size() <= n,
152
0
                   "too many nominals (" << notionals_.size() <<
153
0
                   "), only " << n << " required");
154
0
        QL_REQUIRE(gearings_.size()<=n,
155
0
                   "too many gearings (" << gearings_.size() <<
156
0
                   "), only " << n << " required");
157
0
        QL_REQUIRE(spreads_.size()<=n,
158
0
                   "too many spreads (" << spreads_.size() <<
159
0
                   "), only " << n << " required");
160
0
        QL_REQUIRE(caps_.size()<=n,
161
0
                   "too many caps (" << caps_.size() <<
162
0
                   "), only " << n << " required");
163
0
        QL_REQUIRE(floors_.size()<=n,
164
0
                   "too many floors (" << floors_.size() <<
165
0
                   "), only " << n << " required");
166
167
0
        Leg leg; leg.reserve(n);
168
169
0
        Calendar calendar = paymentCalendar_;
170
171
0
        Date refStart, start, refEnd, end;
172
173
0
        for (Size i=0; i<n; ++i) {
174
0
            refStart = start = schedule_.date(i);
175
0
            refEnd   =   end = schedule_.date(i+1);
176
0
            Date paymentDate = calendar.adjust(end, paymentAdjustment_);
177
0
            if (i==0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
178
0
                BusinessDayConvention bdc = schedule_.businessDayConvention();
179
0
                refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc);
180
0
            }
181
0
            if (i==n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
182
0
                BusinessDayConvention bdc = schedule_.businessDayConvention();
183
0
                refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc);
184
0
            }
185
0
            if (detail::get(gearings_, i, 1.0) == 0.0) { // fixed coupon
186
0
                leg.push_back(ext::make_shared<FixedRateCoupon>(
187
0
                            paymentDate,
188
0
                            detail::get(notionals_, i, 1.0),
189
0
                            detail::effectiveFixedRate(spreads_,caps_,
190
0
                                                       floors_,i),
191
0
                            paymentDayCounter_,
192
0
                            start, end, refStart, refEnd));
193
0
            } else { // yoy inflation coupon
194
0
                if (detail::noOption(caps_, floors_, i)) { // just swaplet
195
0
                    leg.push_back(ext::make_shared<YoYInflationCoupon>(
196
0
                            paymentDate,
197
0
                            detail::get(notionals_, i, 1.0),
198
0
                            start, end,
199
0
                            detail::get(fixingDays_, i, 0),
200
0
                            index_,
201
0
                            observationLag_,
202
0
                            interpolation_,
203
0
                            paymentDayCounter_,
204
0
                            detail::get(gearings_, i, 1.0),
205
0
                            detail::get(spreads_, i, 0.0),
206
0
                            refStart, refEnd));
207
0
                } else {    // cap/floorlet
208
0
                    leg.push_back(ext::make_shared<CappedFlooredYoYInflationCoupon>(
209
0
                            paymentDate,
210
0
                            detail::get(notionals_, i, 1.0),
211
0
                            start, end,
212
0
                            detail::get(fixingDays_, i, 0),
213
0
                            index_,
214
0
                            observationLag_,
215
0
                            interpolation_,
216
0
                            paymentDayCounter_,
217
0
                            detail::get(gearings_, i, 1.0),
218
0
                            detail::get(spreads_, i, 0.0),
219
0
                            detail::get(caps_,   i, Null<Rate>()),
220
0
                            detail::get(floors_, i, Null<Rate>()),
221
0
                            refStart, refEnd));
222
0
                }
223
0
            }
224
0
        }
225
226
        // Without caps or floors, this is enough; otherwise, a more
227
        // specific pricer will need to be set in client code.
228
0
        if (caps_.empty() && floors_.empty())
229
0
            setCouponPricer(leg, ext::make_shared<YoYInflationCouponPricer>());
230
231
0
        return leg;
232
0
    }
233
234
}
235