Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
calendarparser.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 Quaternion Risk Management Ltd
3
4 This file is part of ORE, a free-software/open-source library
5 for transparent pricing and risk analysis - http://opensourcerisk.org
6
7 ORE is free software: you can redistribute it and/or modify it
8 under the terms of the Modified BSD License. You should have received a
9 copy of the license along with this program.
10 The license is also available online at <http://opensourcerisk.org>
11
12 This program is distributed on the basis that it will form a useful
13 contribution to risk analytics and model standardisation, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
16*/
17
18/*! \file ored/utilities/calendarparser.hpp
19 \brief calendar parser singleton class
20 \ingroup utilities
21*/
22
24
25#include <ql/time/calendars/all.hpp>
29#include <qle/calendars/cme.hpp>
34#include <qle/calendars/ice.hpp>
48#include <qle/calendars/wmr.hpp>
49
50#include <boost/algorithm/string.hpp>
51
52namespace ore {
53namespace data {
54
55using namespace QuantLib;
56using namespace QuantExt;
57
59
61 boost::shared_lock<boost::shared_mutex> lock(mutex_);
62 auto it = calendars_.find(name);
63 if (it != calendars_.end())
64 return it->second;
65 else {
66 // Try to split them up
67 std::vector<std::string> calendarNames;
68 split(calendarNames, name, boost::is_any_of(",()")); // , is delimiter, the brackets may arise if joint calendar
69 // if we have only one token, we won't make progress and exit here to avoid an infinite loop by calling
70 // parseCalendar() recursively below
71 QL_REQUIRE(calendarNames.size() > 1, "Cannot convert \"" << name << "\" to calendar");
72 // now remove any leading strings indicating a joint calendar
73 calendarNames.erase(std::remove(calendarNames.begin(), calendarNames.end(), "JoinHolidays"),
74 calendarNames.end());
75 calendarNames.erase(std::remove(calendarNames.begin(), calendarNames.end(), "JoinBusinessDays"),
76 calendarNames.end());
77 calendarNames.erase(std::remove(calendarNames.begin(), calendarNames.end(), ""), calendarNames.end());
78 // Populate a vector of calendars.
79 std::vector<QuantLib::Calendar> calendars;
80 for (Size i = 0; i < calendarNames.size(); i++) {
81 boost::trim(calendarNames[i]);
82 try {
83 calendars.push_back(parseCalendar(calendarNames[i]));
84 } catch (std::exception& e) {
85 QL_FAIL("Cannot convert \"" << name << "\" to Calendar [exception:" << e.what() << "]");
86 } catch (...) {
87 QL_FAIL("Cannot convert \"" << name << "\" to Calendar [unhandled exception]");
88 }
89 }
90 return QuantLib::JointCalendar(calendars);
91 }
92}
93
94QuantLib::Calendar CalendarParser::addCalendar(const std::string baseName, std::string& newName) {
95 auto cal = parseCalendar(baseName);
96 boost::unique_lock<boost::shared_mutex> lock(mutex_);
97 auto it = calendars_.find(newName);
98 if (it == calendars_.end()) {
99 QuantExt::AmendedCalendar tmp(cal, newName);
100 calendars_[newName] = tmp;
101 return std::move(tmp);
102 } else {
103 return it->second;
104 }
105}
106
109
110 boost::unique_lock<boost::shared_mutex> lock(mutex_);
111
112 // When adding to the static map, keep in mind that the calendar name on the LHS might be used to add or remove
113 // holidays in calendaradjustmentconfig.xml. The calendar on the RHS of the mapping will then be adjusted, so this
114 // latter calendar should never be a fallback like WeekendsOnly(), because then the WeekendsOnly() calendar would
115 // unintentionally be adjusted. Instead, use a copy of the fallback calendar in these cases. For example, do not map
116 // "AED" => WeekendsOnly()
117 // but instead use the mapping
118 // "AED" => AmendedCalendar(WeekendsOnly(), "AED")
119
120 static std::map<std::string, QuantExt::Calendar> ref = {
121 {"TGT", TARGET()},
122 {"TARGET", TARGET()},
123
124 // Country-Description
125 {"CN-IB", China(China::IB)},
126 {"US-FED", UnitedStates(UnitedStates::FederalReserve)},
127 {"US-GOV", UnitedStates(UnitedStates::GovernmentBond)},
128 {"US-NERC", UnitedStates(UnitedStates::NERC)},
129 {"US-NYSE", UnitedStates(UnitedStates::NYSE)},
130 {"US-SET", UnitedStates(UnitedStates::Settlement)},
131 {"US-SOFR", UnitedStates(UnitedStates::SOFR)},
132
133 // Country full name to Settlement/Default
134 {"Australia", Australia()},
135 {"Canada", Canada()},
136 {"Cyprus", Cyprus()},
137 {"Denmark", Denmark()},
138 {"Greece", Greece()},
139 {"Ireland", Ireland(Ireland::BankHolidays)},
140 {"Japan", Japan()},
141 {"Norway", Norway()},
142 {"Switzerland", QuantExt::Switzerland()},
143 {"Sweden", Sweden()},
144 {"Belgium", Belgium()},
145 {"Luxembourg", Luxembourg()},
146 {"Spain", Spain()},
147 {"Austria", QuantExt::Austria()},
148
149 // city specific calendars
150 {"FRA", Germany(Germany::Settlement)},
151
152 // Country City
153 {"CATO", Canada()},
154 {"CHZU", QuantExt::Switzerland()},
155 {"JPTO", Japan()},
156 {"GBLO", UnitedKingdom()},
157 {"SEST", Sweden()},
158 {"TRIS", Turkey()},
159 {"USNY", UnitedStates(UnitedStates::Settlement)},
160
161 // ISDA http://www.fpml.org/coding-scheme/business-center-7-15.xml
162 {"EUTA", TARGET()},
163 {"BEBR", Belgium()}, // Belgium, Brussels not in QL,
164
165 // ISO 3166-1 Alpha-2 code
166 {"AT", QuantExt::Austria()},
167 {"AR", Argentina()},
168 {"AU", Australia()},
169 {"BW", Botswana()},
170 {"BR", Brazil()},
171 {"CA", Canada()},
172 {"CL", Chile()},
173 {"CN", China()},
174 {"CO", Colombia()},
175 {"CY", Cyprus()},
176 {"CZ", CzechRepublic()},
177 {"DK", Denmark()},
178 {"FI", Finland()},
179 {"FR", QuantExt::France()},
180 {"GR", Greece()},
181 {"DE", Germany(Germany::Settlement)},
182 {"HK", HongKong()},
183 {"HU", Hungary()},
185 {"IS", Iceland()},
186 {"IN", India()},
187 {"ID", Indonesia()},
188 {"IL", QuantLib::Israel()},
189 {"IT", Italy()},
190 {"JP", Japan()},
191 {"MX", Mexico()},
192 {"MY", Malaysia()},
193 {"NL", Netherlands()},
194 {"NO", Norway()},
195 {"NZ", NewZealand()},
196 {"PE", Peru()},
197 {"PH", Philippines()},
198 {"PL", Poland()},
199 {"RO", Romania()},
200 {"RU", Russia()},
201 // {"SA", SaudiArabia()},
202 {"SG", Singapore()},
203 {"ZA", SouthAfrica()},
204 {"KR", SouthKorea(SouthKorea::Settlement)},
205 {"SE", Sweden()},
206 {"CH", QuantExt::Switzerland()},
207 {"TW", Taiwan()},
208 {"TH", Thailand()},
209 {"TR", Turkey()},
210 {"UA", Ukraine()},
211 {"GB", UnitedKingdom()},
212 {"US", UnitedStates(UnitedStates::Settlement)},
213 {"BE", Belgium()},
214 {"LU", Luxembourg()},
215 {"ES", Spain()},
216 {"AT", QuantExt::Austria()},
217
218 // ISO 3166-1 Alpha-3 code
219 {"ARG", Argentina()},
220 {"AUS", Australia()},
221 {"ATS", QuantExt::Austria()},
222 {"BWA", Botswana()},
223 {"BRA", Brazil()},
224 {"CAN", Canada()},
225 {"CHL", Chile()},
226 {"CHN", China()},
227 {"COL", Colombia()},
228 {"CYP", Cyprus()},
229 {"CZE", CzechRepublic()},
230 {"DNK", Denmark()},
231 {"FIN", Finland()},
232 {"GRC", Greece()},
233 //{"FRA", QuantExt::France()},
234 {"DEU", Germany(Germany::Settlement)},
235 {"HKG", HongKong()},
236 {"HUN", Hungary()},
237 {"ISL", Iceland()},
238
240 {"IND", India()},
241 {"IDN", Indonesia()},
242 {"ISR", QuantLib::Israel()},
243 {"ITA", Italy()},
244 {"JPN", Japan()},
245 {"MEX", Mexico()},
246 {"MYS", Malaysia()},
247 {"NLD", Netherlands()},
248 {"NOR", Norway()},
249 {"NZL", NewZealand()},
250 {"PER", Peru()},
251 {"PHL", Philippines()},
252 {"POL", Poland()},
253 {"ROU", Romania()},
254 {"RUS", Russia()},
255 {"SAU", SaudiArabia()},
256 {"SGP", Singapore()},
257 {"ZAF", SouthAfrica()},
258 {"KOR", SouthKorea(SouthKorea::Settlement)},
259 {"SWE", Sweden()},
260 {"CHE", QuantExt::Switzerland()},
261 {"TWN", Taiwan()},
262 {"THA", Thailand()},
263 {"TUR", Turkey()},
264 {"UKR", Ukraine()},
265 {"GBR", UnitedKingdom()},
266 {"USA", UnitedStates(UnitedStates::Settlement)},
267 {"BEL", Belgium()},
268 {"LUX", Luxembourg()},
269 {"ESP", Spain()},
270 {"AUT", QuantExt::Austria()},
271
272 // ISO 4217 Currency Alphabetic code
273 {"ARS", Argentina()},
274 {"AUD", Australia()},
275 {"BWP", Botswana()},
276 {"BRL", Brazil()},
277 {"CAD", Canada()},
278 {"CLP", Chile()},
279 {"CNH", China()},
280 {"CNY", China()},
281 {"COP", Colombia()},
282 {"CZK", CzechRepublic()},
283 {"DKK", Denmark()},
284 {"FRF", QuantExt::France()},
285 {"HKD", HongKong()},
286 {"HUF", Hungary()},
287 {"INR", India()},
288 {"IDR", Indonesia()},
289 {"ILS", QuantLib::Israel()},
290 {"ISK", Iceland()},
291 {"ITL", Italy()},
292 {"JPY", Japan()},
293 {"MXN", Mexico()},
294 {"MYR", Malaysia()},
295 {"NOK", Norway()},
296 {"NZD", NewZealand()},
297 {"PEN", Peru()},
298 {"PHP", Philippines()},
299 {"PLN", Poland()},
300 {"RON", Romania()},
301 {"RUB", Russia()},
302 {"SAR", SaudiArabia()},
303 {"SGD", Singapore()},
304 {"ZAR", SouthAfrica()},
305 {"KRW", SouthKorea(SouthKorea::Settlement)},
306 {"SEK", Sweden()},
307 {"CHF", QuantExt::Switzerland()},
308 {"EUR", TARGET()},
309 {"TWD", Taiwan()},
310 {"THB", Thailand()},
311 {"TRY", Turkey()},
312 {"UAH", Ukraine()},
313 {"GBP", UnitedKingdom()},
314 {"USD", UnitedStates(UnitedStates::Settlement)},
315 {"BEF", Belgium()},
316 {"LUF", Luxembourg()},
317 {"ATS", QuantExt::Austria()},
318
319 // Minor Currencies
320 {"GBp", UnitedKingdom()},
321 {"GBX", UnitedKingdom()},
322 {"ILa", QuantLib::Israel()},
323 {"ILX", QuantLib::Israel()},
324 {"ILs", QuantLib::Israel()},
325 {"ILA", QuantLib::Israel()},
326 {"ZAc", SouthAfrica()},
327 {"ZAC", SouthAfrica()},
328 {"ZAX", SouthAfrica()},
329
330 // fallback to IslamicWeekendsOnly for these ccys and use amendmends
331 {"AED", AmendedCalendar(UnitedArabEmirates(), "AED")},
332 {"AE", AmendedCalendar(UnitedArabEmirates(), "AED")},
333 {"ARE", AmendedCalendar(UnitedArabEmirates(), "AED")},
334
335 // fallback to amended Mauritius calendar.
336 {"MU", AmendedCalendar(Mauritius(), "MUR")},
337 {"MUR", AmendedCalendar(Mauritius(), "MUR")},
338 {"MUS", AmendedCalendar(Mauritius(), "MUR")},
339 // fallback to WeekendsOnly for these emerging ccys
340 {"BHD", AmendedCalendar(WeekendsOnly(), "BHD")},
341 {"CLF", AmendedCalendar(WeekendsOnly(), "CLF")},
342 {"EGP", AmendedCalendar(WeekendsOnly(), "EGP")},
343 {"KWD", AmendedCalendar(WeekendsOnly(), "KWD")},
344 {"KZT", AmendedCalendar(WeekendsOnly(), "KZT")},
345 {"MAD", AmendedCalendar(WeekendsOnly(), "MAD")},
346 {"MXV", AmendedCalendar(WeekendsOnly(), "MXV")},
347 {"NGN", AmendedCalendar(WeekendsOnly(), "MGN")},
348 {"OMR", AmendedCalendar(WeekendsOnly(), "OMR")},
349 {"PKR", AmendedCalendar(WeekendsOnly(), "PKR")},
350 {"QAR", AmendedCalendar(WeekendsOnly(), "QAR")},
351 {"UYU", AmendedCalendar(WeekendsOnly(), "UYU")},
352 {"TND", AmendedCalendar(WeekendsOnly(), "TND")},
353 {"VND", AmendedCalendar(WeekendsOnly(), "VND")},
354 // new GFMA currencies
355 {"AOA", AmendedCalendar(WeekendsOnly(), "AOA")},
356 {"BGN", AmendedCalendar(WeekendsOnly(), "BGN")},
357 {"ETB", AmendedCalendar(WeekendsOnly(), "ETB")},
358 {"GEL", AmendedCalendar(WeekendsOnly(), "GEL")},
359 {"GHS", AmendedCalendar(WeekendsOnly(), "GHS")},
360 {"HRK", AmendedCalendar(WeekendsOnly(), "HRK")},
361 {"JOD", AmendedCalendar(WeekendsOnly(), "JOD")},
362 {"KES", AmendedCalendar(WeekendsOnly(), "KES")},
363 {"LKR", AmendedCalendar(WeekendsOnly(), "LKR")},
364 {"RSD", AmendedCalendar(WeekendsOnly(), "RSD")},
365 {"UGX", AmendedCalendar(WeekendsOnly(), "UGX")},
366 {"XOF", AmendedCalendar(WeekendsOnly(), "XOF")},
367 {"ZMW", AmendedCalendar(WeekendsOnly(), "ZMW")},
368
369 // ISO 10383 MIC Exchange
370 {"XASX", Australia(Australia::ASX)},
371 {"BVMF", Brazil(Brazil::Exchange)},
372 {"XTSE", Canada(Canada::TSX)},
373 {"XSHG", China(China::SSE)},
374 {"XFRA", Germany(Germany::FrankfurtStockExchange)},
375 {"XETR", Germany(Germany::Xetra)},
376 {"ECAG", Germany(Germany::Eurex)},
377 {"EUWA", Germany(Germany::Euwax)},
378 {"XJKT", Indonesia(Indonesia::JSX)},
379 {"XIDX", Indonesia(Indonesia::IDX)},
380 {"XTAE", QuantLib::Israel(QuantLib::Israel::TASE)},
381 {"XMIL", Italy(Italy::Exchange)},
382 {"MISX", RussiaModified(Russia::MOEX)},
383 {"XKRX", SouthKorea(SouthKorea::KRX)},
385 {"XLON", UnitedKingdom(UnitedKingdom::Exchange)},
386 {"XLME", UnitedKingdom(UnitedKingdom::Metals)},
387 {"XNYS", UnitedStates(UnitedStates::NYSE)},
388 {"XDUB", Ireland()},
389 {"XPAR", QuantLib::France(QuantLib::France::Exchange)},
390
391 // Other / Legacy
392 {"DEN", Denmark()}, // TODO: consider remove it, not ISO
394 {"London stock exchange", UnitedKingdom(UnitedKingdom::Exchange)},
395 {"LNB", UnitedKingdom()},
396 {"New York stock exchange", UnitedStates(UnitedStates::NYSE)},
397 {"SOFR fixing calendar", UnitedStates(UnitedStates::SOFR)},
398 {"NGL", Netherlands()},
399 {"NYB", UnitedStates(UnitedStates::Settlement)},
400 {"SA", SouthAfrica()}, // TODO: consider remove it, not ISO & confuses with Saudi Arabia
401 {"SS", Sweden()}, // TODO: consider remove it, not ISO & confuses with South Sudan
402 {"SYB", Australia()},
403 {"TKB", Japan()},
404 {"TRB", Canada()},
405 {"UK", UnitedKingdom()},
406 {"UK settlement", UnitedKingdom()},
407 {"US settlement", UnitedStates(UnitedStates::Settlement)},
408 {"US with Libor impact", UnitedStates(UnitedStates::LiborImpact)},
409 {"WMR", Wmr()},
410 {"ZUB", QuantExt::Switzerland()},
411
412 // ICE exchange calendars
413 {"ICE_FuturesUS", ICE(ICE::FuturesUS)},
414 {"ICE_FuturesUS_1", ICE(ICE::FuturesUS_1)},
415 {"ICE_FuturesUS_2", ICE(ICE::FuturesUS_2)},
416 {"ICE_FuturesEU", ICE(ICE::FuturesEU)},
417 {"ICE_FuturesEU_1", ICE(ICE::FuturesEU_1)},
418 {"ICE_EndexEnergy", ICE(ICE::EndexEnergy)},
419 {"ICE_EndexEquities", ICE(ICE::EndexEquities)},
420 {"ICE_SwapTradeUS", ICE(ICE::SwapTradeUS)},
421 {"ICE_SwapTradeUK", ICE(ICE::SwapTradeUK)},
422 {"ICE_FuturesSingapore", ICE(ICE::FuturesSingapore)},
423 // CME exchange calendar
424 {"CME", CME()},
425
426 // Simple calendars
427 {"WeekendsOnly", WeekendsOnly()},
428 {"UNMAPPED", WeekendsOnly()},
429 {"NullCalendar", NullCalendar()},
430 {"", NullCalendar()}};
431
432 calendars_ = ref;
433
434 // add ql calendar names
435 for (auto const& c : ref) {
436 calendars_[c.second.name()] = c.second;
437 }
438}
439
441 boost::unique_lock<boost::shared_mutex> lock(mutex_);
442 for (auto& m : calendars_) {
443 m.second.resetAddedAndRemovedHolidays();
444 }
445}
446
447} // namespace data
448} // namespace ore
calendar parser singleton class
std::map< std::string, QuantLib::Calendar > calendars_
QuantLib::Calendar addCalendar(const std::string baseName, std::string &newName)
QuantLib::Calendar parseCalendar(const std::string &name) const
boost::shared_mutex mutex_
@ data
Definition: log.hpp:77
Serializable Credit Default Swap.
Definition: namespaces.docs:23
string name