19
19
20
20
#include < ql/time/ecb.hpp>
21
21
#include < ql/settings.hpp>
22
+ #include < ql/utilities/dataparsers.hpp>
22
23
#include < algorithm>
23
24
25
+ #include < boost/algorithm/string/case_conv.hpp>
26
+
27
+ using boost::algorithm::to_upper_copy;
28
+ using std::string;
29
+
24
30
namespace QuantLib {
25
31
26
32
static std::set<Date> knownDateSet;
@@ -56,6 +62,105 @@ namespace QuantLib {
56
62
knownDateSet.erase (d);
57
63
}
58
64
65
+ Date ECB::date (const string& ecbCode,
66
+ const Date& refDate) {
67
+
68
+ QL_REQUIRE (isECBcode (ecbCode),
69
+ ecbCode << " is not a valid ECB code" );
70
+
71
+ string code = to_upper_copy (ecbCode);
72
+ string monthString = code.substr (0 , 3 );
73
+ QuantLib::Month m;
74
+ if (monthString==" JAN" ) m = January;
75
+ else if (monthString==" FEB" ) m = February;
76
+ else if (monthString==" MAR" ) m = March;
77
+ else if (monthString==" APR" ) m = April;
78
+ else if (monthString==" MAY" ) m = May;
79
+ else if (monthString==" JUN" ) m = June;
80
+ else if (monthString==" JUL" ) m = July;
81
+ else if (monthString==" AUG" ) m = August;
82
+ else if (monthString==" SEP" ) m = September;
83
+ else if (monthString==" OCT" ) m = October;
84
+ else if (monthString==" NOV" ) m = November;
85
+ else if (monthString==" DEC" ) m = December;
86
+ else QL_FAIL (" not an ECB month (and it should have been)" );
87
+
88
+ // lexical_cast causes compilation errors with x64
89
+ // Year y = boost::lexical_cast<Year>(code.substr(3, 2));
90
+
91
+ Year y = io::to_integer (code.substr (3 , 2 ));
92
+ Date referenceDate = (refDate != Date () ?
93
+ refDate :
94
+ Date (Settings::instance ().evaluationDate ()));
95
+ Year referenceYear = (referenceDate.year () % 100 );
96
+ y += referenceDate.year () - referenceYear;
97
+ if (y<Date::minDate ().year ())
98
+ return ECB::nextDate (Date::minDate ());
99
+
100
+ return ECB::nextDate (Date (1 , m, y));
101
+ }
102
+
103
+ string ECB::code (const Date& ecbDate) {
104
+
105
+ QL_REQUIRE (isECBdate (ecbDate),
106
+ ecbDate << " is not a valid ECB date" );
107
+
108
+ std::ostringstream ECBcode;
109
+ unsigned int y = ecbDate.year () % 100 ;
110
+ string padding;
111
+ if (y < 10 )
112
+ padding = " 0" ;
113
+ switch (ecbDate.month ()) {
114
+ case January:
115
+ ECBcode << " JAN" << padding << y;
116
+ break ;
117
+ case February:
118
+ ECBcode << " FEB" << padding << y;
119
+ break ;
120
+ case March:
121
+ ECBcode << " MAR" << padding << y;
122
+ break ;
123
+ case April:
124
+ ECBcode << " APR" << padding << y;
125
+ break ;
126
+ case May:
127
+ ECBcode << " MAY" << padding << y;
128
+ break ;
129
+ case June:
130
+ ECBcode << " JUN" << padding << y;
131
+ break ;
132
+ case July:
133
+ ECBcode << " JUL" << padding << y;
134
+ break ;
135
+ case August:
136
+ ECBcode << " AUG" << padding << y;
137
+ break ;
138
+ case September:
139
+ ECBcode << " SEP" << padding << y;
140
+ break ;
141
+ case October:
142
+ ECBcode << " OCT" << padding << y;
143
+ break ;
144
+ case November:
145
+ ECBcode << " NOV" << padding << y;
146
+ break ;
147
+ case December:
148
+ ECBcode << " DEC" << padding << y;
149
+ break ;
150
+ default :
151
+ QL_FAIL (" not an ECB month (and it should have been)" );
152
+ }
153
+
154
+ #if defined(QL_EXTRA_SAFETY_CHECKS)
155
+ QL_ENSURE (isECBcode (ECBcode.str ()),
156
+ " the result " << ECBcode.str () <<
157
+ " is an invalid ECB code" );
158
+ #endif
159
+ return ECBcode.str ();
160
+ }
161
+
162
+
163
+
59
164
Date ECB::nextDate (const Date& date) {
60
165
Date d = (date == Date () ?
61
166
Settings::instance ().evaluationDate () :
@@ -65,7 +170,7 @@ namespace QuantLib {
65
170
std::upper_bound (knownDates ().begin (), knownDates ().end (), d);
66
171
67
172
QL_REQUIRE (i!=knownDates ().end (),
68
- " ECB dates after " << *knownDates ().end () << " are unknown" );
173
+ " ECB dates after " << *(-- knownDates ().end () ) << " are unknown" );
69
174
return Date (*i);
70
175
}
71
176
@@ -82,4 +187,75 @@ namespace QuantLib {
82
187
return std::vector<Date>(i, knownDates ().end ());
83
188
}
84
189
190
+
191
+ bool ECB::isECBcode (const std::string& ecbCode) {
192
+
193
+ if (ecbCode.length () != 5 )
194
+ return false ;
195
+
196
+ string code = to_upper_copy (ecbCode);
197
+
198
+ string str1 (" 0123456789" );
199
+ string::size_type loc = str1.find (code.substr (3 , 1 ), 0 );
200
+ if (loc == string::npos)
201
+ return false ;
202
+ loc = str1.find (code.substr (4 , 1 ), 0 );
203
+ if (loc == string::npos)
204
+ return false ;
205
+
206
+ string monthString = code.substr (0 , 3 );
207
+ if (monthString==" JAN" ) return true ;
208
+ else if (monthString==" FEB" ) return true ;
209
+ else if (monthString==" MAR" ) return true ;
210
+ else if (monthString==" APR" ) return true ;
211
+ else if (monthString==" MAY" ) return true ;
212
+ else if (monthString==" JUN" ) return true ;
213
+ else if (monthString==" JUL" ) return true ;
214
+ else if (monthString==" AUG" ) return true ;
215
+ else if (monthString==" SEP" ) return true ;
216
+ else if (monthString==" OCT" ) return true ;
217
+ else if (monthString==" NOV" ) return true ;
218
+ else if (monthString==" DEC" ) return true ;
219
+ else return false ;
220
+ }
221
+
222
+ string ECB::nextCode (const std::string& ecbCode) {
223
+ QL_REQUIRE (isECBcode (ecbCode),
224
+ ecbCode << " is not a valid ECB code" );
225
+
226
+ string code = to_upper_copy (ecbCode);
227
+ std::ostringstream result;
228
+
229
+ string monthString = code.substr (0 , 3 );
230
+ if (monthString==" JAN" ) result << " FEB" << code.substr (3 , 2 );
231
+ else if (monthString==" FEB" ) result << " MAR" << code.substr (3 , 2 );
232
+ else if (monthString==" MAR" ) result << " APR" << code.substr (3 , 2 );
233
+ else if (monthString==" APR" ) result << " MAY" << code.substr (3 , 2 );
234
+ else if (monthString==" MAY" ) result << " JUN" << code.substr (3 , 2 );
235
+ else if (monthString==" JUN" ) result << " JUL" << code.substr (3 , 2 );
236
+ else if (monthString==" JUL" ) result << " AUG" << code.substr (3 , 2 );
237
+ else if (monthString==" AUG" ) result << " SEP" << code.substr (3 , 2 );
238
+ else if (monthString==" SEP" ) result << " OCT" << code.substr (3 , 2 );
239
+ else if (monthString==" OCT" ) result << " NOV" << code.substr (3 , 2 );
240
+ else if (monthString==" NOV" ) result << " DEC" << code.substr (3 , 2 );
241
+ else if (monthString==" DEC" ) {
242
+ // lexical_cast causes compilation errors with x64
243
+ // Year y = boost::lexical_cast<Year>(code.substr(3, 2));
244
+ unsigned int y = (io::to_integer (code.substr (3 , 2 )) + 1 ) % 100 ;
245
+ string padding;
246
+ if (y < 10 )
247
+ padding = " 0" ;
248
+
249
+ result << " JAN" << padding << y;
250
+ } else QL_FAIL (" not an ECB month (and it should have been)" );
251
+
252
+
253
+ #if defined(QL_EXTRA_SAFETY_CHECKS)
254
+ QL_ENSURE (isECBcode (result.str ()),
255
+ " the result " << result.str () <<
256
+ " is an invalid ECB code" );
257
+ #endif
258
+ return result.str ();
259
+ }
260
+
85
261
}
0 commit comments