Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
fixings.cpp File Reference
#include <boost/make_shared.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <ored/configuration/conventions.hpp>
#include <ored/configuration/curveconfigurations.hpp>
#include <ored/marketdata/csvloader.hpp>
#include <ored/marketdata/fixings.hpp>
#include <ored/marketdata/todaysmarket.hpp>
#include <ored/marketdata/todaysmarketparameters.hpp>
#include <ored/portfolio/enginefactory.hpp>
#include <ored/portfolio/fixingdates.hpp>
#include <ored/portfolio/portfolio.hpp>
#include <ored/portfolio/trade.hpp>
#include <ored/utilities/csvfilereader.hpp>
#include <ored/utilities/indexparser.hpp>
#include <ored/utilities/to_string.hpp>
#include <qle/indexes/dividendmanager.hpp>
#include <oret/datapaths.hpp>
#include <oret/toplevelfixture.hpp>
#include <ql/time/calendars/weekendsonly.hpp>
#include <tuple>

Go to the source code of this file.

Functions

 BOOST_DATA_TEST_CASE_F (F, testTradeTypes, bdata::make(tradeTypes) *bdata::make(tradeCases) *bdata::make(bools) *bdata::make(bools), tradeType, tradeCase, includeSettlementDateFlows, enforcesTodaysHistoricFixings)
 
 BOOST_AUTO_TEST_CASE (testModifyInflationFixings)
 
 BOOST_AUTO_TEST_CASE (testAddMarketFixings)
 
 BOOST_FIXTURE_TEST_CASE (testFxNotionalResettingSwapFirstCoupon, F)
 
 BOOST_FIXTURE_TEST_CASE (testDividends, F)
 

Function Documentation

◆ BOOST_DATA_TEST_CASE_F()

BOOST_DATA_TEST_CASE_F ( ,
testTradeTypes  ,
bdata::make(tradeTypes) *bdata::make(tradeCases) *bdata::make(bools) *bdata::make(bools)  ,
tradeType  ,
tradeCase  ,
includeSettlementDateFlows  ,
enforcesTodaysHistoricFixings   
)

Definition at line 190 of file fixings.cpp.

192 {
193
194 // Set the flag determining what happens if fixings are required today
195 Settings::instance().enforcesTodaysHistoricFixings() = enforcesTodaysHistoricFixings;
196
197 // Set the flag determining what happens when cashflows happen today
198 Settings::instance().includeTodaysCashFlows() = includeSettlementDateFlows;
199
200 // Read in the trade
201 Portfolio p;
202 string portfolioFile = "trades/" + tradeType + "/" + tradeCase + ".xml";
203 p.fromFile(TEST_INPUT_FILE(portfolioFile));
204 BOOST_REQUIRE_MESSAGE(p.size() == 1, "Expected portfolio to contain a single trade");
205
206 // Ask for fixings before trades are built should return empty set
207 auto m = p.fixings(today);
208 BOOST_CHECK_MESSAGE(m.empty(), "Expected fixings to be empty when trades not built");
209
210 // Build the portfolio and retrieve the fixings
211 p.build(engineFactory);
212 m = p.fixings(today);
213
214 // Check the retrieved fixings against the expected results
215 auto exp = tradeTypeExpected();
216 auto key = make_tuple(tradeType, tradeCase, includeSettlementDateFlows, enforcesTodaysHistoricFixings);
217 if (exp.count(key) == 0) {
218 // Expected result is no required fixings
219 BOOST_CHECK_MESSAGE(m.empty(), "Expected no required fixings for ["
220 << tradeType << ", " << tradeCase << ", "
221 << ore::data::to_string(includeSettlementDateFlows) << ", "
222 << ore::data::to_string(enforcesTodaysHistoricFixings)
223 << "] but got a map containing " << m.size() << " indices");
224
225 // Trade should not throw if we ask for NPV
226 BOOST_CHECK_NO_THROW(p.trades().begin()->second->instrument()->NPV());
227
228 } else {
229 // Check the retrieved fixings against the expected fixings
230 auto expMap = exp.at(key);
231 BOOST_CHECK_EQUAL(expMap.size(), m.size());
232 for (const auto& [indexName, expectedDates] : expMap) {
233 BOOST_CHECK_MESSAGE(m.count(indexName), "Could not find index " <<indexName << " in retrieved fixings");
234 std::set<QuantLib::Date> actualDates;
235 for (const auto& [d, _] : m.at(indexName)) {
236 actualDates.insert(d);
237 }
238 BOOST_CHECK_EQUAL_COLLECTIONS(expectedDates.begin(), expectedDates.end(), actualDates.begin(),
239 actualDates.end());
240 }
241
242 // Trade should throw if we ask for NPV and have not added the fixings
243 // If it is the zciis trade, it won't throw because the fixings were added for the bootstrap
244 if (tradeType != "zciis_with_interp" && tradeType != "cpi_swap_with_interp") {
245 BOOST_CHECK_THROW(p.trades().begin()->second->instrument()->NPV(), Error);
246 }
247
248 // Add the fixings
249 loadFixings(m);
250
251 // Trade should now not throw when we try to price it
252 BOOST_CHECK_NO_THROW(p.trades().begin()->second->instrument()->NPV());
253 }
254}
Serializable portfolio.
Definition: portfolio.hpp:43
const std::map< std::string, QuantLib::ext::shared_ptr< Trade > > & trades() const
Return the map tradeId -> trade.
Definition: portfolio.cpp:162
std::map< std::string, RequiredFixings::FixingDates > fixings(const QuantLib::Date &settlementDate=QuantLib::Date()) const
Definition: portfolio.cpp:220
QuantLib::Size size() const
Portfolio size.
Definition: portfolio.hpp:68
void build(const QuantLib::ext::shared_ptr< EngineFactory > &, const std::string &context="unspecified", const bool emitStructuredError=true)
Call build on all trades in the portfolio, the context is included in error messages.
Definition: portfolio.cpp:122
void fromFile(const std::string &filename)
Definition: xmlutils.cpp:150
RandomVariable exp(RandomVariable x)
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Real at(const Size i) const
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [1/2]

BOOST_AUTO_TEST_CASE ( testModifyInflationFixings  )

Definition at line 256 of file fixings.cpp.

256 {
257
258 // Original fixings
259 map<string, RequiredFixings::FixingDates> fixings = {
260 {"EUHICP", RequiredFixings::FixingDates({Date(1, Jan, 2019), Date(1, Dec, 2018), Date(1, Nov, 2018)}, true)},
261 {"USCPI", RequiredFixings::FixingDates({Date(1, Dec, 2018), Date(1, Nov, 2018), Date(22, Oct, 2018),
262 Date(1, Feb, 2018), Date(1, Feb, 2016)},
263 true)},
264 {"EUR-EURIBOR-3M", RequiredFixings::FixingDates({Date(18, Dec, 2018), Date(13, Feb, 2019)}, true)}};
265
266 // Expected fixings after inflation modification
267 map<string, RequiredFixings::FixingDates> expectedFixings = {
268 {"EUHICP", RequiredFixings::FixingDates({Date(31, Jan, 2019), Date(31, Dec, 2018), Date(30, Nov, 2018)}, true)},
269 {"USCPI", RequiredFixings::FixingDates({Date(31, Dec, 2018), Date(30, Nov, 2018), Date(22, Oct, 2018),
270 Date(28, Feb, 2018), Date(29, Feb, 2016)},
271 true)},
272 {"EUR-EURIBOR-3M", RequiredFixings::FixingDates({Date(18, Dec, 2018), Date(13, Feb, 2019)}, true)}};
273
274 // Amend the inflation portion of the fixings
276
277 // Compare contents of the output files
278 BOOST_CHECK_EQUAL(expectedFixings.size(), fixings.size());
279 for (const auto& [indexname, expectedFixingDates] : expectedFixings) {
280 BOOST_CHECK_MESSAGE(fixings.count(indexname), "Could not find index " << indexname << " in retrieved fixings");
281 std::set<QuantLib::Date> expectedDates;
282 for (const auto& [d, _] : expectedFixingDates) {
283 expectedDates.insert(d);
284 }
285
286 std::set<QuantLib::Date> actualDates;
287 for (const auto& [d, _] : fixings[indexname]) {
288 actualDates.insert(d);
289 }
290 BOOST_CHECK_EQUAL_COLLECTIONS(expectedDates.begin(), expectedDates.end(), actualDates.begin(),
291 actualDates.end());
292 }
293}
void amendInflationFixingDates(std::map< std::string, RequiredFixings::FixingDates > &fixings)
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [2/2]

BOOST_AUTO_TEST_CASE ( testAddMarketFixings  )

Definition at line 295 of file fixings.cpp.

295 {
296
297 // Set the evaluation date
298 Date asof(21, Feb, 2019);
299 Settings::instance().evaluationDate() = asof;
300
301 // Set up a simple TodaysMarketParameters
302 TodaysMarketParameters mktParams;
304
305 // Add discount curves, we expect market fixings for EUR-EONIA
306 map<string, string> m = {{"EUR", "Yield/EUR/EUR-EONIA"}, {"USD", "Yield/USD/USD-IN-EUR"}};
307 mktParams.addMarketObject(MarketObject::DiscountCurve, Market::defaultConfiguration, m);
308
309 // Add ibor index curves
310 m = {{"EUR-EURIBOR-3M", "Yield/EUR/EUR-EURIBOR-3M"},
311 {"USD-FedFunds", "Yield/USD/USD-FedFunds"},
312 {"USD-LIBOR-3M", "Yield/USD/USD-LIBOR-3M"}};
313 mktParams.addMarketObject(MarketObject::IndexCurve, Market::defaultConfiguration, m);
314
315 // Add zero inflation curves
316 m = {{"EUHICPXT", "Inflation/EUHICPXT/EUHICPXT_ZC_Swaps"}, {"USCPI", "Inflation/USCPI/USCPI_ZC_Swaps"}};
317 mktParams.addMarketObject(MarketObject::ZeroInflationCurve, Market::defaultConfiguration, m);
318
319 // Add yoy inflation curves
320 m = {{"EUHICPXT", "Inflation/EUHICPXT/EUHICPXT_YOY_Swaps"}, {"UKRPI", "Inflation/UKRPI/UKRPI_YOY_Swaps"}};
321 mktParams.addMarketObject(MarketObject::YoYInflationCurve, Market::defaultConfiguration, m);
322
323 // Expected additional market fixings
324 set<Date> inflationDates = {Date(1, Feb, 2019), Date(1, Jan, 2019), Date(1, Dec, 2018), Date(1, Nov, 2018),
325 Date(1, Oct, 2018), Date(1, Sep, 2018), Date(1, Aug, 2018), Date(1, Jul, 2018),
326 Date(1, Jun, 2018), Date(1, May, 2018), Date(1, Apr, 2018), Date(1, Mar, 2018),
327 Date(1, Feb, 2018)};
328 set<Date> iborDates = {Date(21, Feb, 2019), Date(20, Feb, 2019), Date(19, Feb, 2019),
329 Date(18, Feb, 2019), Date(15, Feb, 2019), Date(14, Feb, 2019)};
330
331 // Default for OIS dates is a lookback of 4 months on weekend only calendar => 21 Feb 2019 -> 21 Oct 2018.
332 // 21 Oct 2018 is a Sunday => 22 Oct 2018 is the start of the lookback.
333 set<Date> oisDates;
334 Date oisDate(22, Oct, 2018);
335 WeekendsOnly cal;
336 while (oisDate <= asof) {
337 oisDates.insert(oisDate);
338 oisDate = cal.advance(oisDate, 1 * Days);
339 }
340
341 map<string, RequiredFixings::FixingDates> expectedFixings = {
342 {"EUHICPXT", RequiredFixings::FixingDates(inflationDates, false)},
343 {"USCPI", RequiredFixings::FixingDates(inflationDates, false)},
344 {"UKRPI", RequiredFixings::FixingDates(inflationDates, false)},
345 {"EUR-EURIBOR-3M", RequiredFixings::FixingDates(iborDates, false)},
346 {"USD-FedFunds", RequiredFixings::FixingDates(oisDates, false)},
347 {"USD-LIBOR-3M", RequiredFixings::FixingDates(iborDates, false)},
348 {"EUR-EONIA", RequiredFixings::FixingDates(oisDates, false)}};
349
350 // Populate empty fixings map using the function to be tested
351 map<string, RequiredFixings::FixingDates> fixings;
352 addMarketFixingDates(asof, fixings, mktParams);
353
354 // Check the results
355 BOOST_CHECK_EQUAL(expectedFixings.size(), fixings.size());
356 for (const auto& [indexName, expectedFixingDates] : expectedFixings) {
357 BOOST_CHECK_MESSAGE(fixings.count(indexName), "Could not find index " << indexName << " in retrieved fixings");
358 std::set<QuantLib::Date> expectedDates;
359 for (const auto& [d, _] : expectedFixingDates) {
360 expectedDates.insert(d);
361 }
362
363 std::set<QuantLib::Date> actualDates;
364 for (const auto& [d, _] : fixings[indexName]) {
365 actualDates.insert(d);
366 }
367 BOOST_CHECK_EQUAL_COLLECTIONS(expectedDates.begin(), expectedDates.end(), actualDates.begin(),
368 actualDates.end());
369 }
370}
static const string defaultConfiguration
Default configuration label.
Definition: market.hpp:296
void addMarketObject(const MarketObject o, const string &id, const map< string, string > &assignments)
void addConfiguration(const string &name, const MarketConfiguration &configuration)
void addMarketFixingDates(const Date &asof, map< string, RequiredFixings::FixingDates > &fixings, const TodaysMarketParameters &mktParams, const Period &iborLookback, const Period &oisLookback, const Period &bmaLookback, const Period &inflationLookback)
+ Here is the call graph for this function:

◆ BOOST_FIXTURE_TEST_CASE() [1/2]

BOOST_FIXTURE_TEST_CASE ( testFxNotionalResettingSwapFirstCoupon  ,
 
)

Definition at line 372 of file fixings.cpp.

372 {
373
374 // Set the flag determining what happens if fixings are required today
375 Settings::instance().enforcesTodaysHistoricFixings() = true;
376
377 // Set the flag determining what happens when cashflows happen today
378 Settings::instance().includeTodaysCashFlows() = true;
379
380 // Read in the trade
381 Portfolio p;
382 string portfolioFile = "trades/xccy_resetting_swap/simple_case_in_first_coupon.xml";
383 p.fromFile(TEST_INPUT_FILE(portfolioFile));
384 BOOST_REQUIRE_MESSAGE(p.size() == 1, "Expected portfolio to contain a single trade");
385
386 // Ask for fixings before trades are built should return empty set
387 auto m = p.fixings(today);
388 BOOST_CHECK_MESSAGE(m.empty(), "Expected fixings to be empty when trades not built");
389
390 // Build the portfolio and retrieve the fixings
391 p.build(engineFactory);
392 m = p.fixings(today);
393
394 // Expected results
395 map<string, Date> exp = {{"USD-LIBOR-3M", Date(5, Feb, 2019)}, {"EUR-EURIBOR-3M", Date(5, Feb, 2019)}};
396
397 // Check the expected results against the actual results
398 BOOST_CHECK_EQUAL(m.size(), exp.size());
399 for (const auto& kv : exp) {
400 BOOST_CHECK_MESSAGE(m.count(kv.first) == 1, "Could not find index " << kv.first << " in retrieved fixings");
401 if (m.count(kv.first) == 1) {
402 BOOST_CHECK_EQUAL(m.at(kv.first).size(), 1);
403 BOOST_CHECK_EQUAL(kv.second, m.at(kv.first).begin()->first);
404 }
405 }
406
407 // Trade should throw if we ask for NPV and have not added the fixings
408 BOOST_CHECK_THROW(p.trades().begin()->second->instrument()->NPV(), Error);
409
410 // Add the fixings
411 loadFixings(m);
412
413 // Trade should now not throw when we try to price it
414 BOOST_CHECK_NO_THROW(p.trades().begin()->second->instrument()->NPV());
415}
+ Here is the call graph for this function:

◆ BOOST_FIXTURE_TEST_CASE() [2/2]

BOOST_FIXTURE_TEST_CASE ( testDividends  ,
 
)

Definition at line 417 of file fixings.cpp.

417 {
418
419 const string equityName = "RIC:DMIWO00000GUS";
420
421 auto eq = parseEquityIndex("EQ-" + equityName);
422 BOOST_REQUIRE_MESSAGE(eq, "Could not parse equity index EQ-" + equityName);
423
424 BOOST_REQUIRE_MESSAGE(DividendManager::instance().hasHistory(eq->name()),
425 "Could not find index " << eq->name() << " in DividendManager");
426 map<Date, QuantExt::Dividend> divMap;
427 const set<QuantExt::Dividend>& dividends = eq->dividendFixings();
428 for (const auto& d : dividends)
429 divMap[d.exDate] = d;
430
431 // Expected results
432 map<Date, Real> exp = {{Date(1, Nov, 2018), 25.313}, {Date(1, Dec, 2018), 15.957}};
433
434 BOOST_CHECK_EQUAL(dividends.size(), exp.size());
435 for (const auto& kv : exp) {
436 BOOST_CHECK_EQUAL(divMap[kv.first].rate, kv.second);
437 }
438}
QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > parseEquityIndex(const string &s)
Convert std::string (e.g SP5) to QuantExt::EquityIndex.
+ Here is the call graph for this function: