Coverage Report

Created: 2026-01-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/interestrate.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2004 Ferdinando Ametrano
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
#include <ql/interestrate.hpp>
21
#include <ql/utilities/dataformatters.hpp>
22
#include <iomanip>
23
#include <sstream>
24
#include <utility>
25
26
namespace QuantLib {
27
28
    // constructors
29
30
    InterestRate::InterestRate()
31
71.8k
    : r_(Null<Real>()) {}
32
33
    InterestRate::InterestRate(Rate r, DayCounter dc, Compounding comp, Frequency freq)
34
209k
    : r_(r), dc_(std::move(dc)), comp_(comp), freqMakesSense_(false) {
35
36
209k
        if (comp_==Compounded || comp_==SimpleThenCompounded || comp_==CompoundedThenSimple) {
37
0
            freqMakesSense_ = true;
38
0
            QL_REQUIRE(freq!=Once && freq!=NoFrequency,
39
0
                       "frequency not allowed for this interest rate");
40
0
            freq_ = Real(freq);
41
0
        }
42
209k
    }
43
44
25.1M
    Real InterestRate::compoundFactor(Time t) const {
45
46
25.1M
        QL_REQUIRE(t>=0.0, "negative time (" << t << ") not allowed");
47
25.1M
        QL_REQUIRE(r_ != Null<Rate>(), "null interest rate");
48
25.1M
        switch (comp_) {
49
25.1M
          case Simple:
50
25.1M
            return 1.0 + r_*t;
51
0
          case Compounded:
52
0
            return std::pow(1.0+r_/freq_, freq_*t);
53
0
          case Continuous:
54
0
            return std::exp(r_*t);
55
0
          case SimpleThenCompounded:
56
0
            if (t<=1.0/Real(freq_))
57
0
                return 1.0 + r_*t;
58
0
            else
59
0
                return std::pow(1.0+r_/freq_, freq_*t);
60
0
          case CompoundedThenSimple:
61
0
            if (t>1.0/Real(freq_))
62
0
                return 1.0 + r_*t;
63
0
            else
64
0
                return std::pow(1.0+r_/freq_, freq_*t);
65
0
          default:
66
0
            QL_FAIL("unknown compounding convention");
67
25.1M
        }
68
25.1M
    }
69
70
    InterestRate InterestRate::impliedRate(Real compound,
71
                                           const DayCounter& resultDC,
72
                                           Compounding comp,
73
                                           Frequency freq,
74
0
                                           Time t) {
75
76
0
        QL_REQUIRE(compound>0.0, "positive compound factor required");
77
78
0
        Rate r;
79
0
        if (compound==1.0) {
80
0
            QL_REQUIRE(t>=0.0, "non negative time (" << t << ") required");
81
0
            r = 0.0;
82
0
        } else {
83
0
            QL_REQUIRE(t>0.0, "positive time (" << t << ") required");
84
0
            switch (comp) {
85
0
              case Simple:
86
0
                r = (compound - 1.0)/t;
87
0
                break;
88
0
              case Compounded:
89
0
                r = (std::pow(compound, 1.0/(Real(freq)*t))-1.0)*Real(freq);
90
0
                break;
91
0
              case Continuous:
92
0
                r = std::log(compound)/t;
93
0
                break;
94
0
              case SimpleThenCompounded:
95
0
                if (t<=1.0/Real(freq))
96
0
                    r = (compound - 1.0)/t;
97
0
                else
98
0
                    r = (std::pow(compound, 1.0/(Real(freq)*t))-1.0)*Real(freq);
99
0
                break;
100
0
              case CompoundedThenSimple:
101
0
                if (t>1.0/Real(freq))
102
0
                    r = (compound - 1.0)/t;
103
0
                else
104
0
                    r = (std::pow(compound, 1.0/(Real(freq)*t))-1.0)*Real(freq);
105
0
                break;
106
0
              default:
107
0
                QL_FAIL("unknown compounding convention ("
108
0
                        << Integer(comp) << ")");
109
0
            }
110
0
        }
111
0
        return InterestRate(r, resultDC, comp, freq);
112
0
    }
113
114
115
0
    std::ostream& operator<<(std::ostream& out, const InterestRate& ir) {
116
0
        if (ir.rate() == Null<Rate>())
117
0
            return out << "null interest rate";
118
119
0
        out << io::rate(ir.rate()) << " " << ir.dayCounter().name() << " ";
120
0
        switch (ir.compounding()) {
121
0
          case Simple:
122
0
            out << "simple compounding";
123
0
            break;
124
0
          case Compounded:
125
0
            switch (ir.frequency()) {
126
0
              case NoFrequency:
127
0
              case Once:
128
0
                QL_FAIL(ir.frequency() << " frequency not allowed "
129
0
                        "for this interest rate");
130
0
              default:
131
0
                out << ir.frequency() <<" compounding";
132
0
            }
133
0
            break;
134
0
          case Continuous:
135
0
            out << "continuous compounding";
136
0
            break;
137
0
          case SimpleThenCompounded:
138
0
            switch (ir.frequency()) {
139
0
              case NoFrequency:
140
0
              case Once:
141
0
                QL_FAIL(ir.frequency() << " frequency not allowed "
142
0
                        "for this interest rate");
143
0
              default:
144
0
                out << "simple compounding up to "
145
0
                    << Integer(12/ir.frequency()) << " months, then "
146
0
                    << ir.frequency() << " compounding";
147
0
            }
148
0
            break;
149
0
          case CompoundedThenSimple:
150
0
            switch (ir.frequency()) {
151
0
              case NoFrequency:
152
0
              case Once:
153
0
                QL_FAIL(ir.frequency() << " frequency not allowed "
154
0
                        "for this interest rate");
155
0
              default:
156
0
                out << "compounding up to "
157
0
                    << Integer(12/ir.frequency()) << " months, then "
158
0
                    << ir.frequency() << " simple compounding";
159
0
            }
160
0
            break;
161
0
          default:
162
0
            QL_FAIL("unknown compounding convention ("
163
0
                    << Integer(ir.compounding()) << ")");
164
0
        }
165
0
        return out;
166
0
    }
167
168
}