• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lballabio / QuantLib / 31125815801

06 Aug 2026 05:59PM UTC coverage: 75.159% (+0.02%) from 75.142%
31125815801

Pull #2715

github

web-flow
Merge 18be57286 into 5608e3543
Pull Request #2715: Add DerivedTermStructure helper classes

39 of 46 new or added lines in 8 files covered. (84.78%)

4 existing lines in 2 files now uncovered.

60759 of 80841 relevant lines covered (75.16%)

8639286.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.25
/ql/termstructures/yieldtermstructure.cpp
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2

3
/*
4
 Copyright (C) 2004, 2009 Ferdinando Ametrano
5
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
6
 Copyright (C) 2003, 2004, 2005, 2006 StatPro Italia srl
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
#include <ql/termstructures/yieldtermstructure.hpp>
23
#include <ql/utilities/dataformatters.hpp>
24
#include <utility>
25

26
namespace QuantLib {
27

28
    namespace {
29
        // time interval used in finite differences
30
        const Time dt = 0.0001;
31
    }
32

33
    YieldTermStructure::YieldTermStructure(const DayCounter& dc) : TermStructure(dc) {}
127,218✔
34

35
    YieldTermStructure::YieldTermStructure(const Date& referenceDate,
524,555✔
36
                                           const Calendar& cal,
37
                                           const DayCounter& dc,
38
                                           std::vector<Handle<Quote> > jumps,
39
                                           const std::vector<Date>& jumpDates)
×
40
    : TermStructure(referenceDate, cal, dc), jumps_(std::move(jumps)), jumpDates_(jumpDates),
524,555✔
41
      jumpTimes_(jumpDates.size()), nJumps_(jumps_.size()) {
1,573,665✔
42
        setJumps(YieldTermStructure::referenceDate());
524,555✔
43
        for (Size i=0; i<nJumps_; ++i)
524,555✔
44
            registerWith(jumps_[i]);
×
45
    }
524,555✔
46

47
    YieldTermStructure::YieldTermStructure(Natural settlementDays,
3,327✔
48
                                           const Calendar& cal,
49
                                           const DayCounter& dc,
50
                                           std::vector<Handle<Quote> > jumps,
51
                                           const std::vector<Date>& jumpDates)
×
52
    : TermStructure(settlementDays, cal, dc), jumps_(std::move(jumps)), jumpDates_(jumpDates),
3,327✔
53
      jumpTimes_(jumpDates.size()), nJumps_(jumps_.size()) {
9,981✔
54
        setJumps(YieldTermStructure::referenceDate());
3,327✔
55
        for (Size i=0; i<nJumps_; ++i)
3,327✔
56
            registerWith(jumps_[i]);
×
57
    }
3,327✔
58

59
    void YieldTermStructure::setJumps(const Date& referenceDate) {
600,067✔
60
        if (jumpDates_.empty() && !jumps_.empty()) { // turn of year dates
600,067✔
61
            jumpDates_.resize(nJumps_);
×
62
            jumpTimes_.resize(nJumps_);
×
63
            Year y = referenceDate.year();
×
64
            for (Size i=0; i<nJumps_; ++i)
×
65
                jumpDates_[i] = Date(31, December, y+i);
×
66
        } else { // fixed dates
67
            QL_REQUIRE(jumpDates_.size()==nJumps_,
600,067✔
68
                       "mismatch between number of jumps (" << nJumps_ <<
69
                       ") and jump dates (" << jumpDates_.size() << ")");
70
        }
71
        for (Size i=0; i<nJumps_; ++i)
600,067✔
72
            jumpTimes_[i] = timeFromReference(jumpDates_[i]);
×
73
        latestReference_ = referenceDate;
600,067✔
74
    }
600,067✔
75

76
    DiscountFactor YieldTermStructure::discount(Time t,
1,572,205,818✔
77
                                                bool extrapolate) const {
78
        checkRange(t, extrapolate);
1,572,205,818✔
79

80
        if (jumps_.empty())
1,572,205,813✔
81
            return discountImpl(t);
1,572,205,813✔
82

83
        DiscountFactor jumpEffect = 1.0;
84
        for (Size i=0; i<nJumps_; ++i) {
×
85
            if (jumpTimes_[i]>0 && jumpTimes_[i]<t) {
×
86
                QL_REQUIRE(jumps_[i]->isValid(),
×
87
                           "invalid " << io::ordinal(i+1) << " jump quote");
88
                DiscountFactor thisJump = jumps_[i]->value();
×
89
                QL_REQUIRE(thisJump > 0.0,
×
90
                           "invalid " << io::ordinal(i+1) << " jump value: " <<
91
                           thisJump);
92
                jumpEffect *= thisJump;
×
93
            }
94
        }
95
        return jumpEffect * discountImpl(t);
×
96
    }
97

98
    InterestRate YieldTermStructure::zeroRate(const Date& d,
409,655✔
99
                                              const DayCounter& dayCounter,
100
                                              Compounding comp,
101
                                              Frequency freq,
102
                                              bool extrapolate) const {
103
        Time t = timeFromReference(d);
409,655✔
104
        if (t == 0) {
409,655✔
105
            Real compound = 1.0/discount(dt, extrapolate);
1,102✔
106
            // t has been calculated with a possibly different daycounter
107
            // but the difference should not matter for very small times
108
            return InterestRate::impliedRate(compound,
109
                                             dayCounter, comp, freq,
110
                                             dt);
1,102✔
111
        }
112
        Real compound = 1.0/discount(t, extrapolate);
408,553✔
113
        return InterestRate::impliedRate(compound,
114
                                         dayCounter, comp, freq,
115
                                         referenceDate(), d);
408,553✔
116
    }
117

118
    InterestRate YieldTermStructure::zeroRate(Time t,
910,221✔
119
                                              Compounding comp,
120
                                              Frequency freq,
121
                                              bool extrapolate) const {
122
        if (t==0.0) t = dt;
910,221✔
123
        Real compound = 1.0/discount(t, extrapolate);
910,221✔
124
        return InterestRate::impliedRate(compound,
125
                                         dayCounter(), comp, freq,
910,221✔
126
                                         t);
1,820,442✔
127
    }
128

129
    InterestRate YieldTermStructure::forwardRate(const Date& d1,
752,885✔
130
                                                 const Date& d2,
131
                                                 const DayCounter& dayCounter,
132
                                                 Compounding comp,
133
                                                 Frequency freq,
134
                                                 bool extrapolate) const {
135
        if (d1==d2) {
752,885✔
136
            checkRange(d1, extrapolate);
430✔
137
            Time t1 = std::max(timeFromReference(d1) - dt/2.0, 0.0);
430✔
138
            Time t2 = t1 + dt;
430✔
139
            Real compound =
140
                discount(t1, true)/discount(t2, true);
430✔
141
            // times have been calculated with a possibly different daycounter
142
            // but the difference should not matter for very small times
143
            return InterestRate::impliedRate(compound,
144
                                             dayCounter, comp, freq,
145
                                             dt);
430✔
146
        }
147
        QL_REQUIRE(d1 < d2,  d1 << " later than " << d2);
752,455✔
148
        Real compound = discount(d1, extrapolate)/discount(d2, extrapolate);
752,455✔
149
        return InterestRate::impliedRate(compound,
150
                                         dayCounter, comp, freq,
151
                                         d1, d2);
752,455✔
152
    }
153

154
    InterestRate YieldTermStructure::forwardRate(Time t1,
626,584,743✔
155
                                                 Time t2,
156
                                                 Compounding comp,
157
                                                 Frequency freq,
158
                                                 bool extrapolate) const {
159
        Real compound;
160
        if (t2==t1) {
626,584,743✔
161
            checkRange(t1, extrapolate);
140,397,632✔
162
            t1 = std::max(t1 - dt/2.0, 0.0);
140,397,632✔
163
            t2 = t1 + dt;
140,397,632✔
164
            compound = discount(t1, true)/discount(t2, true);
140,397,632✔
165
        } else {
166
            QL_REQUIRE(t2>t1, "t1 (" << t1 << ") >= t2 (" << t2 << ")");
486,187,111✔
167
            compound = discount(t1, extrapolate)/discount(t2, extrapolate);
486,187,111✔
168
        }
169
        return InterestRate::impliedRate(compound,
170
                                         dayCounter(), comp, freq,
1,253,169,486✔
171
                                         t2-t1);
1,253,169,486✔
172
    }
173

174
    void YieldTermStructure::update() {
222,085✔
175
        TermStructure::update();
222,085✔
176
        Date newReference;
222,085✔
177
        try {
178
            newReference = referenceDate();
222,085✔
UNCOV
179
        } catch (Error&) {
×
180
            // the curve couldn't calculate the reference
181
            // date. Most of the times, this is because some
182
            // underlying handle wasn't set, so we can just absorb
183
            // the exception and continue; the jumps will be set
184
            // correctly when a valid underlying is set.
185
            return;
UNCOV
186
        }
×
187
        if (newReference != latestReference_)
222,085✔
188
            setJumps(newReference);
72,185✔
189
    }
190

191
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc