Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
cube.cpp File Reference
#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
#include <orea/cube/inmemorycube.hpp>
#include <orea/cube/cube_io.hpp>
#include <orea/cube/npvcube.hpp>
#include <orea/cube/jaggedcube.hpp>
#include <orea/engine/filteredsensitivitystream.hpp>
#include <orea/engine/observationmode.hpp>
#include <orea/engine/parametricvar.hpp>
#include <orea/engine/riskfilter.hpp>
#include <orea/engine/sensitivityaggregator.hpp>
#include <orea/engine/sensitivityanalysis.hpp>
#include <orea/engine/sensitivitycubestream.hpp>
#include <orea/engine/sensitivityfilestream.hpp>
#include <orea/engine/sensitivityinmemorystream.hpp>
#include <orea/engine/sensitivityrecord.hpp>
#include <orea/engine/sensitivitystream.hpp>
#include <orea/engine/stresstest.hpp>
#include <orea/engine/valuationcalculator.hpp>
#include <orea/engine/valuationengine.hpp>
#include <orea/scenario/crossassetmodelscenariogenerator.hpp>
#include <orea/scenario/scenariosimmarket.hpp>
#include <orea/scenario/scenariosimmarketparameters.hpp>
#include <orea/scenario/simplescenariofactory.hpp>
#include <ored/model/crossassetmodelbuilder.hpp>
#include <ored/model/lgmdata.hpp>
#include <ored/portfolio/builders/swap.hpp>
#include <ored/portfolio/portfolio.hpp>
#include <ored/portfolio/swap.hpp>
#include <ored/utilities/log.hpp>
#include <ored/utilities/osutils.hpp>
#include <ql/math/randomnumbers/mt19937uniformrng.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/time/date.hpp>
#include <ql/time/daycounters/actualactual.hpp>
#include <oret/toplevelfixture.hpp>
#include <test/oreatoplevelfixture.hpp>
#include "testmarket.hpp"

Go to the source code of this file.

Functions

unsigned long randInt (MersenneTwisterUniformRng &rng, Size min, Size max)
 
const string & randString (MersenneTwisterUniformRng &rng, const vector< string > &strs)
 
bool randBoolean (MersenneTwisterUniformRng &rng)
 
QuantLib::ext::shared_ptr< PortfoliobuildPortfolio (Size portfolioSize, QuantLib::ext::shared_ptr< EngineFactory > &factory)
 
 BOOST_AUTO_TEST_CASE (testSinglePrecisionInMemoryCube)
 
 BOOST_AUTO_TEST_CASE (testDoublePrecisionInMemoryCube)
 
 BOOST_AUTO_TEST_CASE (testSinglePrecisionInMemoryCubeN)
 
 BOOST_AUTO_TEST_CASE (testDoublePrecisionInMemoryCubeN)
 
 BOOST_AUTO_TEST_CASE (testDoublePrecisionInMemoryCubeFileIO)
 
 BOOST_AUTO_TEST_CASE (testDoublePrecisionInMemoryCubeFileNIO)
 
 BOOST_AUTO_TEST_CASE (testInMemoryCubeGetSetbyDateID)
 
 BOOST_AUTO_TEST_CASE (testSinglePrecisionJaggedCube)
 
 BOOST_AUTO_TEST_CASE (testDoublePrecisionJaggedCube)
 

Function Documentation

◆ randInt()

unsigned long randInt ( MersenneTwisterUniformRng &  rng,
Size  min,
Size  max 
)

Definition at line 255 of file cube.cpp.

255 {
256 return min + (rng.nextInt32() % (max + 1 - min));
257}
RandomVariable max(RandomVariable x, const RandomVariable &y)
RandomVariable min(RandomVariable x, const RandomVariable &y)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ randString()

const string & randString ( MersenneTwisterUniformRng &  rng,
const vector< string > &  strs 
)

Definition at line 259 of file cube.cpp.

259 {
260 return strs[randInt(rng, 0, strs.size() - 1)];
261}
unsigned long randInt(MersenneTwisterUniformRng &rng, Size min, Size max)
Definition: cube.cpp:255
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ randBoolean()

bool randBoolean ( MersenneTwisterUniformRng &  rng)

Definition at line 262 of file cube.cpp.

262{ return randInt(rng, 0, 1) == 1; }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildPortfolio()

QuantLib::ext::shared_ptr< Portfolio > buildPortfolio ( Size  portfolioSize,
QuantLib::ext::shared_ptr< EngineFactory > &  factory 
)

Definition at line 264 of file cube.cpp.

264 {
265
266 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
267
268 vector<string> ccys = {"EUR", "USD", "GBP", "JPY", "CHF"};
269
270 map<string, vector<string>> indices = {{"EUR", {"EUR-EURIBOR-6M"}},
271 {"USD", {"USD-LIBOR-3M"}},
272 {"GBP", {"GBP-LIBOR-6M"}},
273 {"CHF", {"CHF-LIBOR-6M"}},
274 {"JPY", {"JPY-LIBOR-6M"}}};
275
276 vector<string> fixedTenors = {"6M", "1Y"};
277
278 Size minTerm = 2;
279 Size maxTerm = 30;
280
281 Size minFixedBps = 10;
282 Size maxFixedBps = 400;
283
284 Size seed = 5; // keep this constant to ensure portfolio doesn't change
285 MersenneTwisterUniformRng rng(seed);
286
287 Date today = Settings::instance().evaluationDate();
288 Calendar cal = TARGET();
289 string calStr = "TARGET";
290 string conv = "MF";
291 string rule = "Forward";
292 Size days = 2;
293 string fixDC = "30/360";
294 string floatDC = "ACT/365";
295
296 vector<double> notional(1, 1000000);
297 vector<double> spread(1, 0);
298
299 for (Size i = 0; i < portfolioSize; i++) {
300 Size term = portfolioSize == 1 ? 20 : randInt(rng, minTerm, maxTerm);
301
302 // Start today +/- 1 Year
303 Date startDate = portfolioSize == 1 ? cal.adjust(today) : cal.adjust(today - 365 + randInt(rng, 0, 730));
304 Date endDate = cal.adjust(startDate + term * Years);
305
306 // date 2 string
307 std::ostringstream oss;
308 oss << io::iso_date(startDate);
309 string start(oss.str());
310 oss.str("");
311 oss.clear();
312 oss << io::iso_date(endDate);
313 string end(oss.str());
314
315 // ccy + index
316 string ccy = portfolioSize == 1 ? "EUR" : randString(rng, ccys);
317 string index = portfolioSize == 1 ? "EUR-EURIBOR-6M" : randString(rng, indices[ccy]);
318 string floatFreq = portfolioSize == 1 ? "6M" : index.substr(index.find('-', 4) + 1);
319
320 // fixed details
321 Real fixedRate = portfolioSize == 1 ? 0.02 : randInt(rng, minFixedBps, maxFixedBps) / 100.0;
322 string fixFreq = portfolioSize == 1 ? "1Y" : randString(rng, fixedTenors);
323
324 // envelope
325 Envelope env("CP");
326
327 // Schedules
328 ScheduleData floatSchedule(ScheduleRules(start, end, floatFreq, calStr, conv, conv, rule));
329 ScheduleData fixedSchedule(ScheduleRules(start, end, fixFreq, calStr, conv, conv, rule));
330
331 bool isPayer = randBoolean(rng);
332
333 // fixed Leg - with dummy rate
334 LegData fixedLeg(QuantLib::ext::make_shared<FixedLegData>(vector<double>(1, fixedRate)), isPayer, ccy, fixedSchedule,
335 fixDC, notional);
336
337 // float Leg
338 vector<double> spreads(1, 0);
339 LegData floatingLeg(QuantLib::ext::make_shared<FloatingLegData>(index, days, false, spread), !isPayer, ccy,
340 floatSchedule, floatDC, notional);
341
342 QuantLib::ext::shared_ptr<Trade> swap(new ore::data::Swap(env, floatingLeg, fixedLeg));
343
344 // id
345 oss.clear();
346 oss.str("");
347 oss << "Trade_" << i + 1;
348 swap->id() = oss.str();
349
350 portfolio->add(swap);
351 }
352 // portfolio->save("port.xml");
353
354 portfolio->build(factory);
355
356 if (portfolio->size() != portfolioSize)
357 BOOST_ERROR("Failed to build portfolio (got " << portfolio->size() << " expected " << portfolioSize << ")");
358
359 // Dump stats about portfolio
360 Time maturity = 0;
361 DayCounter dc = ActualActual(ActualActual::ISDA);
362 map<string, Size> fixedFreqs;
363 map<string, Size> floatFreqs;
364 for (const auto& [tradeId, trade] : portfolio->trades()) {
365 maturity += dc.yearFraction(today, trade->maturity());
366
367 // fixed Freq
368 QuantLib::ext::shared_ptr<ore::data::Swap> swap = QuantLib::ext::dynamic_pointer_cast<ore::data::Swap>(trade);
369 string floatFreq = swap->legData()[0].schedule().rules().front().tenor();
370 string fixFreq = swap->legData()[1].schedule().rules().front().tenor();
371 QL_REQUIRE(swap->legData()[0].legType() == "Floating" && swap->legData()[1].legType() == "Fixed", "Leg mixup");
372 if (fixedFreqs.find(fixFreq) == fixedFreqs.end())
373 fixedFreqs[fixFreq] = 1;
374 else
375 fixedFreqs[fixFreq]++;
376 if (floatFreqs.find(floatFreq) == floatFreqs.end())
377 floatFreqs[floatFreq] = 1;
378 else
379 floatFreqs[floatFreq]++;
380 }
381 maturity /= portfolioSize;
382 BOOST_TEST_MESSAGE("Portfolio Size : " << portfolioSize);
383 BOOST_TEST_MESSAGE("Average Maturity : " << maturity);
384 std::ostringstream oss;
385 for (Size i = 0; i < ccys.size(); i++)
386 oss << ccys[i] << " ";
387 BOOST_TEST_MESSAGE("Currencies : " << oss.str());
388 // dump % breakdown of tenors
389 map<string, Size>::iterator it;
390 BOOST_TEST_MESSAGE("Fixed Tenors : ");
391 for (it = fixedFreqs.begin(); it != fixedFreqs.end(); ++it) {
392 Real perc = 100 * it->second / (Real)portfolioSize;
393 BOOST_TEST_MESSAGE(" " << it->first << " " << perc << " %");
394 }
395 BOOST_TEST_MESSAGE("Floating Tenors : ");
396 for (it = floatFreqs.begin(); it != floatFreqs.end(); ++it) {
397 Real perc = 100 * it->second / (Real)portfolioSize;
398 BOOST_TEST_MESSAGE(" " << it->first << " " << perc << " %");
399 }
400
401 return portfolio;
402}
bool randBoolean(MersenneTwisterUniformRng &rng)
Definition: cube.cpp:262
const string & randString(MersenneTwisterUniformRng &rng, const vector< string > &strs)
Definition: cube.cpp:259
Time maturity
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BOOST_AUTO_TEST_CASE() [1/9]

BOOST_AUTO_TEST_CASE ( testSinglePrecisionInMemoryCube  )

Definition at line 408 of file cube.cpp.

408 {
409 // trades, dates, samples
410 std::set<string> ids {string("id")}; // the overlap doesn't matter
411 vector<Date> dates(100, Date());
412 Size samples = 1000;
413 SinglePrecisionInMemoryCube c(Date(), ids, dates, samples);
414 testCube(c, "SinglePrecisionInMemoryCube", 1e-5);
415}
InMemoryCube of fixed depth 1.

◆ BOOST_AUTO_TEST_CASE() [2/9]

BOOST_AUTO_TEST_CASE ( testDoublePrecisionInMemoryCube  )

Definition at line 417 of file cube.cpp.

417 {
418 std::set<string> ids{string("id")}; // the overlap doesn't matter
419 vector<Date> dates(100, Date());
420 Size samples = 1000;
421 DoublePrecisionInMemoryCube c(Date(), ids, dates, samples);
422 testCube(c, "DoublePrecisionInMemoryCube", 1e-14);
423}

◆ BOOST_AUTO_TEST_CASE() [3/9]

BOOST_AUTO_TEST_CASE ( testSinglePrecisionInMemoryCubeN  )

Definition at line 425 of file cube.cpp.

425 {
426 std::set<string> ids{string("id")}; // the overlap doesn't matter
427 vector<Date> dates(50, Date());
428 Size samples = 200;
429 Size depth = 6;
430 SinglePrecisionInMemoryCubeN c(Date(), ids, dates, samples, depth);
431 testCube(c, "SinglePrecisionInMemoryCubeN", 1e-5);
432}
InMemoryCube of variable depth.

◆ BOOST_AUTO_TEST_CASE() [4/9]

BOOST_AUTO_TEST_CASE ( testDoublePrecisionInMemoryCubeN  )

Definition at line 434 of file cube.cpp.

434 {
435 std::set<string> ids{string("id")}; // the overlap doesn't matter
436 vector<Date> dates(50, Date());
437 Size samples = 200;
438 Size depth = 6;
439 DoublePrecisionInMemoryCubeN c(Date(), ids, dates, samples, depth);
440 testCube(c, "DoublePrecisionInMemoryCubeN", 1e-14);
441}

◆ BOOST_AUTO_TEST_CASE() [5/9]

BOOST_AUTO_TEST_CASE ( testDoublePrecisionInMemoryCubeFileIO  )

Definition at line 443 of file cube.cpp.

443 {
444 std::set<string> ids{string("id")}; // the overlap doesn't matter
445 Date d(1, QuantLib::Jan, 2016); // need a real date here
446 vector<Date> dates(100, d);
447 Size samples = 1000;
448 auto c = QuantLib::ext::make_shared<DoublePrecisionInMemoryCube>(d, ids, dates, samples);
449 testCubeFileIO<DoublePrecisionInMemoryCube>(c, "DoublePrecisionInMemoryCube", 1e-14, true);
450}

◆ BOOST_AUTO_TEST_CASE() [6/9]

BOOST_AUTO_TEST_CASE ( testDoublePrecisionInMemoryCubeFileNIO  )

Definition at line 452 of file cube.cpp.

452 {
453 std::set<string> ids{string("id")}; // the overlap doesn't matter
454 Date d(1, QuantLib::Jan, 2016); // need a real date here
455 vector<Date> dates(50, d);
456 Size samples = 200;
457 Size depth = 6;
458 auto c = QuantLib::ext::make_shared<DoublePrecisionInMemoryCubeN>(d, ids, dates, samples, depth);
459 testCubeFileIO<DoublePrecisionInMemoryCubeN>(c, "DoublePrecisionInMemoryCubeN", 1e-14, true);
460}

◆ BOOST_AUTO_TEST_CASE() [7/9]

BOOST_AUTO_TEST_CASE ( testInMemoryCubeGetSetbyDateID  )

Definition at line 462 of file cube.cpp.

462 {
463 std::set<string> ids = {"id1", "id2", "id3"}; // the overlap doesn't matter
464 Date today = Date::todaysDate();
465 vector<Date> dates = {today + QuantLib::Period(1, QuantLib::Days), today + QuantLib::Period(2, QuantLib::Days),
466 today + QuantLib::Period(3, QuantLib::Days)};
467 Size samples = 1;
468 DoublePrecisionInMemoryCube cube(Date(), ids, dates, samples);
469 testCubeGetSetbyDateID(cube, 1e-14);
470}

◆ BOOST_AUTO_TEST_CASE() [8/9]

BOOST_AUTO_TEST_CASE ( testSinglePrecisionJaggedCube  )

Definition at line 472 of file cube.cpp.

472 {
473
474 SavedSettings backup;
475
476 Size portfolioSize = 100;
477 Size depth = 10;
478
479 Date today = Date(15, December, 2016);
480 Settings::instance().evaluationDate() = today;
481 string dateGridStr = "270,2W";
482 QuantLib::ext::shared_ptr<DateGrid> d = QuantLib::ext::make_shared<DateGrid>(dateGridStr);
483
484 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
485
486 // Init Market
487 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<testsuite::TestMarket>(today);
488
489 data->model("EuropeanSwaption") = "BlackBachelier";
490 data->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
491 data->model("Swap") = "DiscountedCashflows";
492 data->engine("Swap") = "DiscountingSwapEngine";
493 data->model("FxOption") = "GarmanKohlhagen";
494 data->engine("FxOption") = "AnalyticEuropeanEngine";
495
496 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(data, initMarket);
497
498 QuantLib::ext::shared_ptr<Portfolio> portfolio = buildPortfolio(portfolioSize, factory);
499
500 Size samples = 10;
501 JaggedCube<float> jaggedCube(today, portfolio, d->dates(), samples, depth);
502 testCube(jaggedCube, "SinglePrecisionJaggedCube", 1e-5, portfolio, d);
503 IndexManager::instance().clearHistories();
504}
JaggedCube stores the cube in memory using a vector of trade specific blocks.
Definition: jaggedcube.hpp:140
QuantLib::ext::shared_ptr< Portfolio > buildPortfolio(Size portfolioSize, QuantLib::ext::shared_ptr< EngineFactory > &factory)
Definition: cube.cpp:264
data
+ Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [9/9]

BOOST_AUTO_TEST_CASE ( testDoublePrecisionJaggedCube  )

Definition at line 506 of file cube.cpp.

506 {
507
508 SavedSettings backup;
509
510 Size portfolioSize = 100;
511 Size depth = 10;
512
513 Date today = Date(15, December, 2016);
514 Settings::instance().evaluationDate() = today;
515 string dateGridStr = "270,2W";
516 QuantLib::ext::shared_ptr<DateGrid> d = QuantLib::ext::make_shared<DateGrid>(dateGridStr);
517
518 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
519
520 // Init Market
521 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<testsuite::TestMarket>(today);
522
523 data->model("EuropeanSwaption") = "BlackBachelier";
524 data->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
525 data->model("Swap") = "DiscountedCashflows";
526 data->engine("Swap") = "DiscountingSwapEngine";
527 data->model("FxOption") = "GarmanKohlhagen";
528 data->engine("FxOption") = "AnalyticEuropeanEngine";
529
530 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(data, initMarket);
531
532 QuantLib::ext::shared_ptr<Portfolio> portfolio = buildPortfolio(portfolioSize, factory);
533
534 Size samples = 10;
535 JaggedCube<double> jaggedCube(today, portfolio, d->dates(), samples, depth);
536 testCube(jaggedCube, "DoublePrecisionJaggedCube", 1e-5, portfolio, d);
537 IndexManager::instance().clearHistories();
538}
+ Here is the call graph for this function: