Coverage Report

Created: 2026-06-08 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/termstructures/bootstraphelper.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, 2007, 2008 StatPro Italia srl
5
 Copyright (C) 2007, 2009, 2015 Ferdinando Ametrano
6
 Copyright (C) 2015 Paolo Mazzocchi
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 bootstraphelper.hpp
23
    \brief base helper class used for bootstrapping
24
*/
25
26
#ifndef quantlib_bootstrap_helper_hpp
27
#define quantlib_bootstrap_helper_hpp
28
29
#include <ql/handle.hpp>
30
#include <ql/patterns/observable.hpp>
31
#include <ql/patterns/visitor.hpp>
32
#include <ql/quote.hpp>
33
#include <ql/quotes/simplequote.hpp>
34
#include <ql/settings.hpp>
35
#include <ql/time/date.hpp>
36
#include <utility>
37
38
namespace QuantLib {
39
40
    struct Pillar {
41
        //! Alternatives ways of determining the pillar date
42
        enum Choice {
43
            MaturityDate,     //! instruments maturity date
44
            LastRelevantDate, //! last date relevant for instrument pricing
45
            CustomDate        //! custom choice
46
        };
47
    };
48
49
    std::ostream& operator<<(std::ostream& out, Pillar::Choice type);
50
51
    //! Base helper class for bootstrapping
52
    /*! This class provides an abstraction for the instruments used to
53
        bootstrap a term structure.
54
55
        It is advised that a bootstrap helper for an instrument
56
        contains an instance of the actual instrument class to ensure
57
        consistancy between the algorithms used during bootstrapping
58
        and later instrument pricing. This is not yet fully enforced
59
        in the available bootstrap helpers.
60
    */
61
    template <class TS>
62
    class BootstrapHelper : public Observer, public Observable {
63
      public:
64
        explicit BootstrapHelper(const std::variant<Spread, Handle<Quote>>& quote);
65
0
        ~BootstrapHelper() override = default;
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::~BootstrapHelper()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::~BootstrapHelper()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::~BootstrapHelper()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::~BootstrapHelper()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::~BootstrapHelper()
66
        //! \name BootstrapHelper interface
67
        //@{
68
0
        const Handle<Quote>& quote() const { return quote_; }
69
        virtual Real impliedQuote() const = 0;
70
0
        Real quoteError() const { return quote_->value() - impliedQuote(); }
71
        //! sets the term structure to be used for pricing
72
        /*! \warning Being a pointer and not a shared_ptr, the term
73
                     structure is not guaranteed to remain allocated
74
                     for the whole life of the rate helper. It is
75
                     responsibility of the programmer to ensure that
76
                     the pointer remains valid. It is advised that
77
                     this method is called only inside the term
78
                     structure being bootstrapped, setting the pointer
79
                     to <b>this</b>, i.e., the term structure itself.
80
        */
81
        virtual void setTermStructure(TS*);
82
83
        //! earliest relevant date
84
        /*! The earliest date at which data are needed by the
85
            helper in order to provide a quote.
86
        */
87
        virtual Date earliestDate() const;
88
89
        //! instrument's maturity date
90
        virtual Date maturityDate() const;
91
92
        //! latest relevant date
93
        /*! The latest date at which data are needed by the helper
94
            in order to provide a quote. It does not necessarily
95
            equal the maturity of the underlying instrument.
96
        */
97
        virtual Date latestRelevantDate() const;
98
99
        //! pillar date
100
        virtual Date pillarDate() const;
101
102
        //! latest date
103
        /*! equal to pillarDate()
104
        */
105
        virtual Date latestDate() const;
106
        //@}
107
        //! \name Observer interface
108
        //@{
109
        void update() override;
110
        //@}
111
        //! \name Visitability
112
        //@{
113
        virtual void accept(AcyclicVisitor&);
114
        //@}
115
      protected:
116
        Handle<Quote> quote_;
117
        TS* termStructure_;
118
        Date earliestDate_, latestDate_;
119
        Date maturityDate_, latestRelevantDate_, pillarDate_;
120
    };
121
122
    //! Bootstrap helper with date schedule relative to global evaluation date
123
    /*! Derived classes must takes care of rebuilding the date schedule when
124
        the global evaluation date changes.
125
126
        \warning Using this helper together with a bootstrapped curve constructed 
127
                 with a fixed reference date causes the curve to re-bootstrap on 
128
                 every evaluation date change, even though the result is identical. 
129
                 This is because the helper registers with the global evaluation 
130
                 date and notifies the curve on every change. To avoid the unnecessary 
131
                 work, either:
132
                 - call \c freeze() on the curve after the initial bootstrap; 
133
                 - use the fixed-effective-date constructors of the helpers so that 
134
                 they do not register with the global evaluation date at all.
135
    */
136
    template <class TS>
137
    class RelativeDateBootstrapHelper : public BootstrapHelper<TS> {
138
      public:
139
        explicit RelativeDateBootstrapHelper(
140
            const std::variant<Spread, Handle<Quote>>& quote,
141
            bool updateDates = true);
142
143
        //! \name Observer interface
144
        //@{
145
0
        void update() override {
146
0
            if (updateDates_ && evaluationDate_ != Settings::instance().evaluationDate()) {
147
0
                evaluationDate_ = Settings::instance().evaluationDate();
148
0
                initializeDates();
149
0
            }
150
0
            BootstrapHelper<TS>::update();
151
0
        }
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::YieldTermStructure>::update()
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::update()
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::ZeroInflationTermStructure>::update()
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::YoYInflationTermStructure>::update()
152
        //@}
153
      protected:
154
        virtual void initializeDates() = 0;
155
        Date evaluationDate_;
156
        bool updateDates_;
157
    };
158
159
    // template definitions
160
161
    template <class TS>
162
    BootstrapHelper<TS>::BootstrapHelper(const std::variant<Spread, Handle<Quote>>& quote)
163
0
    : quote_(handleFromVariant(quote)), termStructure_(nullptr) {
164
0
        registerWith(quote_);
165
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::BootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::BootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::BootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::BootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::BootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&)
166
167
    template <class TS>
168
0
    void BootstrapHelper<TS>::setTermStructure(TS* t) {
169
0
        QL_REQUIRE(t != nullptr, "null term structure given");
170
0
        termStructure_ = t;
171
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::setTermStructure(QuantLib::DefaultProbabilityTermStructure*)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::setTermStructure(QuantLib::YoYOptionletVolatilitySurface*)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::setTermStructure(QuantLib::YieldTermStructure*)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::setTermStructure(QuantLib::ZeroInflationTermStructure*)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::setTermStructure(QuantLib::YoYInflationTermStructure*)
172
173
    template <class TS>
174
0
    Date BootstrapHelper<TS>::earliestDate() const {
175
0
        return earliestDate_;
176
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::earliestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::earliestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::earliestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::earliestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::earliestDate() const
177
178
    template <class TS>
179
0
    Date BootstrapHelper<TS>::maturityDate() const {
180
0
        if (maturityDate_ == Date())
181
0
            return latestRelevantDate();
182
0
        return maturityDate_;
183
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::maturityDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::maturityDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::maturityDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::maturityDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::maturityDate() const
184
185
    template <class TS>
186
0
    Date BootstrapHelper<TS>::latestRelevantDate() const {
187
0
        if (latestRelevantDate_ == Date())
188
0
            return latestDate();
189
0
        return latestRelevantDate_;
190
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::latestRelevantDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::latestRelevantDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::latestRelevantDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::latestRelevantDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::latestRelevantDate() const
191
192
    template <class TS>
193
0
    Date BootstrapHelper<TS>::pillarDate() const {
194
0
        if (pillarDate_==Date())
195
0
            return latestDate();
196
0
        return pillarDate_;
197
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::pillarDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::pillarDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::pillarDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::pillarDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::pillarDate() const
198
199
    template <class TS>
200
0
    Date BootstrapHelper<TS>::latestDate() const {
201
0
        if (latestDate_ == Date())
202
0
            return pillarDate_;
203
0
        return latestDate_;
204
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::latestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::latestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::latestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::latestDate() const
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::latestDate() const
205
206
    template <class TS>
207
0
    void BootstrapHelper<TS>::update() {
208
0
        notifyObservers();
209
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::update()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::update()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::update()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::update()
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::update()
210
211
    template <class TS>
212
0
    void BootstrapHelper<TS>::accept(AcyclicVisitor& v) {
213
0
        auto* v1 = dynamic_cast<Visitor<BootstrapHelper<TS> >*>(&v);
214
0
        if (v1 != nullptr)
215
0
            v1->visit(*this);
216
0
        else
217
0
            QL_FAIL("not a bootstrap-helper visitor");
218
0
    }
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::accept(QuantLib::AcyclicVisitor&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYOptionletVolatilitySurface>::accept(QuantLib::AcyclicVisitor&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YieldTermStructure>::accept(QuantLib::AcyclicVisitor&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure>::accept(QuantLib::AcyclicVisitor&)
Unexecuted instantiation: QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure>::accept(QuantLib::AcyclicVisitor&)
219
220
221
    template <class TS>
222
    RelativeDateBootstrapHelper<TS>::RelativeDateBootstrapHelper(
223
        const std::variant<Spread, Handle<Quote>>& quote, bool updateDates)
224
0
    : BootstrapHelper<TS>(quote), updateDates_(updateDates) {
225
0
        if (updateDates) {
226
0
            this->registerWith(Settings::instance().evaluationDate());
227
0
            evaluationDate_ = Settings::instance().evaluationDate();
228
0
        }
229
0
    }
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::YieldTermStructure>::RelativeDateBootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&, bool)
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::DefaultProbabilityTermStructure>::RelativeDateBootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&, bool)
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::ZeroInflationTermStructure>::RelativeDateBootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&, bool)
Unexecuted instantiation: QuantLib::RelativeDateBootstrapHelper<QuantLib::YoYInflationTermStructure>::RelativeDateBootstrapHelper(std::__1::variant<double, QuantLib::Handle<QuantLib::Quote> > const&, bool)
230
231
232
    inline std::ostream& operator<<(std::ostream& out,
233
0
                                    Pillar::Choice t) {
234
0
        switch (t) {
235
0
        case Pillar::MaturityDate:
236
0
            return out << "MaturityPillarDate";
237
0
        case Pillar::LastRelevantDate:
238
0
            return out << "LastRelevantPillarDate";
239
0
        case Pillar::CustomDate:
240
0
            return out << "CustomPillarDate";
241
0
        default:
242
0
            QL_FAIL("unknown Pillar::Choice(" << Integer(t) << ")");
243
0
        }
244
0
    }
245
246
    namespace detail {
247
248
        class BootstrapHelperSorter {
249
          public:
250
            template <class Helper>
251
            bool operator()(
252
                    const ext::shared_ptr<Helper>& h1,
253
                    const ext::shared_ptr<Helper>& h2) const {
254
                return (h1->pillarDate() < h2->pillarDate());
255
            }
256
        };
257
258
    }
259
260
}
261
262
#endif