Coverage Report

Created: 2026-03-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/cashflows/cashflows.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2005, 2006 StatPro Italia srl
5
 Copyright (C) 2005 Charles Whitmore
6
 Copyright (C) 2007, 2008, 2009, 2010, 2011 Ferdinando Ametrano
7
 Copyright (C) 2008 Toyin Akin
8
9
 This file is part of QuantLib, a free-software/open-source library
10
 for financial quantitative analysts and developers - http://quantlib.org/
11
12
 QuantLib is free software: you can redistribute it and/or modify it
13
 under the terms of the QuantLib license.  You should have received a
14
 copy of the license along with this program; if not, please email
15
 <quantlib-dev@lists.sf.net>. The license is also available online at
16
 <https://www.quantlib.org/license.shtml>.
17
18
 This program is distributed in the hope that it will be useful, but WITHOUT
19
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20
 FOR A PARTICULAR PURPOSE.  See the license for more details.
21
*/
22
23
/*! \file cashflows.hpp
24
    \brief Cash-flow analysis functions
25
*/
26
27
#ifndef quantlib_cashflows_hpp
28
#define quantlib_cashflows_hpp
29
30
#include <ql/cashflows/duration.hpp>
31
#include <ql/cashflow.hpp>
32
#include <ql/interestrate.hpp>
33
#include <ql/shared_ptr.hpp>
34
35
namespace QuantLib {
36
37
    class YieldTermStructure;
38
39
    //! %cashflow-analysis functions
40
    /*! \todo add tests */
41
    class CashFlows {
42
      private:
43
        class IrrFinder {
44
          public:
45
            IrrFinder(const Leg& leg,
46
                      Real npv,
47
                      DayCounter dayCounter,
48
                      Compounding comp,
49
                      Frequency freq,
50
                      const ext::optional<bool>& includeSettlementDateFlows,
51
                      Date settlementDate,
52
                      Date npvDate);
53
54
            Real operator()(Rate y) const;
55
            Real derivative(Rate y) const;
56
          private:
57
            void checkSign() const;
58
59
            const Leg& leg_;
60
            Real npv_;
61
            DayCounter dayCounter_;
62
            Compounding compounding_;
63
            Frequency frequency_;
64
            ext::optional<bool> includeSettlementDateFlows_;
65
            Date settlementDate_, npvDate_;
66
        };
67
      public:
68
        CashFlows() = delete;
69
        CashFlows(CashFlows&&) = delete;
70
        CashFlows(const CashFlows&) = delete;
71
        CashFlows& operator=(CashFlows&&) = delete;
72
        CashFlows& operator=(const CashFlows&) = delete;
73
        ~CashFlows() = default;
74
75
        //! \name Date functions
76
        //@{
77
        static Date startDate(const Leg& leg);
78
        static Date maturityDate(const Leg& leg);
79
        static bool isExpired(const Leg& leg,
80
                              const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
81
                              Date settlementDate = Date());
82
        //@}
83
84
        //! \name CashFlow functions
85
        //@{
86
        //! the last cashflow paying before or at the given date
87
        static Leg::const_reverse_iterator
88
        previousCashFlow(const Leg& leg,
89
                         const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
90
                         Date settlementDate = Date());
91
        //! the first cashflow paying after the given date
92
        static Leg::const_iterator
93
        nextCashFlow(const Leg& leg,
94
                     const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
95
                     Date settlementDate = Date());
96
        static Date
97
        previousCashFlowDate(const Leg& leg,
98
                             const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
99
                             Date settlementDate = Date());
100
        static Date
101
        nextCashFlowDate(const Leg& leg,
102
                         const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
103
                         Date settlementDate = Date());
104
        static Real
105
        previousCashFlowAmount(const Leg& leg,
106
                               const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
107
                               Date settlementDate = Date());
108
        static Real
109
        nextCashFlowAmount(const Leg& leg,
110
                           const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
111
                           Date settlementDate = Date());
112
        //@}
113
114
        //! \name Coupon inspectors
115
        //@{
116
        static Rate
117
        previousCouponRate(const Leg& leg,
118
                           const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
119
                           Date settlementDate = Date());
120
        static Rate
121
        nextCouponRate(const Leg& leg,
122
                       const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
123
                       Date settlementDate = Date());
124
125
        static Real
126
        nominal(const Leg& leg,
127
                const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
128
                Date settlementDate = Date());
129
        static Date
130
        accrualStartDate(const Leg& leg,
131
                         const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
132
                         Date settlementDate = Date());
133
        static Date
134
        accrualEndDate(const Leg& leg,
135
                       const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
136
                       Date settlementDate = Date());
137
        static Date
138
        referencePeriodStart(const Leg& leg,
139
                             const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
140
                             Date settlementDate = Date());
141
        static Date
142
        referencePeriodEnd(const Leg& leg,
143
                           const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
144
                           Date settlementDate = Date());
145
        static Time
146
        accrualPeriod(const Leg& leg,
147
                      const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
148
                      Date settlementDate = Date());
149
        static Date::serial_type
150
        accrualDays(const Leg& leg,
151
                    const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
152
                    Date settlementDate = Date());
153
        static Time
154
        accruedPeriod(const Leg& leg,
155
                      const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
156
                      Date settlementDate = Date());
157
        static Date::serial_type
158
        accruedDays(const Leg& leg,
159
                    const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
160
                    Date settlementDate = Date());
161
        static Real
162
        accruedAmount(const Leg& leg,
163
                      const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
164
                      Date settlementDate = Date());
165
        //@}
166
167
        //! \name YieldTermStructure functions
168
        //@{
169
        //! NPV of the cash flows.
170
        /*! The NPV is the sum of the cash flows, each discounted
171
            according to the given term structure.
172
        */
173
        static Real npv(const Leg& leg,
174
                        const YieldTermStructure& discountCurve,
175
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
176
                        Date settlementDate = Date(),
177
                        Date npvDate = Date());
178
        //! Basis-point sensitivity of the cash flows.
179
        /*! The result is the change in NPV due to a uniform
180
            1-basis-point change in the rate paid by the cash
181
            flows. The change for each coupon is discounted according
182
            to the given term structure.
183
        */
184
        static Real bps(const Leg& leg,
185
                        const YieldTermStructure& discountCurve,
186
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
187
                        Date settlementDate = Date(),
188
                        Date npvDate = Date());
189
190
        //! NPV and BPS of the cash flows.
191
        /*! The NPV and BPS of the cash flows calculated
192
            together for performance reason
193
        */
194
        static std::pair<Real, Real> npvbps(const Leg& leg,
195
                                            const YieldTermStructure& discountCurve,
196
                                            const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
197
                                            Date settlementDate = Date(),
198
                                            Date npvDate = Date());
199
200
        //! At-the-money rate of the cash flows.
201
        /*! The result is the fixed rate for which a fixed rate cash flow
202
            vector, equivalent to the input vector, has the required NPV
203
            according to the given term structure. If the required NPV is
204
            not given, the input cash flow vector's NPV is used instead.
205
        */
206
        static Rate atmRate(const Leg& leg,
207
                            const YieldTermStructure& discountCurve,
208
                            const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
209
                            Date settlementDate = Date(),
210
                            Date npvDate = Date(),
211
                            Real npv = Null<Real>());
212
        //@}
213
214
        //! \name Yield (a.k.a. Internal Rate of Return, i.e. IRR) functions
215
        /*! The IRR is the interest rate at which the NPV of the cash
216
            flows equals the dirty price.
217
        */
218
        //@{
219
        //! NPV of the cash flows.
220
        /*! The NPV is the sum of the cash flows, each discounted
221
            according to the given constant interest rate.  The result
222
            is affected by the choice of the interest-rate compounding
223
            and the relative frequency and day counter.
224
        */
225
        static Real npv(const Leg& leg,
226
                        const InterestRate& yield,
227
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
228
                        Date settlementDate = Date(),
229
                        Date npvDate = Date());
230
        static Real npv(const Leg& leg,
231
                        Rate yield,
232
                        const DayCounter& dayCounter,
233
                        Compounding compounding,
234
                        Frequency frequency,
235
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
236
                        Date settlementDate = Date(),
237
                        Date npvDate = Date());
238
        //! Basis-point sensitivity of the cash flows.
239
        /*! The result is the change in NPV due to a uniform
240
            1-basis-point change in the rate paid by the cash
241
            flows. The change for each coupon is discounted according
242
            to the given constant interest rate.  The result is
243
            affected by the choice of the interest-rate compounding
244
            and the relative frequency and day counter.
245
        */
246
        static Real bps(const Leg& leg,
247
                        const InterestRate& yield,
248
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
249
                        Date settlementDate = Date(),
250
                        Date npvDate = Date());
251
        static Real bps(const Leg& leg,
252
                        Rate yield,
253
                        const DayCounter& dayCounter,
254
                        Compounding compounding,
255
                        Frequency frequency,
256
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
257
                        Date settlementDate = Date(),
258
                        Date npvDate = Date());
259
        //! Implied internal rate of return.
260
        /*! The function verifies
261
            the theoretical existence of an IRR and numerically
262
            establishes the IRR to the desired precision.
263
        */
264
        static Rate yield(const Leg& leg,
265
                          Real npv,
266
                          const DayCounter& dayCounter,
267
                          Compounding compounding,
268
                          Frequency frequency,
269
                          const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
270
                          Date settlementDate = Date(),
271
                          Date npvDate = Date(),
272
                          Real accuracy = 1.0e-10,
273
                          Size maxIterations = 100,
274
                          Rate guess = 0.05);
275
276
        template <typename Solver>
277
        static Rate yield(const Solver& solver,
278
                          const Leg& leg,
279
                          Real npv,
280
                          const DayCounter& dayCounter,
281
                          Compounding compounding,
282
                          Frequency frequency,
283
                          const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
284
                          Date settlementDate = Date(),
285
                          Date npvDate = Date(),
286
                          Real accuracy = 1.0e-10,
287
0
                          Rate guess = 0.05) {
288
0
            IrrFinder objFunction(leg, npv, dayCounter, compounding,
289
0
                                  frequency, includeSettlementDateFlows,
290
0
                                  settlementDate, npvDate);
291
0
            return solver.solve(objFunction, accuracy, guess, guess/10.0);
292
0
        }
293
294
        //! Cash-flow duration.
295
        /*! The simple duration of a string of cash flows is defined as
296
            \f[
297
            D_{\mathrm{simple}} = \frac{\sum t_i c_i B(t_i)}{\sum c_i B(t_i)}
298
            \f]
299
            where \f$ c_i \f$ is the amount of the \f$ i \f$-th cash
300
            flow, \f$ t_i \f$ is its payment time, and \f$ B(t_i) \f$
301
            is the corresponding discount according to the passed yield.
302
303
            The modified duration is defined as
304
            \f[
305
            D_{\mathrm{modified}} = -\frac{1}{P} \frac{\partial P}{\partial y}
306
            \f]
307
            where \f$ P \f$ is the present value of the cash flows
308
            according to the given IRR \f$ y \f$.
309
310
            The Macaulay duration is defined for a compounded IRR as
311
            \f[
312
            D_{\mathrm{Macaulay}} = \left( 1 + \frac{y}{N} \right)
313
                                    D_{\mathrm{modified}}
314
            \f]
315
            where \f$ y \f$ is the IRR and \f$ N \f$ is the number of
316
            cash flows per year.
317
        */
318
        static Time duration(const Leg& leg,
319
                             const InterestRate& yield,
320
                             Duration::Type type,
321
                             const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
322
                             Date settlementDate = Date(),
323
                             Date npvDate = Date());
324
        static Time duration(const Leg& leg,
325
                             Rate yield,
326
                             const DayCounter& dayCounter,
327
                             Compounding compounding,
328
                             Frequency frequency,
329
                             Duration::Type type,
330
                             const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
331
                             Date settlementDate = Date(),
332
                             Date npvDate = Date());
333
334
        //! Cash-flow convexity
335
        /*! The convexity of a string of cash flows is defined as
336
            \f[
337
            C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2}
338
            \f]
339
            where \f$ P \f$ is the present value of the cash flows
340
            according to the given IRR \f$ y \f$.
341
        */
342
        static Real convexity(const Leg& leg,
343
                              const InterestRate& yield,
344
                              const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
345
                              Date settlementDate = Date(),
346
                              Date npvDate = Date());
347
        static Real convexity(const Leg& leg,
348
                              Rate yield,
349
                              const DayCounter& dayCounter,
350
                              Compounding compounding,
351
                              Frequency frequency,
352
                              const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
353
                              Date settlementDate = Date(),
354
                              Date npvDate = Date());
355
356
        //! Basis-point value
357
        /*! Obtained by setting dy = 0.0001 in the 2nd-order Taylor
358
            series expansion.
359
        */
360
        static Real basisPointValue(const Leg& leg,
361
                                    const InterestRate& yield,
362
                                    const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
363
                                    Date settlementDate = Date(),
364
                                    Date npvDate = Date());
365
        static Real basisPointValue(const Leg& leg,
366
                                    Rate yield,
367
                                    const DayCounter& dayCounter,
368
                                    Compounding compounding,
369
                                    Frequency frequency,
370
                                    const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
371
                                    Date settlementDate = Date(),
372
                                    Date npvDate = Date());
373
374
        //! Yield value of a basis point
375
        /*! The yield value of a one basis point change in price is
376
            the derivative of the yield with respect to the price
377
            multiplied by 0.01
378
        */
379
        static Real yieldValueBasisPoint(const Leg& leg,
380
                                         const InterestRate& yield,
381
                                         const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
382
                                         Date settlementDate = Date(),
383
                                         Date npvDate = Date());
384
        static Real yieldValueBasisPoint(const Leg& leg,
385
                                         Rate yield,
386
                                         const DayCounter& dayCounter,
387
                                         Compounding compounding,
388
                                         Frequency frequency,
389
                                         const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
390
                                         Date settlementDate = Date(),
391
                                         Date npvDate = Date());
392
        //@}
393
394
        //! \name Z-spread functions
395
        /*! For details on z-spread refer to:
396
            "Credit Spreads Explained", Lehman Brothers European Fixed
397
            Income Research - March 2004, D. O'Kane
398
        */
399
        //@{
400
        //! NPV of the cash flows.
401
        /*! The NPV is the sum of the cash flows, each discounted
402
            according to the z-spreaded term structure.  The spread
403
            is expressed in terms of the underlying curve's day counter.
404
        */
405
        static Real npv(const Leg& leg,
406
                        const ext::shared_ptr<YieldTermStructure>& discount,
407
                        Spread zSpread,
408
                        Compounding compounding,
409
                        Frequency frequency,
410
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
411
                        Date settlementDate = Date(),
412
                        Date npvDate = Date());
413
        /*! \deprecated Use the overload without a day counter.
414
                        Deprecated in version 1.42.
415
        */
416
        [[deprecated("Use the overload without a day counter")]]
417
        static Real npv(const Leg& leg,
418
                        const ext::shared_ptr<YieldTermStructure>& discount,
419
                        Spread zSpread,
420
                        const DayCounter& dayCounter,
421
                        Compounding compounding,
422
                        Frequency frequency,
423
                        const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
424
                        Date settlementDate = Date(),
425
                        Date npvDate = Date());
426
        //! implied Z-spread.
427
        static Spread zSpread(const Leg& leg,
428
                              Real npv,
429
                              const ext::shared_ptr<YieldTermStructure>&,
430
                              Compounding compounding,
431
                              Frequency frequency,
432
                              const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
433
                              Date settlementDate = Date(),
434
                              Date npvDate = Date(),
435
                              Real accuracy = 1.0e-10,
436
                              Size maxIterations = 100,
437
                              Rate guess = 0.0);
438
        /*! \deprecated Use the overload without a day counter.
439
                        Deprecated in version 1.42.
440
        */
441
        [[deprecated("Use the overload without a day counter")]]
442
        static Spread zSpread(const Leg& leg,
443
                              Real npv,
444
                              const ext::shared_ptr<YieldTermStructure>&,
445
                              const DayCounter& dayCounter,
446
                              Compounding compounding,
447
                              Frequency frequency,
448
                              const ext::optional<bool>& includeSettlementDateFlows = ext::nullopt,
449
                              Date settlementDate = Date(),
450
                              Date npvDate = Date(),
451
                              Real accuracy = 1.0e-10,
452
                              Size maxIterations = 100,
453
                              Rate guess = 0.0);
454
        //@}
455
456
    };
457
458
}
459
460
#endif