QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
period.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2014 Ferdinando Ametrano
5 Copyright (C) 2006 Katiuscia Manzoni
6 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
7 Copyright (C) 2003, 2004, 2005, 2006, 2008 StatPro Italia srl
8 Copyright (C) 2014 Paolo Mazzocchi
9
10 This file is part of QuantLib, a free-software/open-source library
11 for financial quantitative analysts and developers - http://quantlib.org/
12
13 QuantLib is free software: you can redistribute it and/or modify it
14 under the terms of the QuantLib license. You should have received a
15 copy of the license along with this program; if not, please email
16 <quantlib-dev@lists.sf.net>. The license is also available online at
17 <http://quantlib.org/license.shtml>.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 FOR A PARTICULAR PURPOSE. See the license for more details.
22*/
23
24#include <ql/time/period.hpp>
25#include <ql/errors.hpp>
26
27namespace QuantLib {
28
30 switch (f) {
31 case NoFrequency:
32 // same as Period()
33 units_ = Days;
34 length_ = 0;
35 break;
36 case Once:
37 units_ = Years;
38 length_ = 0;
39 break;
40 case Annual:
41 units_ = Years;
42 length_ = 1;
43 break;
44 case Semiannual:
46 case Quarterly:
47 case Bimonthly:
48 case Monthly:
49 units_ = Months;
50 length_ = 12/f;
51 break;
52 case EveryFourthWeek:
53 case Biweekly:
54 case Weekly:
55 units_ = Weeks;
56 length_ = 52/f;
57 break;
58 case Daily:
59 units_ = Days;
60 length_ = 1;
61 break;
62 case OtherFrequency:
63 QL_FAIL("unknown frequency"); // no point in showing 999...
64 default:
65 QL_FAIL("unknown frequency (" << Integer(f) << ")");
66 }
67 }
68
70 // unsigned version
71 Size length = std::abs(length_);
72
73 if (length==0) {
74 if (units_==Years) return Once;
75 return NoFrequency;
76 }
77
78 switch (units_) {
79 case Years:
80 if (length == 1)
81 return Annual;
82 else
83 return OtherFrequency;
84 case Months:
85 if (12%length == 0 && length <= 12)
86 return Frequency(12/length);
87 else
88 return OtherFrequency;
89 case Weeks:
90 if (length==1)
91 return Weekly;
92 else if (length==2)
93 return Biweekly;
94 else if (length==4)
95 return EveryFourthWeek;
96 else
97 return OtherFrequency;
98 case Days:
99 if (length==1)
100 return Daily;
101 else
102 return OtherFrequency;
103 default:
104 QL_FAIL("unknown time unit (" << Integer(units_) << ")");
105 }
106 }
107
109 if (length_ == 0) {
110 units_ = Days;
111 } else {
112 switch (units_) {
113 case Months:
114 if ((length_ % 12) == 0) {
115 length_ /= 12;
116 units_ = Years;
117 }
118 break;
119 case Days:
120 if ((length_ % 7) == 0) {
121 length_ /= 7;
122 units_ = Weeks;
123 }
124 break;
125 case Weeks:
126 case Years:
127 break;
128 default:
129 QL_FAIL("unknown time unit (" << Integer(units_) << ")");
130 }
131 }
132 }
133
135
136 if (length_==0) {
137 length_ = p.length();
138 units_ = p.units();
139 } else if (units_==p.units()) {
140 // no conversion needed
141 length_ += p.length();
142 } else {
143 switch (units_) {
144
145 case Years:
146 switch (p.units()) {
147 case Months:
148 units_ = Months;
149 length_ = length_*12 + p.length();
150 break;
151 case Weeks:
152 case Days:
153 QL_REQUIRE(p.length()==0,
154 "impossible addition between " << *this <<
155 " and " << p);
156 break;
157 default:
158 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
159 }
160 break;
161
162 case Months:
163 switch (p.units()) {
164 case Years:
165 length_ += p.length()*12;
166 break;
167 case Weeks:
168 case Days:
169 QL_REQUIRE(p.length()==0,
170 "impossible addition between " << *this <<
171 " and " << p);
172 break;
173 default:
174 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
175 }
176 break;
177
178 case Weeks:
179 switch (p.units()) {
180 case Days:
181 units_ = Days;
182 length_ = length_*7 + p.length();
183 break;
184 case Years:
185 case Months:
186 QL_REQUIRE(p.length()==0,
187 "impossible addition between " << *this <<
188 " and " << p);
189 break;
190 default:
191 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
192 }
193 break;
194
195 case Days:
196 switch (p.units()) {
197 case Weeks:
198 length_ += p.length()*7;
199 break;
200 case Years:
201 case Months:
202 QL_REQUIRE(p.length()==0,
203 "impossible addition between " << *this <<
204 " and " << p);
205 break;
206 default:
207 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
208 }
209 break;
210
211 default:
212 QL_FAIL("unknown time unit (" << Integer(units_) << ")");
213 }
214 }
215
216 return *this;
217 }
218
220 return operator+=(-p);
221 }
222
224 length_ *= n;
225 return *this;
226 }
227
229 QL_REQUIRE(n != 0, "cannot be divided by zero");
230 if (length_ % n == 0) {
231 // keep the original units. If the user created a
232 // 24-months period, he'll probably want a 12-months one
233 // when he halves it.
234 length_ /= n;
235 } else {
236 // try
239 switch (units) {
240 case Years:
241 length *= 12;
242 units = Months;
243 break;
244 case Weeks:
245 length *= 7;
246 units = Days;
247 break;
248 default:
249 ;
250 }
251 QL_REQUIRE(length % n == 0,
252 *this << " cannot be divided by " << n);
253 length_ = length/n;
254 units_ = units;
255 }
256 return *this;
257 }
258
259
260 namespace {
261
262 std::pair<Integer,Integer> daysMinMax(const Period& p) {
263 switch (p.units()) {
264 case Days:
265 return std::make_pair(p.length(), p.length());
266 case Weeks:
267 return std::make_pair(7*p.length(), 7*p.length());
268 case Months:
269 return std::make_pair(28*p.length(), 31*p.length());
270 case Years:
271 return std::make_pair(365*p.length(), 366*p.length());
272 default:
273 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
274 }
275 }
276
277 }
278
279 Real years(const Period& p) {
280 if (p.length()==0) return 0.0;
281
282 switch (p.units()) {
283 case Days:
284 QL_FAIL("cannot convert Days into Years");
285 case Weeks:
286 QL_FAIL("cannot convert Weeks into Years");
287 case Months:
288 return p.length()/12.0;
289 case Years:
290 return p.length();
291 default:
292 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
293 }
294 }
295
296 Real months(const Period& p) {
297 if (p.length()==0) return 0.0;
298
299 switch (p.units()) {
300 case Days:
301 QL_FAIL("cannot convert Days into Months");
302 case Weeks:
303 QL_FAIL("cannot convert Weeks into Months");
304 case Months:
305 return p.length();
306 case Years:
307 return p.length()*12.0;
308 default:
309 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
310 }
311 }
312
313 Real weeks(const Period& p) {
314 if (p.length()==0) return 0.0;
315
316 switch (p.units()) {
317 case Days:
318 return p.length()/7.0;
319 case Weeks:
320 return p.length();
321 case Months:
322 QL_FAIL("cannot convert Months into Weeks");
323 case Years:
324 QL_FAIL("cannot convert Years into Weeks");
325 default:
326 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
327 }
328 }
329
330 Real days(const Period& p) {
331 if (p.length()==0) return 0.0;
332
333 switch (p.units()) {
334 case Days:
335 return p.length();
336 case Weeks:
337 return p.length()*7.0;
338 case Months:
339 QL_FAIL("cannot convert Months into Days");
340 case Years:
341 QL_FAIL("cannot convert Years into Days");
342 default:
343 QL_FAIL("unknown time unit (" << Integer(p.units()) << ")");
344 }
345 }
346
347 bool operator<(const Period& p1, const Period& p2) {
348
349 // special cases
350 if (p1.length() == 0)
351 return p2.length() > 0;
352 if (p2.length() == 0)
353 return p1.length() < 0;
354
355 // exact comparisons
356 if (p1.units() == p2.units())
357 return p1.length() < p2.length();
358 if (p1.units() == Months && p2.units() == Years)
359 return p1.length() < 12*p2.length();
360 if (p1.units() == Years && p2.units() == Months)
361 return 12*p1.length() < p2.length();
362 if (p1.units() == Days && p2.units() == Weeks)
363 return p1.length() < 7*p2.length();
364 if (p1.units() == Weeks && p2.units() == Days)
365 return 7*p1.length() < p2.length();
366
367 // inexact comparisons (handled by converting to days and using limits)
368 std::pair<Integer, Integer> p1lim = daysMinMax(p1);
369 std::pair<Integer, Integer> p2lim = daysMinMax(p2);
370
371 if (p1lim.second < p2lim.first)
372 return true;
373 else if (p1lim.first > p2lim.second)
374 return false;
375 else
376 QL_FAIL("undecidable comparison between " << p1 << " and " << p2);
377 }
378
379
380 Period operator+(const Period& p1, const Period& p2) {
381 Period result = p1;
382 result += p2;
383 return result;
384 }
385
386 Period operator-(const Period& p1, const Period& p2) {
387 return p1+(-p2);
388 }
389
391 Period result = p;
392 result /= n;
393 return result;
394 }
395
396 // period formatting
397
398 std::ostream& operator<<(std::ostream& out, const Period& p) {
399 return out << io::short_period(p);
400 }
401
402 namespace detail {
403
404 std::ostream& operator<<(std::ostream& out,
405 const long_period_holder& holder) {
406 Integer n = holder.p.length();
407 switch (holder.p.units()) {
408 case Days:
409 return out << n << (n == 1 ? " day" : " days");
410 case Weeks:
411 return out << n << (n == 1 ? " week" : " weeks");
412 case Months:
413 return out << n << (n == 1 ? " month" : " months");
414 case Years:
415 return out << n << (n == 1 ? " year" : " years");
416 default:
417 QL_FAIL("unknown time unit (" << Integer(holder.p.units()) << ")");
418 }
419 }
420
421 std::ostream& operator<<(std::ostream& out,
422 const short_period_holder& holder) {
423 Integer n = holder.p.length();
424 switch (holder.p.units()) {
425 case Days:
426 return out << n << "D";
427 case Weeks:
428 return out << n << "W";
429 case Months:
430 return out << n << "M";
431 case Years:
432 return out << n << "Y";
433 default:
434 QL_FAIL("unknown time unit (" << Integer(holder.p.units()) << ")");
435 }
436 }
437
438 }
439
440 namespace io {
441
444 }
445
448 }
449
450 }
451
452}
Period & operator+=(const Period &)
Definition: period.cpp:134
TimeUnit units() const
Definition: period.hpp:51
Period & operator/=(Integer)
Definition: period.cpp:228
Period()=default
Integer length() const
Definition: period.hpp:50
Period & operator*=(Integer)
Definition: period.cpp:223
Period & operator-=(const Period &)
Definition: period.cpp:219
void normalize()
Definition: period.cpp:108
Frequency frequency() const
Definition: period.cpp:69
TimeUnit units_
Definition: period.hpp:61
Integer length_
Definition: period.hpp:60
Classes and functions for error handling.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
Frequency
Frequency of events.
Definition: frequency.hpp:37
TimeUnit
Units used to describe time periods.
Definition: timeunit.hpp:37
@ Monthly
once a month
Definition: frequency.hpp:44
@ Biweekly
every second week
Definition: frequency.hpp:46
@ EveryFourthWeek
every fourth week
Definition: frequency.hpp:45
@ Weekly
once a week
Definition: frequency.hpp:47
@ OtherFrequency
some other unknown frequency
Definition: frequency.hpp:49
@ Annual
once a year
Definition: frequency.hpp:39
@ Daily
once a day
Definition: frequency.hpp:48
@ Bimonthly
every second month
Definition: frequency.hpp:43
@ Once
only once, e.g., a zero-coupon
Definition: frequency.hpp:38
@ Quarterly
every third month
Definition: frequency.hpp:42
@ EveryFourthMonth
every fourth month
Definition: frequency.hpp:41
@ Semiannual
twice a year
Definition: frequency.hpp:40
@ NoFrequency
null frequency
Definition: frequency.hpp:37
detail::short_period_holder short_period(const Period &p)
output periods in short format (e.g. "2w")
Definition: period.cpp:446
detail::long_period_holder long_period(const Period &p)
output periods in long format (e.g. "2 weeks")
Definition: period.cpp:442
QL_REAL Real
real number
Definition: types.hpp:50
QL_INTEGER Integer
integer number
Definition: types.hpp:35
std::size_t Size
size of a container
Definition: types.hpp:58
std::ostream & operator<<(std::ostream &out, const short_date_holder &holder)
Definition: date.cpp:894
Definition: any.hpp:35
Quantity operator-(const Quantity &m1, const Quantity &m2)
Definition: quantity.hpp:171
Real weeks(const Period &p)
Definition: period.cpp:313
bool operator<(const Quantity &m1, const Quantity &m2)
Definition: quantity.cpp:125
Real months(const Period &p)
Definition: period.cpp:296
Real years(const Period &p)
Definition: period.cpp:279
std::ostream & operator<<(std::ostream &out, GFunctionFactory::YieldCurveModel type)
Quantity operator+(const Quantity &m1, const Quantity &m2)
Definition: quantity.hpp:165
Real days(const Period &p)
Definition: period.cpp:330
Real operator/(const Quantity &m1, const Quantity &m2)
Definition: quantity.cpp:86
period- and frequency-related classes and enumerations