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