Coverage Report

Created: 2026-08-14 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/cashflows/rangeaccrual.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
5
 Copyright (C) 2006, 2007 Giorgio Facchinetti
6
 Copyright (C) 2006, 2007 Mario Pucci
7
8
 This file is part of QuantLib, a free-software/open-source library
9
 for financial quantitative analysts and developers - http://quantlib.org/
10
11
 QuantLib is free software: you can redistribute it and/or modify it
12
 under the terms of the QuantLib license.  You should have received a
13
 copy of the license along with this program; if not, please email
14
 <quantlib-dev@lists.sf.net>. The license is also available online at
15
 <https://www.quantlib.org/license.shtml>.
16
17
 This program is distributed in the hope that it will be useful, but WITHOUT
18
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 FOR A PARTICULAR PURPOSE.  See the license for more details.
20
*/
21
22
/*! \file rangeaccrual.hpp
23
    \brief range-accrual coupon
24
*/
25
26
#ifndef quantlib_range_accrual_h
27
#define quantlib_range_accrual_h
28
29
#include <ql/termstructures/volatility/smilesection.hpp>
30
#include <ql/cashflows/couponpricer.hpp>
31
#include <ql/cashflows/floatingratecoupon.hpp>
32
#include <ql/time/schedule.hpp>
33
#include <vector>
34
35
namespace QuantLib {
36
37
    class IborIndex;
38
39
    class RangeAccrualFloatersCoupon : public FloatingRateCoupon {
40
41
      public:
42
        RangeAccrualFloatersCoupon(const Date& paymentDate,
43
                                   Real nominal,
44
                                   const ext::shared_ptr<IborIndex>& index,
45
                                   const Date& startDate,
46
                                   const Date& endDate,
47
                                   Natural fixingDays,
48
                                   const DayCounter& dayCounter,
49
                                   Real gearing,
50
                                   Rate spread,
51
                                   const Date& refPeriodStart,
52
                                   const Date& refPeriodEnd,
53
                                   Schedule observationsSchedule,
54
                                   Real lowerTrigger,
55
                                   Real upperTrigger);
56
57
        /*! \deprecated Use the overload taking a Schedule instead.
58
                        Deprecated in version 1.40.
59
        */
60
        [[deprecated("Use the overload taking a Schedule instead")]]
61
        RangeAccrualFloatersCoupon(const Date& paymentDate,
62
                                   Real nominal,
63
                                   const ext::shared_ptr<IborIndex>& index,
64
                                   const Date& startDate,
65
                                   const Date& endDate,
66
                                   Natural fixingDays,
67
                                   const DayCounter& dayCounter,
68
                                   Real gearing,
69
                                   Rate spread,
70
                                   const Date& refPeriodStart,
71
                                   const Date& refPeriodEnd,
72
                                   const ext::shared_ptr<Schedule>& observationsSchedule,
73
                                   Real lowerTrigger,
74
                                   Real upperTrigger)
75
        : RangeAccrualFloatersCoupon(paymentDate, nominal, index, startDate, endDate,
76
                                     fixingDays, dayCounter, gearing, spread,
77
                                     refPeriodStart, refPeriodEnd,
78
                                     *observationsSchedule,
79
0
                                     lowerTrigger, upperTrigger) {}
80
81
0
        Real startTime() const {return startTime_; }
82
0
        Real endTime() const {return endTime_; }
83
0
        Real lowerTrigger() const {return lowerTrigger_; }
84
0
        Real upperTrigger() const {return upperTrigger_; }
85
0
        Size observationsNo() const {return observationsNo_; }
86
0
        const std::vector<Date>& observationDates() const {
87
0
            return observationDates_;
88
0
        }
89
0
        const std::vector<Real>& observationTimes() const {
90
0
            return observationTimes_;
91
0
        }
92
0
        const Schedule& observationSchedule() const { return observationSchedule_; }
93
        /*! \deprecated Use observationSchedule instead.
94
                        Deprecated in version 1.40.
95
        */
96
        [[deprecated("Use observationSchedule instead")]]
97
0
        ext::shared_ptr<Schedule> observationsSchedule() const {
98
0
            return ext::make_shared<Schedule>(observationSchedule_);
99
0
        }
100
101
        Real priceWithoutOptionality(
102
                       const Handle<YieldTermStructure>& discountCurve) const;
103
        //! \name Visitability
104
        //@{
105
        void accept(AcyclicVisitor&) override;
106
        //@}
107
      private:
108
109
        Real startTime_;                               // S
110
        Real endTime_;                                 // T
111
112
        Schedule observationSchedule_;
113
        std::vector<Date> observationDates_;
114
        std::vector<Real> observationTimes_;
115
        Size observationsNo_;
116
117
        Real lowerTrigger_;
118
        Real upperTrigger_;
119
     };
120
121
    class RangeAccrualPricer: public FloatingRateCouponPricer {
122
      public:
123
        //! \name Observer interface
124
        //@{
125
        Rate swapletRate() const override;
126
        Real capletPrice(Rate effectiveCap) const override;
127
        Rate capletRate(Rate effectiveCap) const override;
128
        Real floorletPrice(Rate effectiveFloor) const override;
129
        Rate floorletRate(Rate effectiveFloor) const override;
130
        void initialize(const FloatingRateCoupon& coupon) override;
131
        //@}
132
133
    protected:
134
        const RangeAccrualFloatersCoupon* coupon_;
135
        Real startTime_;                                   // S
136
        Real endTime_;                                     // T
137
        Real accrualFactor_;                               // T-S
138
        std::vector<Real> observationTimeLags_;            // d
139
        std::vector<Real> observationTimes_;               // U
140
        std::vector<Real> initialValues_;
141
        Size observationsNo_;
142
        Real lowerTrigger_;
143
        Real upperTrigger_;
144
        Real discount_;
145
        Real gearing_;
146
        Spread spread_;
147
        Real spreadLegValue_;
148
149
    };
150
151
    class RangeAccrualPricerByBgm : public RangeAccrualPricer {
152
153
     public:
154
       RangeAccrualPricerByBgm(Real correlation,
155
                               ext::shared_ptr<SmileSection> smilesOnExpiry,
156
                               ext::shared_ptr<SmileSection> smilesOnPayment,
157
                               bool withSmile,
158
                               bool byCallSpread);
159
       //! \name Observer interface
160
       //@{
161
       Real swapletPrice() const override;
162
       //@}
163
164
     protected:
165
166
        Real drift(Real U, Real lambdaS, Real lambdaT, Real correlation) const;
167
        Real derDriftDerLambdaS(Real U, Real lambdaS, Real lambdaT,
168
                                Real correlation) const;
169
        Real derDriftDerLambdaT(Real U, Real lambdaS, Real lambdaT,
170
                                Real correlation) const;
171
172
        Real lambda(Real U, Real lambdaS, Real lambdaT) const;
173
        Real derLambdaDerLambdaS(Real U) const;
174
        Real derLambdaDerLambdaT(Real U) const;
175
176
        std::vector<Real> driftsOverPeriod(Real U, Real lambdaS, Real lambdaT,
177
                                           Real correlation) const;
178
        std::vector<Real> lambdasOverPeriod(Real U, Real lambdaS,
179
                                            Real lambdaT) const;
180
181
        Real digitalRangePrice(Real lowerTrigger,
182
                                Real upperTrigger,
183
                                Real initialValue,
184
                                Real expiry,
185
                                Real deflator) const;
186
187
        Real digitalPrice(Real strike,
188
                    Real initialValue,
189
                    Real expiry,
190
                    Real deflator) const;
191
192
        Real digitalPriceWithoutSmile(Real strike,
193
                    Real initialValue,
194
                    Real expiry,
195
                    Real deflator) const;
196
197
        Real digitalPriceWithSmile(Real strike,
198
                    Real initialValue,
199
                    Real expiry,
200
                    Real deflator) const;
201
202
        Real callSpreadPrice(Real previousInitialValue,
203
                            Real nextInitialValue,
204
                            Real previousStrike,
205
                            Real nextStrike,
206
                            Real deflator,
207
                            Real previousVariance,
208
                            Real nextVariance) const;
209
210
        Real smileCorrection(Real strike,
211
                               Real initialValue,
212
                               Real expiry,
213
                               Real deflator) const;
214
215
     private:
216
        Real correlation_;   // correlation between L(S) and L(T)
217
        bool withSmile_;
218
        bool byCallSpread_;
219
220
        ext::shared_ptr<SmileSection> smilesOnExpiry_;
221
        ext::shared_ptr<SmileSection> smilesOnPayment_;
222
        Real eps_ = 1.0e-8;
223
    };
224
225
226
    //! helper class building a sequence of range-accrual floating-rate coupons
227
    class RangeAccrualLeg {
228
      public:
229
        RangeAccrualLeg(Schedule schedule, ext::shared_ptr<IborIndex> index);
230
        RangeAccrualLeg& withNotionals(Real notional);
231
        RangeAccrualLeg& withNotionals(const std::vector<Real>& notionals);
232
        RangeAccrualLeg& withPaymentDayCounter(const DayCounter&);
233
        RangeAccrualLeg& withPaymentAdjustment(BusinessDayConvention);
234
        RangeAccrualLeg& withFixingDays(Natural fixingDays);
235
        RangeAccrualLeg& withFixingDays(const std::vector<Natural>& fixingDays);
236
        RangeAccrualLeg& withGearings(Real gearing);
237
        RangeAccrualLeg& withGearings(const std::vector<Real>& gearings);
238
        RangeAccrualLeg& withSpreads(Spread spread);
239
        RangeAccrualLeg& withSpreads(const std::vector<Spread>& spreads);
240
        RangeAccrualLeg& withLowerTriggers(Rate trigger);
241
        RangeAccrualLeg& withLowerTriggers(const std::vector<Rate>& triggers);
242
        RangeAccrualLeg& withUpperTriggers(Rate trigger);
243
        RangeAccrualLeg& withUpperTriggers(const std::vector<Rate>& triggers);
244
        RangeAccrualLeg& withObservationTenor(const Period&);
245
        RangeAccrualLeg& withObservationConvention(BusinessDayConvention);
246
        operator Leg() const;
247
      private:
248
        Schedule schedule_;
249
        ext::shared_ptr<IborIndex> index_;
250
        std::vector<Real> notionals_;
251
        DayCounter paymentDayCounter_;
252
        BusinessDayConvention paymentAdjustment_ = Following;
253
        std::vector<Natural> fixingDays_;
254
        std::vector<Real> gearings_;
255
        std::vector<Spread> spreads_;
256
        std::vector<Rate> lowerTriggers_, upperTriggers_;
257
        Period observationTenor_;
258
        BusinessDayConvention observationConvention_ = ModifiedFollowing;
259
    };
260
261
}
262
263
264
#endif