Coverage Report

Created: 2025-11-04 06:12

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
        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
    template <class TS>
127
    class RelativeDateBootstrapHelper : public BootstrapHelper<TS> {
128
      public:
129
        explicit RelativeDateBootstrapHelper(
130
            const std::variant<Spread, Handle<Quote>>& quote,
131
            bool updateDates = true);
132
133
        //! \name Observer interface
134
        //@{
135
0
        void update() override {
136
0
            if (updateDates_ && evaluationDate_ != Settings::instance().evaluationDate()) {
137
0
                evaluationDate_ = Settings::instance().evaluationDate();
138
0
                initializeDates();
139
0
            }
140
0
            BootstrapHelper<TS>::update();
141
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()
142
        //@}
143
      protected:
144
        virtual void initializeDates() = 0;
145
        Date evaluationDate_;
146
        bool updateDates_;
147
    };
148
149
    // template definitions
150
151
    template <class TS>
152
    BootstrapHelper<TS>::BootstrapHelper(const std::variant<Spread, Handle<Quote>>& quote)
153
0
    : quote_(handleFromVariant(quote)), termStructure_(nullptr) {
154
0
        registerWith(quote_);
155
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&)
156
157
    template <class TS>
158
0
    void BootstrapHelper<TS>::setTermStructure(TS* t) {
159
0
        QL_REQUIRE(t != nullptr, "null term structure given");
160
0
        termStructure_ = t;
161
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*)
162
163
    template <class TS>
164
0
    Date BootstrapHelper<TS>::earliestDate() const {
165
0
        return earliestDate_;
166
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
167
168
    template <class TS>
169
0
    Date BootstrapHelper<TS>::maturityDate() const {
170
0
        if (maturityDate_ == Date())
171
0
            return latestRelevantDate();
172
0
        return maturityDate_;
173
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
174
175
    template <class TS>
176
0
    Date BootstrapHelper<TS>::latestRelevantDate() const {
177
0
        if (latestRelevantDate_ == Date())
178
0
            return latestDate();
179
0
        return latestRelevantDate_;
180
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
181
182
    template <class TS>
183
0
    Date BootstrapHelper<TS>::pillarDate() const {
184
0
        if (pillarDate_==Date())
185
0
            return latestDate();
186
0
        return pillarDate_;
187
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
188
189
    template <class TS>
190
0
    Date BootstrapHelper<TS>::latestDate() const {
191
0
        if (latestDate_ == Date())
192
0
            return pillarDate_;
193
0
        return latestDate_;
194
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
195
196
    template <class TS>
197
0
    void BootstrapHelper<TS>::update() {
198
0
        notifyObservers();
199
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()
200
201
    template <class TS>
202
0
    void BootstrapHelper<TS>::accept(AcyclicVisitor& v) {
203
0
        auto* v1 = dynamic_cast<Visitor<BootstrapHelper<TS> >*>(&v);
204
0
        if (v1 != nullptr)
205
0
            v1->visit(*this);
206
0
        else
207
0
            QL_FAIL("not a bootstrap-helper visitor");
208
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&)
209
210
211
    template <class TS>
212
    RelativeDateBootstrapHelper<TS>::RelativeDateBootstrapHelper(
213
        const std::variant<Spread, Handle<Quote>>& quote, bool updateDates)
214
0
    : BootstrapHelper<TS>(quote), updateDates_(updateDates) {
215
0
        if (updateDates) {
216
0
            this->registerWith(Settings::instance().evaluationDate());
217
0
            evaluationDate_ = Settings::instance().evaluationDate();
218
0
        }
219
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)
220
221
222
    inline std::ostream& operator<<(std::ostream& out,
223
0
                                    Pillar::Choice t) {
224
0
        switch (t) {
225
0
        case Pillar::MaturityDate:
226
0
            return out << "MaturityPillarDate";
227
0
        case Pillar::LastRelevantDate:
228
0
            return out << "LastRelevantPillarDate";
229
0
        case Pillar::CustomDate:
230
0
            return out << "CustomPillarDate";
231
0
        default:
232
0
            QL_FAIL("unknown Pillar::Choice(" << Integer(t) << ")");
233
0
        }
234
0
    }
235
236
    namespace detail {
237
238
        class BootstrapHelperSorter {
239
          public:
240
            template <class Helper>
241
            bool operator()(
242
                    const ext::shared_ptr<Helper>& h1,
243
                    const ext::shared_ptr<Helper>& h2) const {
244
                return (h1->pillarDate() < h2->pillarDate());
245
            }
246
        };
247
248
    }
249
250
}
251
252
#endif