/src/quantlib/ql/time/daycounters/thirty360.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl |
5 | | Copyright (C) 2018 Alexey Indiryakov |
6 | | |
7 | | This file is part of QuantLib, a free-software/open-source library |
8 | | for financial quantitative analysts and developers - http://quantlib.org/ |
9 | | |
10 | | QuantLib is free software: you can redistribute it and/or modify it |
11 | | under the terms of the QuantLib license. You should have received a |
12 | | copy of the license along with this program; if not, please email |
13 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
14 | | <http://quantlib.org/license.shtml>. |
15 | | |
16 | | This program is distributed in the hope that it will be useful, but WITHOUT |
17 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
18 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
19 | | */ |
20 | | |
21 | | #include <ql/time/daycounters/thirty360.hpp> |
22 | | #include <algorithm> |
23 | | |
24 | | namespace QuantLib { |
25 | | |
26 | | namespace { |
27 | | |
28 | 0 | bool isLastOfFebruary(Day d, Month m, Year y) { |
29 | 0 | return m == 2 && d == 28 + (Date::isLeap(y) ? 1 : 0); |
30 | 0 | } |
31 | | |
32 | | } |
33 | | |
34 | | ext::shared_ptr<DayCounter::Impl> |
35 | 6 | Thirty360::implementation(Thirty360::Convention c, const Date& terminationDate) { |
36 | 6 | switch (c) { |
37 | 0 | case USA: |
38 | 0 | return ext::shared_ptr<DayCounter::Impl>(new US_Impl); |
39 | 0 | case European: |
40 | 0 | case EurobondBasis: |
41 | 0 | return ext::shared_ptr<DayCounter::Impl>(new EU_Impl); |
42 | 0 | case Italian: |
43 | 0 | return ext::shared_ptr<DayCounter::Impl>(new IT_Impl); |
44 | 0 | case ISMA: |
45 | 6 | case BondBasis: |
46 | 6 | return ext::shared_ptr<DayCounter::Impl>(new ISMA_Impl); |
47 | 0 | case ISDA: |
48 | 0 | case German: |
49 | 0 | return ext::shared_ptr<DayCounter::Impl>(new ISDA_Impl(terminationDate)); |
50 | 0 | case NASD: |
51 | 0 | return ext::shared_ptr<DayCounter::Impl>(new NASD_Impl); |
52 | 0 | default: |
53 | 0 | QL_FAIL("unknown 30/360 convention"); |
54 | 6 | } |
55 | 6 | } |
56 | | |
57 | | Date::serial_type Thirty360::US_Impl::dayCount(const Date& d1, |
58 | 0 | const Date& d2) const { |
59 | 0 | Day dd1 = d1.dayOfMonth(), dd2 = d2.dayOfMonth(); |
60 | 0 | Month mm1 = d1.month(), mm2 = d2.month(); |
61 | 0 | Year yy1 = d1.year(), yy2 = d2.year(); |
62 | | |
63 | | // See https://en.wikipedia.org/wiki/Day_count_convention#30/360_US |
64 | | // NOTE: the order of checks is important |
65 | 0 | if (isLastOfFebruary(dd1, mm1, yy1)) { |
66 | 0 | if (isLastOfFebruary(dd2, mm2, yy2)) { dd2 = 30; } |
67 | 0 | dd1 = 30; |
68 | 0 | } |
69 | 0 | if (dd2 == 31 && dd1 >= 30) { dd2 = 30; } |
70 | 0 | if (dd1 == 31) { dd1 = 30; } |
71 | |
|
72 | 0 | return 360*(yy2-yy1) + 30*(mm2-mm1) + (dd2-dd1); |
73 | 0 | } |
74 | | |
75 | | Date::serial_type Thirty360::ISMA_Impl::dayCount(const Date& d1, |
76 | 0 | const Date& d2) const { |
77 | 0 | Day dd1 = d1.dayOfMonth(), dd2 = d2.dayOfMonth(); |
78 | 0 | Month mm1 = d1.month(), mm2 = d2.month(); |
79 | 0 | Year yy1 = d1.year(), yy2 = d2.year(); |
80 | |
|
81 | 0 | if (dd1 == 31) { dd1 = 30; } |
82 | 0 | if (dd2 == 31 && dd1 == 30) { dd2 = 30; } |
83 | |
|
84 | 0 | return 360*(yy2-yy1) + 30*(mm2-mm1) + (dd2-dd1); |
85 | 0 | } |
86 | | |
87 | | Date::serial_type Thirty360::EU_Impl::dayCount(const Date& d1, |
88 | 0 | const Date& d2) const { |
89 | 0 | Day dd1 = d1.dayOfMonth(), dd2 = d2.dayOfMonth(); |
90 | 0 | Month mm1 = d1.month(), mm2 = d2.month(); |
91 | 0 | Year yy1 = d1.year(), yy2 = d2.year(); |
92 | |
|
93 | 0 | if (dd1 == 31) { dd1 = 30; } |
94 | 0 | if (dd2 == 31) { dd2 = 30; } |
95 | |
|
96 | 0 | return 360*(yy2-yy1) + 30*(mm2-mm1) + (dd2-dd1); |
97 | 0 | } |
98 | | |
99 | | Date::serial_type Thirty360::IT_Impl::dayCount(const Date& d1, |
100 | 0 | const Date& d2) const { |
101 | 0 | Day dd1 = d1.dayOfMonth(), dd2 = d2.dayOfMonth(); |
102 | 0 | Month mm1 = d1.month(), mm2 = d2.month(); |
103 | 0 | Year yy1 = d1.year(), yy2 = d2.year(); |
104 | |
|
105 | 0 | if (dd1 == 31) { dd1 = 30; } |
106 | 0 | if (dd2 == 31) { dd2 = 30; } |
107 | |
|
108 | 0 | if (mm1 == 2 && dd1 > 27) { dd1 = 30; } |
109 | 0 | if (mm2 == 2 && dd2 > 27) { dd2 = 30; } |
110 | |
|
111 | 0 | return 360*(yy2-yy1) + 30*(mm2-mm1) + (dd2-dd1); |
112 | 0 | } |
113 | | |
114 | | Date::serial_type Thirty360::ISDA_Impl::dayCount(const Date& d1, |
115 | 0 | const Date& d2) const { |
116 | 0 | Day dd1 = d1.dayOfMonth(), dd2 = d2.dayOfMonth(); |
117 | 0 | Month mm1 = d1.month(), mm2 = d2.month(); |
118 | 0 | Year yy1 = d1.year(), yy2 = d2.year(); |
119 | |
|
120 | 0 | if (dd1 == 31) { dd1 = 30; } |
121 | 0 | if (dd2 == 31) { dd2 = 30; } |
122 | |
|
123 | 0 | if (isLastOfFebruary(dd1, mm1, yy1)) { dd1 = 30; } |
124 | |
|
125 | 0 | if (d2 != terminationDate_ && isLastOfFebruary(dd2, mm2, yy2)) { dd2 = 30; } |
126 | |
|
127 | 0 | return 360*(yy2-yy1) + 30*(mm2-mm1) + (dd2-dd1); |
128 | 0 | } |
129 | | |
130 | | Date::serial_type Thirty360::NASD_Impl::dayCount(const Date& d1, |
131 | 0 | const Date& d2) const { |
132 | 0 | Day dd1 = d1.dayOfMonth(), dd2 = d2.dayOfMonth(); |
133 | 0 | Integer mm1 = d1.month(), mm2 = d2.month(); |
134 | 0 | Year yy1 = d1.year(), yy2 = d2.year(); |
135 | |
|
136 | 0 | if (dd1 == 31) { dd1 = 30; } |
137 | 0 | if (dd2 == 31 && dd1 >= 30) { dd2 = 30; } |
138 | 0 | if (dd2 == 31 && dd1 < 30) { dd2 = 1; mm2++; } |
139 | |
|
140 | 0 | return 360*(yy2-yy1) + 30*(mm2-mm1) + (dd2-dd1); |
141 | 0 | } |
142 | | |
143 | | } |