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  <http://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 <sstream>
23 #include <iomanip>
24 
25 namespace QuantLib {
26 
27     // constructors
28 
InterestRate()29     InterestRate::InterestRate()
30     : r_(Null<Real>()) {}
31 
InterestRate(Rate r,const DayCounter & dc,Compounding comp,Frequency freq)32     InterestRate::InterestRate(Rate r,
33                                const DayCounter& dc,
34                                Compounding comp,
35                                Frequency freq)
36     : r_(r), dc_(dc), comp_(comp), freqMakesSense_(false) {
37 
38         if (comp_==Compounded || comp_==SimpleThenCompounded || comp_==CompoundedThenSimple) {
39             freqMakesSense_ = true;
40             QL_REQUIRE(freq!=Once && freq!=NoFrequency,
41                        "frequency not allowed for this interest rate");
42             freq_ = Real(freq);
43         }
44     }
45 
compoundFactor(Time t) const46     Real InterestRate::compoundFactor(Time t) const {
47 
48         QL_REQUIRE(t>=0.0, "negative time (" << t << ") not allowed");
49         QL_REQUIRE(r_ != Null<Rate>(), "null interest rate");
50         switch (comp_) {
51           case Simple:
52             return 1.0 + r_*t;
53           case Compounded:
54             return std::pow(1.0+r_/freq_, freq_*t);
55           case Continuous:
56             return std::exp(r_*t);
57           case SimpleThenCompounded:
58             if (t<=1.0/Real(freq_))
59                 return 1.0 + r_*t;
60             else
61                 return std::pow(1.0+r_/freq_, freq_*t);
62           case CompoundedThenSimple:
63             if (t>1.0/Real(freq_))
64                 return 1.0 + r_*t;
65             else
66                 return std::pow(1.0+r_/freq_, freq_*t);
67           default:
68             QL_FAIL("unknown compounding convention");
69         }
70     }
71 
impliedRate(Real compound,const DayCounter & resultDC,Compounding comp,Frequency freq,Time t)72     InterestRate InterestRate::impliedRate(Real compound,
73                                            const DayCounter& resultDC,
74                                            Compounding comp,
75                                            Frequency freq,
76                                            Time t) {
77 
78         QL_REQUIRE(compound>0.0, "positive compound factor required");
79 
80         Rate r;
81         if (compound==1.0) {
82             QL_REQUIRE(t>=0.0, "non negative time (" << t << ") required");
83             r = 0.0;
84         } else {
85             QL_REQUIRE(t>0.0, "positive time (" << t << ") required");
86             switch (comp) {
87               case Simple:
88                 r = (compound - 1.0)/t;
89                 break;
90               case Compounded:
91                 r = (std::pow(compound, 1.0/(Real(freq)*t))-1.0)*Real(freq);
92                 break;
93               case Continuous:
94                 r = std::log(compound)/t;
95                 break;
96               case SimpleThenCompounded:
97                 if (t<=1.0/Real(freq))
98                     r = (compound - 1.0)/t;
99                 else
100                     r = (std::pow(compound, 1.0/(Real(freq)*t))-1.0)*Real(freq);
101                 break;
102               case CompoundedThenSimple:
103                 if (t>1.0/Real(freq))
104                     r = (compound - 1.0)/t;
105                 else
106                     r = (std::pow(compound, 1.0/(Real(freq)*t))-1.0)*Real(freq);
107                 break;
108               default:
109                 QL_FAIL("unknown compounding convention ("
110                         << Integer(comp) << ")");
111             }
112         }
113         return InterestRate(r, resultDC, comp, freq);
114     }
115 
116 
operator <<(std::ostream & out,const InterestRate & ir)117     std::ostream& operator<<(std::ostream& out, const InterestRate& ir) {
118         if (ir.rate() == Null<Rate>())
119             return out << "null interest rate";
120 
121         out << io::rate(ir.rate()) << " " << ir.dayCounter().name() << " ";
122         switch (ir.compounding()) {
123           case Simple:
124             out << "simple compounding";
125             break;
126           case Compounded:
127             switch (ir.frequency()) {
128               case NoFrequency:
129               case Once:
130                 QL_FAIL(ir.frequency() << " frequency not allowed "
131                         "for this interest rate");
132               default:
133                 out << ir.frequency() <<" compounding";
134             }
135             break;
136           case Continuous:
137             out << "continuous compounding";
138             break;
139           case SimpleThenCompounded:
140             switch (ir.frequency()) {
141               case NoFrequency:
142               case Once:
143                 QL_FAIL(ir.frequency() << " frequency not allowed "
144                         "for this interest rate");
145               default:
146                 out << "simple compounding up to "
147                     << Integer(12/ir.frequency()) << " months, then "
148                     << ir.frequency() << " compounding";
149             }
150             break;
151           case CompoundedThenSimple:
152             switch (ir.frequency()) {
153               case NoFrequency:
154               case Once:
155                 QL_FAIL(ir.frequency() << " frequency not allowed "
156                         "for this interest rate");
157               default:
158                 out << "compounding up to "
159                     << Integer(12/ir.frequency()) << " months, then "
160                     << ir.frequency() << " simple compounding";
161             }
162             break;
163           default:
164             QL_FAIL("unknown compounding convention ("
165                     << Integer(ir.compounding()) << ")");
166         }
167         return out;
168     }
169 
170 }
171