19#include <boost/test/unit_test.hpp>
20#include <oret/toplevelfixture.hpp>
22#include <boost/algorithm/string/replace.hpp>
23#include <boost/make_shared.hpp>
25#include <ql/currencies/all.hpp>
26#include <ql/time/calendars/all.hpp>
27#include <ql/time/daycounters/all.hpp>
31using namespace boost::unit_test_framework;
35using boost::algorithm::replace_all_copy;
39void testIborIndexConvention(
const string&
id,
const string& fixingCalendar,
const string& dayCounter,
40 const Size settlementDays,
const string& businessDayConvention,
const bool endOfMonth,
41 const string& internalId =
"") {
43 QuantLib::ext::shared_ptr<IborIndexConvention> convention;
45 convention = QuantLib::ext::make_shared<IborIndexConvention>(
id, fixingCalendar, dayCounter,
46 settlementDays, businessDayConvention, endOfMonth));
49 BOOST_CHECK_EQUAL(convention->id(), internalId.empty() ?
id : internalId);
50 BOOST_CHECK_EQUAL(convention->fixingCalendar(), fixingCalendar);
51 BOOST_CHECK_EQUAL(convention->dayCounter(), dayCounter);
52 BOOST_CHECK_EQUAL(convention->settlementDays(), settlementDays);
53 BOOST_CHECK_EQUAL(convention->businessDayConvention(), businessDayConvention);
54 BOOST_CHECK_EQUAL(convention->endOfMonth(), endOfMonth);
59BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)
61BOOST_AUTO_TEST_SUITE(ConventionsTests)
65 BOOST_TEST_MESSAGE(
"Testing cross currency fix float convention construction");
68 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwapConvention> convention;
70 convention = QuantLib::ext::make_shared<CrossCcyFixFloatSwapConvention>(
"USD-TRY-XCCY-FIX-FLOAT",
"2",
"US,UK,TRY",
"F",
71 "TRY",
"Annual",
"F",
"A360",
"USD-LIBOR-3M"));
74 BOOST_CHECK_EQUAL(convention->id(),
"USD-TRY-XCCY-FIX-FLOAT");
75 BOOST_CHECK_EQUAL(convention->settlementDays(), 2);
76 BOOST_CHECK_EQUAL(convention->settlementCalendar(), JointCalendar(UnitedStates(UnitedStates::Settlement), UnitedKingdom(), Turkey()));
77 BOOST_CHECK_EQUAL(convention->settlementConvention(), Following);
78 BOOST_CHECK_EQUAL(convention->fixedCurrency(), TRYCurrency());
79 BOOST_CHECK_EQUAL(convention->fixedFrequency(), Annual);
80 BOOST_CHECK_EQUAL(convention->fixedConvention(), Following);
81 BOOST_CHECK_EQUAL(convention->fixedDayCounter(), Actual360());
82 BOOST_CHECK_EQUAL(convention->index()->name(),
"USDLibor3M Actual/360");
83 BOOST_CHECK(!convention->eom());
87 convention = QuantLib::ext::make_shared<CrossCcyFixFloatSwapConvention>(
88 "USD-TRY-XCCY-FIX-FLOAT",
"2",
"US,UK,TRY",
"F",
"TRY",
"Annual",
"F",
"A360",
"USD-LIBOR-3M",
"false"));
89 BOOST_CHECK(!convention->eom());
92 convention = QuantLib::ext::make_shared<CrossCcyFixFloatSwapConvention>(
93 "USD-TRY-XCCY-FIX-FLOAT",
"2",
"US,UK,TRY",
"F",
"TRY",
"Annual",
"F",
"A360",
"USD-LIBOR-3M",
"true"));
94 BOOST_CHECK(convention->eom());
99 BOOST_TEST_MESSAGE(
"Testing parsing of cross currency fix float convention from XML");
103 xml.append(
"<CrossCurrencyFixFloat>");
104 xml.append(
" <Id>USD-TRY-XCCY-FIX-FLOAT</Id>");
105 xml.append(
" <SettlementDays>2</SettlementDays>");
106 xml.append(
" <SettlementCalendar>US,UK,TRY</SettlementCalendar>");
107 xml.append(
" <SettlementConvention>F</SettlementConvention>");
108 xml.append(
" <FixedCurrency>TRY</FixedCurrency>");
109 xml.append(
" <FixedFrequency>Annual</FixedFrequency>");
110 xml.append(
" <FixedConvention>F</FixedConvention>");
111 xml.append(
" <FixedDayCounter>A360</FixedDayCounter>");
112 xml.append(
" <Index>USD-LIBOR-3M</Index>");
113 xml.append(
"</CrossCurrencyFixFloat>");
116 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwapConvention> convention = QuantLib::ext::make_shared<CrossCcyFixFloatSwapConvention>();
117 BOOST_CHECK_NO_THROW(convention->fromXMLString(xml));
120 BOOST_CHECK_EQUAL(convention->id(),
"USD-TRY-XCCY-FIX-FLOAT");
121 BOOST_CHECK_EQUAL(convention->settlementDays(), 2);
122 BOOST_CHECK_EQUAL(convention->settlementCalendar(), JointCalendar(UnitedStates(UnitedStates::Settlement), UnitedKingdom(), Turkey()));
123 BOOST_CHECK_EQUAL(convention->settlementConvention(), Following);
124 BOOST_CHECK_EQUAL(convention->fixedCurrency(), TRYCurrency());
125 BOOST_CHECK_EQUAL(convention->fixedFrequency(), Annual);
126 BOOST_CHECK_EQUAL(convention->fixedConvention(), Following);
127 BOOST_CHECK_EQUAL(convention->fixedDayCounter(), Actual360());
128 BOOST_CHECK_EQUAL(convention->index()->name(),
"USDLibor3M Actual/360");
129 BOOST_CHECK(!convention->eom());
132 xml = replace_all_copy(xml,
"</CrossCurrencyFixFloat>",
"<EOM>false</EOM></CrossCurrencyFixFloat>");
133 BOOST_TEST_MESSAGE(
"xml is: " << xml);
134 convention->fromXMLString(xml);
135 BOOST_CHECK(!convention->eom());
137 xml = replace_all_copy(xml,
"<EOM>false</EOM>",
"<EOM>true</EOM>");
138 convention->fromXMLString(xml);
139 BOOST_CHECK(convention->eom());
144 BOOST_TEST_MESSAGE(
"Testing writing of cross currency fix float convention to XML");
147 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwapConvention> convention;
148 BOOST_CHECK_NO_THROW(
149 convention = QuantLib::ext::make_shared<CrossCcyFixFloatSwapConvention>(
"USD-TRY-XCCY-FIX-FLOAT",
"2",
"US,UK,TRY",
"F",
150 "TRY",
"Annual",
"F",
"A360",
"USD-LIBOR-3M"));
153 string xml = convention->toXMLString();
156 QuantLib::ext::shared_ptr<CrossCcyFixFloatSwapConvention> readConvention =
157 QuantLib::ext::make_shared<CrossCcyFixFloatSwapConvention>();
158 BOOST_CHECK_NO_THROW(readConvention->fromXMLString(xml));
161 BOOST_CHECK_EQUAL(convention->id(), readConvention->id());
162 BOOST_CHECK_EQUAL(convention->settlementDays(), readConvention->settlementDays());
163 BOOST_CHECK_EQUAL(convention->settlementCalendar(), readConvention->settlementCalendar());
164 BOOST_CHECK_EQUAL(convention->settlementConvention(), readConvention->settlementConvention());
165 BOOST_CHECK_EQUAL(convention->fixedCurrency(), readConvention->fixedCurrency());
166 BOOST_CHECK_EQUAL(convention->fixedFrequency(), readConvention->fixedFrequency());
167 BOOST_CHECK_EQUAL(convention->fixedConvention(), readConvention->fixedConvention());
168 BOOST_CHECK_EQUAL(convention->fixedDayCounter(), readConvention->fixedDayCounter());
169 BOOST_CHECK_EQUAL(convention->index()->name(), readConvention->index()->name());
170 BOOST_CHECK_EQUAL(convention->eom(), readConvention->eom());
175 BOOST_TEST_MESSAGE(
"Testing commodity future convention construction with day of month based anchor day");
179 set<PE> prohibitedExpiries;
180 prohibitedExpiries.insert(PE(Date(31, Dec, 2020)));
181 prohibitedExpiries.insert(PE(Date(31, Dec, 2021)));
182 prohibitedExpiries.insert(PE(Date(30, Dec, 2022)));
184 QuantLib::ext::shared_ptr<CommodityFutureConvention> convention;
188 BOOST_CHECK_NO_THROW(convention = QuantLib::ext::make_shared<CommodityFutureConvention>(
189 "ICE:B", dayOfMonth,
"Monthly",
"ICE_FuturesEU",
"UK", 2,
"Jan",
"0",
"Preceding",
true,
190 false, optionExpiryDateRule, prohibitedExpiries));
193 BOOST_CHECK_EQUAL(convention->id(),
"ICE:B");
194 BOOST_CHECK(convention->anchorType() == CommodityFutureConvention::AnchorType::DayOfMonth);
195 BOOST_CHECK_EQUAL(convention->dayOfMonth(), 31);
196 BOOST_CHECK_EQUAL(convention->contractFrequency(), Monthly);
198 BOOST_CHECK_EQUAL(convention->expiryCalendar(), UnitedKingdom());
199 BOOST_CHECK_EQUAL(convention->expiryMonthLag(), 2);
200 BOOST_CHECK_EQUAL(convention->oneContractMonth(), Jan);
201 BOOST_CHECK_EQUAL(convention->offsetDays(), 0);
202 BOOST_CHECK_EQUAL(convention->businessDayConvention(), Preceding);
203 BOOST_CHECK(convention->adjustBeforeOffset());
204 BOOST_CHECK(!convention->isAveraging());
205 BOOST_CHECK_EQUAL(convention->optionExpiryOffset(), 3);
207 set<Date> expExpiries{Date(31, Dec, 2020), Date(31, Dec, 2021), Date(30, Dec, 2022)};
208 const auto& proExps = convention->prohibitedExpiries();
209 BOOST_CHECK_EQUAL(proExps.size(), expExpiries.size());
210 for (
const Date& expExpiry : expExpiries) {
211 auto it = proExps.find(PE(expExpiry));
212 BOOST_REQUIRE_MESSAGE(it != proExps.end(),
"Expected date " << io::iso_date(expExpiry) <<
213 " not found in Prohibited Expiries");
214 BOOST_CHECK_EQUAL(it->expiry(), expExpiry);
215 BOOST_CHECK(it->forFuture());
216 BOOST_CHECK_EQUAL(it->futureBdc(), Preceding);
217 BOOST_CHECK(it->forOption());
218 BOOST_CHECK_EQUAL(it->optionBdc(), Preceding);
224 BOOST_TEST_MESSAGE(
"Testing parsing of commodity future convention with day of month based anchor day from XML");
228 xml.append(
"<CommodityFuture>");
229 xml.append(
" <Id>ICE:B</Id>");
230 xml.append(
" <AnchorDay>");
231 xml.append(
" <DayOfMonth>31</DayOfMonth>");
232 xml.append(
" </AnchorDay>");
233 xml.append(
" <ContractFrequency>Monthly</ContractFrequency>");
234 xml.append(
" <Calendar>ICE_FuturesEU</Calendar>");
235 xml.append(
" <ExpiryCalendar>UK</ExpiryCalendar>");
236 xml.append(
" <ExpiryMonthLag>2</ExpiryMonthLag>");
237 xml.append(
" <IsAveraging>false</IsAveraging>");
238 xml.append(
" <OptionExpiryOffset>3</OptionExpiryOffset>");
239 xml.append(
" <ProhibitedExpiries>");
240 xml.append(
" <Dates>");
241 xml.append(
" <Date>2020-12-31</Date>");
242 xml.append(
" <Date>2021-12-31</Date>");
243 xml.append(
" <Date>2022-12-30</Date>");
244 xml.append(
" </Dates>");
245 xml.append(
" </ProhibitedExpiries>");
246 xml.append(
"</CommodityFuture>");
249 QuantLib::ext::shared_ptr<CommodityFutureConvention> convention = QuantLib::ext::make_shared<CommodityFutureConvention>();
250 BOOST_CHECK_NO_THROW(convention->fromXMLString(xml));
253 BOOST_CHECK_EQUAL(convention->id(),
"ICE:B");
254 BOOST_CHECK(convention->anchorType() == CommodityFutureConvention::AnchorType::DayOfMonth);
255 BOOST_CHECK_EQUAL(convention->dayOfMonth(), 31);
256 BOOST_CHECK_EQUAL(convention->contractFrequency(), Monthly);
258 BOOST_CHECK_EQUAL(convention->expiryCalendar(), UnitedKingdom());
259 BOOST_CHECK_EQUAL(convention->expiryMonthLag(), 2);
260 BOOST_CHECK_EQUAL(convention->oneContractMonth(), Jan);
261 BOOST_CHECK_EQUAL(convention->offsetDays(), 0);
262 BOOST_CHECK_EQUAL(convention->businessDayConvention(), Preceding);
263 BOOST_CHECK(convention->adjustBeforeOffset());
264 BOOST_CHECK(!convention->isAveraging());
265 BOOST_CHECK_EQUAL(convention->optionExpiryOffset(), 3);
268 set<Date> expExpiries{ Date(31, Dec, 2020), Date(31, Dec, 2021), Date(30, Dec, 2022) };
269 const auto& proExps = convention->prohibitedExpiries();
270 BOOST_CHECK_EQUAL(proExps.size(), expExpiries.size());
271 for (
const Date& expExpiry : expExpiries) {
272 auto it = proExps.find(PE(expExpiry));
273 BOOST_REQUIRE_MESSAGE(it != proExps.end(),
"Expected date " << io::iso_date(expExpiry) <<
274 " not found in Prohibited Expiries");
275 BOOST_CHECK_EQUAL(it->expiry(), expExpiry);
276 BOOST_CHECK(it->forFuture());
277 BOOST_CHECK_EQUAL(it->futureBdc(), Preceding);
278 BOOST_CHECK(it->forOption());
279 BOOST_CHECK_EQUAL(it->optionBdc(), Preceding);
285 BOOST_TEST_MESSAGE(
"Testing writing of commodity future convention with day of month based anchor day to XML");
289 set<PE> prohibitedExpiries;
290 prohibitedExpiries.insert(PE(Date(31, Dec, 2020),
true, Following,
false, ModifiedFollowing));
291 prohibitedExpiries.insert(PE(Date(31, Dec, 2021),
false, Preceding,
true, ModifiedPreceding));
292 prohibitedExpiries.insert(PE(Date(31, Dec, 2021),
false, Following));
294 QuantLib::ext::shared_ptr<CommodityFutureConvention> convention;
298 BOOST_CHECK_NO_THROW(convention = QuantLib::ext::make_shared<CommodityFutureConvention>(
299 "ICE:B", dayOfMonth,
"Monthly",
"ICE_FuturesEU",
"UK", 2,
"Jan",
"0",
"Preceding",
true,
300 false, optionExpiryDateRule, prohibitedExpiries));
303 string xml = convention->toXMLString();
306 QuantLib::ext::shared_ptr<CommodityFutureConvention> readConvention = QuantLib::ext::make_shared<CommodityFutureConvention>();
307 BOOST_CHECK_NO_THROW(readConvention->fromXMLString(xml));
310 BOOST_CHECK_EQUAL(convention->id(), readConvention->id());
311 BOOST_CHECK(convention->anchorType() == readConvention->anchorType());
312 BOOST_CHECK_EQUAL(convention->dayOfMonth(), readConvention->dayOfMonth());
313 BOOST_CHECK_EQUAL(convention->contractFrequency(), readConvention->contractFrequency());
314 BOOST_CHECK_EQUAL(convention->calendar(), readConvention->calendar());
315 BOOST_CHECK_EQUAL(convention->expiryMonthLag(), readConvention->expiryMonthLag());
316 BOOST_CHECK_EQUAL(convention->oneContractMonth(), readConvention->oneContractMonth());
317 BOOST_CHECK_EQUAL(convention->offsetDays(), readConvention->offsetDays());
318 BOOST_CHECK_EQUAL(convention->businessDayConvention(), readConvention->businessDayConvention());
319 BOOST_CHECK_EQUAL(convention->adjustBeforeOffset(), readConvention->adjustBeforeOffset());
320 BOOST_CHECK_EQUAL(convention->isAveraging(), readConvention->isAveraging());
322 const auto& proExps = convention->prohibitedExpiries();
323 const auto& readProExps = readConvention->prohibitedExpiries();
324 BOOST_CHECK_EQUAL(proExps.size(), readProExps.size());
325 for (
const auto& pe : proExps) {
326 auto it = readProExps.find(pe);
327 BOOST_REQUIRE_MESSAGE(it != readProExps.end(),
"Expected date " << io::iso_date(pe.expiry()) <<
328 " not found in Prohibited Expiries");
329 BOOST_CHECK_EQUAL(it->expiry(), pe.expiry());
330 BOOST_CHECK_EQUAL(it->forFuture(), pe.forFuture());
331 BOOST_CHECK_EQUAL(it->futureBdc(), pe.futureBdc());
332 BOOST_CHECK_EQUAL(it->forOption(), pe.forOption());
333 BOOST_CHECK_EQUAL(it->optionBdc(), pe.optionBdc());
339 BOOST_TEST_MESSAGE(
"Testing Ibor Index convention construction with Tenor");
340 testIborIndexConvention(
"AED-EIBOR-3M",
"AED",
"ACT/360", 2,
"MF",
false);
345 BOOST_TEST_MESSAGE(
"Testing Ibor Index convention construction with Tenor");
346 testIborIndexConvention(
"AED-EIBOR",
"AED",
"ACT/360", 2,
"MF",
false);
350 BOOST_TEST_MESSAGE(
"Testing Ibor Index convention construction with Tenor");
351 testIborIndexConvention(
"CNY-REPO-7D",
"CNY",
"A365F", 2,
"MF",
true,
"CNY-REPO-1W");
354BOOST_AUTO_TEST_SUITE_END()
356BOOST_AUTO_TEST_SUITE_END()
Class to hold prohibited expiry information.
Currency and instrument specific conventions/defaults.
Classes to differentiate constructors below.
BOOST_AUTO_TEST_CASE(testCrossCcyFixFloatSwapConventionConstruction)