Coverage Report

Created: 2026-02-03 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/termstructures/yield/ratehelpers.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5
 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 StatPro Italia srl
6
 Copyright (C) 2007, 2008, 2009, 2015 Ferdinando Ametrano
7
 Copyright (C) 2007, 2009 Roland Lichters
8
 Copyright (C) 2015 Maddalena Zanzi
9
 Copyright (C) 2015 Paolo Mazzocchi
10
 Copyright (C) 2018 Matthias Lungwitz
11
12
 This file is part of QuantLib, a free-software/open-source library
13
 for financial quantitative analysts and developers - http://quantlib.org/
14
15
 QuantLib is free software: you can redistribute it and/or modify it
16
 under the terms of the QuantLib license.  You should have received a
17
 copy of the license along with this program; if not, please email
18
 <quantlib-dev@lists.sf.net>. The license is also available online at
19
 <https://www.quantlib.org/license.shtml>.
20
21
 This program is distributed in the hope that it will be useful, but WITHOUT
22
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23
 FOR A PARTICULAR PURPOSE.  See the license for more details.
24
*/
25
26
/*! \file ratehelpers.hpp
27
    \brief deposit, FRA, futures, and various swap rate helpers
28
*/
29
30
#ifndef quantlib_ratehelpers_hpp
31
#define quantlib_ratehelpers_hpp
32
33
#include <ql/termstructures/bootstraphelper.hpp>
34
#include <ql/instruments/vanillaswap.hpp>
35
#include <ql/instruments/bmaswap.hpp>
36
#include <ql/instruments/futures.hpp>
37
#include <ql/time/calendar.hpp>
38
#include <ql/time/daycounter.hpp>
39
#include <ql/optional.hpp>
40
41
namespace QuantLib {
42
43
    class SwapIndex;
44
    class Quote;
45
46
    typedef BootstrapHelper<YieldTermStructure> RateHelper;
47
    typedef RelativeDateBootstrapHelper<YieldTermStructure>
48
                                                        RelativeDateRateHelper;
49
50
    //! Rate helper for bootstrapping over IborIndex futures prices
51
    class FuturesRateHelper : public RateHelper {
52
      public:
53
        FuturesRateHelper(const std::variant<Real, Handle<Quote>>& price,
54
                          const Date& iborStartDate,
55
                          Natural lengthInMonths,
56
                          const Calendar& calendar,
57
                          BusinessDayConvention convention,
58
                          bool endOfMonth,
59
                          const DayCounter& dayCounter,
60
                          const std::variant<Real, Handle<Quote>>& convexityAdjustment = 0.0,
61
                          Futures::Type type = Futures::IMM);
62
        FuturesRateHelper(const std::variant<Real, Handle<Quote>>& price,
63
                          const Date& iborStartDate,
64
                          const Date& iborEndDate,
65
                          const DayCounter& dayCounter,
66
                          const std::variant<Real, Handle<Quote>>& convexityAdjustment = 0.0,
67
                          Futures::Type type = Futures::IMM);
68
        FuturesRateHelper(const std::variant<Real, Handle<Quote>>& price,
69
                          const Date& iborStartDate,
70
                          const ext::shared_ptr<IborIndex>& iborIndex,
71
                          const std::variant<Real, Handle<Quote>>& convexityAdjustment = 0.0,
72
                          Futures::Type type = Futures::IMM);
73
        //! \name RateHelper interface
74
        //@{
75
        Real impliedQuote() const override;
76
        //@}
77
        //! \name FuturesRateHelper inspectors
78
        //@{
79
        Real convexityAdjustment() const;
80
        //@}
81
        //! \name Visitability
82
        //@{
83
        void accept(AcyclicVisitor&) override;
84
        //@}
85
      private:
86
        Time yearFraction_;
87
        Handle<Quote> convAdj_;
88
    };
89
90
91
    //! Rate helper for bootstrapping over deposit rates
92
    class DepositRateHelper : public RelativeDateRateHelper {
93
      public:
94
        DepositRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
95
                          const Period& tenor,
96
                          Natural fixingDays,
97
                          const Calendar& calendar,
98
                          BusinessDayConvention convention,
99
                          bool endOfMonth,
100
                          const DayCounter& dayCounter);
101
        DepositRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
102
                          const ext::shared_ptr<IborIndex>& iborIndex);
103
        DepositRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
104
                          Date fixingDate,
105
                          const ext::shared_ptr<IborIndex>& iborIndex);
106
        //! \name RateHelper interface
107
        //@{
108
        Real impliedQuote() const override;
109
        void setTermStructure(YieldTermStructure*) override;
110
        //@}
111
        //! \name Visitability
112
        //@{
113
        void accept(AcyclicVisitor&) override;
114
        //@}
115
      private:
116
        void initializeDates() override;
117
        Date fixingDate_;
118
        ext::shared_ptr<IborIndex> iborIndex_;
119
        RelinkableHandle<YieldTermStructure> termStructureHandle_;
120
    };
121
122
123
    //! Rate helper for bootstrapping over %FRA rates
124
    class FraRateHelper : public RelativeDateRateHelper {
125
      public:
126
        FraRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
127
                      Natural monthsToStart,
128
                      Natural monthsToEnd,
129
                      Natural fixingDays,
130
                      const Calendar& calendar,
131
                      BusinessDayConvention convention,
132
                      bool endOfMonth,
133
                      const DayCounter& dayCounter,
134
                      Pillar::Choice pillar = Pillar::LastRelevantDate,
135
                      Date customPillarDate = Date(),
136
                      bool useIndexedCoupon = true);
137
        FraRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
138
                      Natural monthsToStart,
139
                      const ext::shared_ptr<IborIndex>& iborIndex,
140
                      Pillar::Choice pillar = Pillar::LastRelevantDate,
141
                      Date customPillarDate = Date(),
142
                      bool useIndexedCoupon = true);
143
        FraRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
144
                      Period periodToStart,
145
                      Natural lengthInMonths,
146
                      Natural fixingDays,
147
                      const Calendar& calendar,
148
                      BusinessDayConvention convention,
149
                      bool endOfMonth,
150
                      const DayCounter& dayCounter,
151
                      Pillar::Choice pillar = Pillar::LastRelevantDate,
152
                      Date customPillarDate = Date(),
153
                      bool useIndexedCoupon = true);
154
        FraRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
155
                      Period periodToStart,
156
                      const ext::shared_ptr<IborIndex>& iborIndex,
157
                      Pillar::Choice pillar = Pillar::LastRelevantDate,
158
                      Date customPillarDate = Date(),
159
                      bool useIndexedCoupon = true);
160
        FraRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
161
                      Natural immOffsetStart,
162
                      Natural immOffsetEnd,
163
                      const ext::shared_ptr<IborIndex>& iborIndex,
164
                      Pillar::Choice pillar = Pillar::LastRelevantDate,
165
                      Date customPillarDate = Date(),
166
                      bool useIndexedCoupon = true);
167
        FraRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
168
                      Date startDate,
169
                      Date endDate,
170
                      const ext::shared_ptr<IborIndex>& iborIndex,
171
                      Pillar::Choice pillar = Pillar::LastRelevantDate,
172
                      Date customPillarDate = Date(),
173
                      bool useIndexedCoupon = true);
174
        //! \name RateHelper interface
175
        //@{
176
        Real impliedQuote() const override;
177
        void setTermStructure(YieldTermStructure*) override;
178
        //@}
179
        //! \name Visitability
180
        //@{
181
        void accept(AcyclicVisitor&) override;
182
        //@}
183
      private:
184
        void initializeDates() override;
185
        Date fixingDate_;
186
        ext::optional<Period> periodToStart_;
187
        ext::optional<Natural> immOffsetStart_, immOffsetEnd_;
188
        Pillar::Choice pillarChoice_;
189
        ext::shared_ptr<IborIndex> iborIndex_;
190
        RelinkableHandle<YieldTermStructure> termStructureHandle_;
191
        bool useIndexedCoupon_;
192
        Real spanningTime_;
193
    };
194
195
196
    //! Rate helper for bootstrapping over swap rates
197
    /*! \todo use input SwapIndex to create the swap */
198
    class SwapRateHelper : public RelativeDateRateHelper {
199
      public:
200
        SwapRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
201
                       const ext::shared_ptr<SwapIndex>& swapIndex,
202
                       Handle<Quote> spread = {},
203
                       const Period& fwdStart = 0 * Days,
204
                       // exogenous discounting curve
205
                       Handle<YieldTermStructure> discountingCurve = {},
206
                       Pillar::Choice pillar = Pillar::LastRelevantDate,
207
                       Date customPillarDate = Date(),
208
                       bool endOfMonth = false,
209
                       const ext::optional<bool>& useIndexedCoupons = ext::nullopt);
210
        SwapRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
211
                       const Period& tenor,
212
                       Calendar calendar,
213
                       // fixed leg
214
                       Frequency fixedFrequency,
215
                       BusinessDayConvention fixedConvention,
216
                       DayCounter fixedDayCount,
217
                       // floating leg
218
                       const ext::shared_ptr<IborIndex>& iborIndex,
219
                       Handle<Quote> spread = {},
220
                       const Period& fwdStart = 0 * Days,
221
                       // exogenous discounting curve
222
                       Handle<YieldTermStructure> discountingCurve = {},
223
                       Natural settlementDays = Null<Natural>(),
224
                       Pillar::Choice pillar = Pillar::LastRelevantDate,
225
                       Date customPillarDate = Date(),
226
                       bool endOfMonth = false,
227
                       const ext::optional<bool>& useIndexedCoupons = ext::nullopt,
228
                       const ext::optional<BusinessDayConvention>& floatConvention = ext::nullopt);
229
        SwapRateHelper(const std::variant<Rate, Handle<Quote>>& rate,
230
                       const Date& startDate,
231
                       const Date& endDate,
232
                       Calendar calendar,
233
                       // fixed leg
234
                       Frequency fixedFrequency,
235
                       BusinessDayConvention fixedConvention,
236
                       DayCounter fixedDayCount,
237
                       // floating leg
238
                       const ext::shared_ptr<IborIndex>& iborIndex,
239
                       Handle<Quote> spread = {},
240
                       // exogenous discounting curve
241
                       Handle<YieldTermStructure> discountingCurve = {},
242
                       Pillar::Choice pillar = Pillar::LastRelevantDate,
243
                       Date customPillarDate = Date(),
244
                       bool endOfMonth = false,
245
                       const ext::optional<bool>& useIndexedCoupons = ext::nullopt,
246
                       const ext::optional<BusinessDayConvention>& floatConvention = ext::nullopt);
247
        //! \name RateHelper interface
248
        //@{
249
        Real impliedQuote() const override;
250
        void setTermStructure(YieldTermStructure*) override;
251
        //@}
252
        //! \name SwapRateHelper inspectors
253
        //@{
254
        Spread spread() const;
255
        // NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
256
        ext::shared_ptr<VanillaSwap> swap() const;
257
        const Period& forwardStart() const;
258
        //@}
259
        //! \name Visitability
260
        //@{
261
        void accept(AcyclicVisitor&) override;
262
        //@}
263
      protected:
264
        void initialize(const ext::shared_ptr<IborIndex>& iborIndex,
265
                        Date customPillarDate);
266
        void initializeDates() override;
267
        Natural settlementDays_;
268
        Period tenor_;
269
        Date startDate_, endDate_;
270
        Pillar::Choice pillarChoice_;
271
        Calendar calendar_;
272
        BusinessDayConvention fixedConvention_;
273
        Frequency fixedFrequency_;
274
        DayCounter fixedDayCount_;
275
        ext::shared_ptr<IborIndex> iborIndex_;
276
        ext::shared_ptr<VanillaSwap> swap_;
277
        RelinkableHandle<YieldTermStructure> termStructureHandle_;
278
        Handle<Quote> spread_;
279
        bool endOfMonth_;
280
        Period fwdStart_;
281
        Handle<YieldTermStructure> discountHandle_;
282
        RelinkableHandle<YieldTermStructure> discountRelinkableHandle_;
283
        ext::optional<bool> useIndexedCoupons_;
284
        ext::optional<BusinessDayConvention> floatConvention_;
285
    };
286
287
288
    //! Rate helper for bootstrapping over BMA swap rates
289
    class BMASwapRateHelper : public RelativeDateRateHelper {
290
      public:
291
        BMASwapRateHelper(const Handle<Quote>& liborFraction,
292
                          const Period& tenor, // swap maturity
293
                          Natural settlementDays,
294
                          Calendar calendar,
295
                          // bma leg
296
                          const Period& bmaPeriod,
297
                          BusinessDayConvention bmaConvention,
298
                          DayCounter bmaDayCount,
299
                          ext::shared_ptr<BMAIndex> bmaIndex,
300
                          // ibor leg
301
                          ext::shared_ptr<IborIndex> index);
302
        //! \name RateHelper interface
303
        //@{
304
        Real impliedQuote() const override;
305
        void setTermStructure(YieldTermStructure*) override;
306
        //@}
307
        //! \name Visitability
308
        //@{
309
        void accept(AcyclicVisitor&) override;
310
        //@}
311
    protected:
312
      void initializeDates() override;
313
      Period tenor_;
314
      Natural settlementDays_;
315
      Calendar calendar_;
316
      Period bmaPeriod_;
317
      BusinessDayConvention bmaConvention_;
318
      DayCounter bmaDayCount_;
319
      ext::shared_ptr<BMAIndex> bmaIndex_;
320
      ext::shared_ptr<IborIndex> iborIndex_;
321
322
      ext::shared_ptr<BMASwap> swap_;
323
      RelinkableHandle<YieldTermStructure> termStructureHandle_;
324
    };
325
326
327
    //! Rate helper for bootstrapping over Fx Swap rates
328
    /*! The forward is given by `fwdFx = spotFx + fwdPoint`.
329
330
        `isFxBaseCurrencyCollateralCurrency` indicates if the base
331
        currency of the FX currency pair is the one used as collateral.
332
333
        `calendar` is usually the joint calendar of the two currencies
334
        in the pair.
335
336
        `tradingCalendar` can be used when the cross pairs don't
337
        include the currency of the business center (usually USD; the
338
        corresponding calendar is `UnitedStates`).  If given, it will
339
        be used for adjusting the earliest settlement date and for
340
        setting the latest date. Due to FX spot market conventions, it
341
        is not sufficient to pass a JointCalendar with UnitedStates
342
        included as `calendar`; with regard the earliest date, this
343
        calendar is only used in case the spot date of the two
344
        currencies is not a US business day.
345
346
        \warning The ON fx swaps can be achieved by setting
347
                 `fixingDays` to 0 and using a tenor of '1d'. The same
348
                 tenor should be used for TN swaps, with `fixingDays`
349
                 set to 1.  However, handling ON and TN swaps for
350
                 cross rates without USD is not trivial and should be
351
                 treated with caution. If today is a US holiday, ON
352
                 trade is not possible. If tomorrow is a US Holiday,
353
                 the ON trade will be at least two business days long
354
                 in the other countries and the TN trade will not
355
                 exist. In such cases, if this helper is used for
356
                 curve construction, probably it is safer not to pass
357
                 a trading calendar to the ON and TN helpers and
358
                 provide fwdPoints that will yield proper level of
359
                 discount factors.
360
    */
361
    class FxSwapRateHelper : public RelativeDateRateHelper {
362
      public:
363
        FxSwapRateHelper(const Handle<Quote>& fwdPoint,
364
                         Handle<Quote> spotFx,
365
                         const Period& tenor,
366
                         Natural fixingDays,
367
                         Calendar calendar,
368
                         BusinessDayConvention convention,
369
                         bool endOfMonth,
370
                         bool isFxBaseCurrencyCollateralCurrency,
371
                         Handle<YieldTermStructure> collateralCurve,
372
                         Calendar tradingCalendar = Calendar());
373
        FxSwapRateHelper(const Handle<Quote>& fwdPoint,
374
                         Handle<Quote> spotFx,
375
                         const Date& startDate,
376
                         const Date& endDate,
377
                         bool isFxBaseCurrencyCollateralCurrency,
378
                         Handle<YieldTermStructure> collateralCurve);
379
        //! \name RateHelper interface
380
        //@{
381
        Real impliedQuote() const override;
382
        void setTermStructure(YieldTermStructure*) override;
383
        //@}
384
        //! \name FxSwapRateHelper inspectors
385
        //@{
386
0
        Real spot() const { return spot_->value(); }
387
0
        Period tenor() const { return tenor_; }
388
0
        Natural fixingDays() const { return fixingDays_; }
389
0
        Calendar calendar() const { return cal_; }
390
0
        BusinessDayConvention businessDayConvention() const { return conv_; }
391
0
        bool endOfMonth() const { return eom_; }
392
0
        bool isFxBaseCurrencyCollateralCurrency() const {
393
0
                                return isFxBaseCurrencyCollateralCurrency_; }
394
0
        Calendar tradingCalendar() const { return tradingCalendar_; }
395
0
        Calendar adjustmentCalendar() const { return jointCalendar_; }
396
        //@}
397
        //! \name Visitability
398
        //@{
399
        void accept(AcyclicVisitor&) override;
400
        //@}
401
    private:
402
      void initializeDates() override;
403
      Handle<Quote> spot_;
404
      Period tenor_;
405
      Natural fixingDays_;
406
      Calendar cal_;
407
      BusinessDayConvention conv_;
408
      bool eom_;
409
      bool isFxBaseCurrencyCollateralCurrency_;
410
411
      RelinkableHandle<YieldTermStructure> termStructureHandle_;
412
413
      Handle<YieldTermStructure> collHandle_;
414
      RelinkableHandle<YieldTermStructure> collRelinkableHandle_;
415
416
      Calendar tradingCalendar_;
417
      Calendar jointCalendar_;
418
    };
419
420
    // inline
421
422
0
    inline Spread SwapRateHelper::spread() const {
423
0
        return spread_.empty() ? 0.0 : spread_->value();
424
0
    }
425
426
    // NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
427
0
    inline ext::shared_ptr<VanillaSwap> SwapRateHelper::swap() const {
428
0
        return swap_;
429
0
    }
430
431
0
    inline const Period& SwapRateHelper::forwardStart() const {
432
0
        return fwdStart_;
433
0
    }
434
435
}
436
437
#endif