Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
bond.cpp File Reference
#include <boost/make_shared.hpp>
#include <boost/test/unit_test.hpp>
#include <ored/marketdata/marketimpl.hpp>
#include <ored/portfolio/bond.hpp>
#include <ored/portfolio/builders/bond.hpp>
#include <ored/portfolio/enginedata.hpp>
#include <ored/portfolio/envelope.hpp>
#include <ored/portfolio/legdata.hpp>
#include <ored/portfolio/schedule.hpp>
#include <ored/utilities/indexparser.hpp>
#include <oret/toplevelfixture.hpp>
#include <ql/termstructures/credit/flathazardrate.hpp>
#include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/time/daycounters/actualactual.hpp>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testZeroBond)
 
 BOOST_AUTO_TEST_CASE (testAmortizingBond)
 
 BOOST_AUTO_TEST_CASE (testAmortizingBondWithChangingAmortisation)
 
 BOOST_AUTO_TEST_CASE (testMultiPhaseBond)
 
 BOOST_AUTO_TEST_CASE (testBondZeroSpreadDefault)
 
 BOOST_AUTO_TEST_CASE (testBondCompareDefault)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/6]

BOOST_AUTO_TEST_CASE ( testZeroBond  )

Definition at line 288 of file bond.cpp.

288 {
289 BOOST_TEST_MESSAGE("Testing Zero Bond...");
290
291 // build market
292 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>();
293 Settings::instance().evaluationDate() = market->asofDate();
294
295 CommonVars vars;
296 QuantLib::ext::shared_ptr<ore::data::Bond> bond = vars.makeZeroBond();
297
298 // Build and price
299 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
300 engineData->model("Bond") = "DiscountedCashflows";
301 engineData->engine("Bond") = "DiscountingRiskyBondEngine";
302
303 map<string, string> engineparams;
304 engineparams["TimestepPeriod"] = "6M";
305 engineData->engineParameters("Bond") = engineparams;
306
307 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
308
309 bond->build(engineFactory);
310
311 Real npv = bond->instrument()->NPV();
312 Real expectedNpv = 9048374.18;
313
314 BOOST_CHECK_CLOSE(npv, expectedNpv, 1.0);
315}

◆ BOOST_AUTO_TEST_CASE() [2/6]

BOOST_AUTO_TEST_CASE ( testAmortizingBond  )

Definition at line 317 of file bond.cpp.

317 {
318 BOOST_TEST_MESSAGE("Testing Amortising Bonds...");
319
320 // build market
321 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>();
322 Date today = Date(30, Jan, 2021);
323 Settings::instance().evaluationDate() = today; // market->asofDate();
324
325 CommonVars vars;
326 vector<QuantLib::ext::shared_ptr<ore::data::Bond>> bonds;
327 QuantLib::ext::shared_ptr<ore::data::Bond> bondFixedAmount = vars.makeAmortizingFixedBond("FixedAmount", 2500000, true);
328 bonds.push_back(bondFixedAmount);
329
330 QuantLib::ext::shared_ptr<ore::data::Bond> bondRelativeInitial =
331 vars.makeAmortizingFixedBond("RelativeToInitialNotional", 0.25, true);
332 bonds.push_back(bondRelativeInitial);
333
334 // Build and price
335 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
336 engineData->model("Bond") = "DiscountedCashflows";
337 engineData->engine("Bond") = "DiscountingRiskyBondEngine";
338
339 map<string, string> engineparams;
340 engineparams["TimestepPeriod"] = "6M";
341 engineData->engineParameters("Bond") = engineparams;
342
343 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
344
345 Real npvTol = 0.5;
346
347 for (auto& b : bonds) {
348 b->build(engineFactory);
349
350 // output schedule
351 printBondSchedule(b);
352
353 Real npv = b->instrument()->NPV();
354 Real expectedNpv = 0.0;
355
356 BOOST_CHECK(std::fabs(npv - expectedNpv) < npvTol);
357 }
358
359 QuantLib::ext::shared_ptr<ore::data::Bond> bondRelativePrevious =
360 vars.makeAmortizingFixedBond("RelativeToPreviousNotional", 0.25, true);
361 bondRelativePrevious->build(engineFactory);
362 printBondSchedule(bondRelativePrevious);
363
364 QuantLib::ext::shared_ptr<QuantLib::Instrument> inst1 = bondRelativePrevious->instrument()->qlInstrument();
365 QuantLib::ext::shared_ptr<QuantLib::Bond> qlBond1 = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(inst1);
366 Real expectedNotional = 3164062.5;
367
368 Real notional = qlBond1->notionals()[qlBond1->notionals().size() - 2];
369
370 BOOST_CHECK_CLOSE(notional, expectedNotional, 1);
371
372 QuantLib::ext::shared_ptr<ore::data::Bond> bondFixedAnnuity = vars.makeAmortizingFixedBond("Annuity", 2500000, true);
373 bondFixedAnnuity->build(engineFactory);
374 printBondSchedule(bondFixedAnnuity);
375
376 QuantLib::ext::shared_ptr<QuantLib::Instrument> inst2 = bondFixedAnnuity->instrument()->qlInstrument();
377 QuantLib::ext::shared_ptr<QuantLib::Bond> qlBond2 = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(inst2);
378 expectedNotional = 1380908.447;
379
380 notional = qlBond2->notionals()[qlBond2->notionals().size() - 2];
381
382 BOOST_CHECK(std::fabs(notional - expectedNotional) < npvTol);
383
384 QuantLib::ext::shared_ptr<ore::data::Bond> bondFloatingAnnuity = vars.makeAmortizingFloatingBond("Annuity", 2500000, true);
385 bondFloatingAnnuity->build(engineFactory);
386 printBondSchedule(bondFloatingAnnuity);
387
388 QuantLib::ext::shared_ptr<QuantLib::Instrument> inst3 = bondFloatingAnnuity->instrument()->qlInstrument();
389 QuantLib::ext::shared_ptr<QuantLib::Bond> qlBond3 = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(inst3);
390 Real expectedAmount = 93.41;
391
392 Real amount = qlBond3->cashflows()[qlBond3->cashflows().size() - 2]->amount();
393
394 BOOST_CHECK(std::fabs(amount - expectedAmount) < npvTol);
395}

◆ BOOST_AUTO_TEST_CASE() [3/6]

BOOST_AUTO_TEST_CASE ( testAmortizingBondWithChangingAmortisation  )

Definition at line 397 of file bond.cpp.

397 {
398 BOOST_TEST_MESSAGE("Testing Amortising Bonds with changing amortisation...");
399
400 // build market
401 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>();
402 Date today = Date(30, Jan, 2021);
403 Settings::instance().evaluationDate() = today; // market->asofDate();
404
405 // build engine factory
406 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
407 engineData->model("Bond") = "DiscountedCashflows";
408 engineData->engine("Bond") = "DiscountingRiskyBondEngine";
409 map<string, string> engineparams;
410 engineparams["TimestepPeriod"] = "6M";
411 engineData->engineParameters("Bond") = engineparams;
412 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
413
414 // test different amortization combinations
415 CommonVars vars;
416
417 // fixed rate bond test cases
418 QuantLib::ext::shared_ptr<ore::data::Bond> bond1 = vars.makeAmortizingFixedBondWithChangingAmortisation(
419 "FixedAmount", 2500000, true, "05-02-2018", "FixedAmount", 1250000, true);
420 bond1->build(engineFactory);
421 printBondSchedule(bond1);
422 checkNominalSchedule(bond1, {1.0E7, 7.5E6, 6.25E6, 5.0E6, 3.75E6});
423
424 QuantLib::ext::shared_ptr<ore::data::Bond> bond2 = vars.makeAmortizingFixedBondWithChangingAmortisation(
425 "FixedAmount", 2500000, true, "05-02-2018", "RelativeToInitialNotional", 0.1, true);
426 bond2->build(engineFactory);
427 printBondSchedule(bond2);
428 checkNominalSchedule(bond2, {1.0E7, 7.5E6, 6.5E6, 5.5E6, 4.5E6});
429
430 QuantLib::ext::shared_ptr<ore::data::Bond> bond3 = vars.makeAmortizingFixedBondWithChangingAmortisation(
431 "RelativeToPreviousNotional", 0.1, true, "05-02-2018", "Annuity", 1E6, true);
432 bond3->build(engineFactory);
433 printBondSchedule(bond3);
434 checkNominalSchedule(bond3, {1.0E7, 9.0E6, 8.45247E6, 7.87393E6, 7.26645E6});
435
436 QuantLib::ext::shared_ptr<ore::data::Bond> bond4 = vars.makeAmortizingFixedBondWithChangingAmortisation(
437 "Annuity", 1E6, true, "05-02-2018", "RelativeToPreviousNotional", 0.1, true);
438 bond4->build(engineFactory);
439 printBondSchedule(bond4);
440 checkNominalSchedule(bond4, {1.0E7, 9.50012E6, 8.55011E6, 7.6951E6, 6.92559E6});
441
442 // floating rate bond test cases
443 QuantLib::ext::shared_ptr<ore::data::Bond> bond5 = vars.makeAmortizingFloatingBondWithChangingAmortisation(
444 "FixedAmount", 2500000, true, "05-02-2018", "FixedAmount", 1250000, true);
445 bond5->build(engineFactory);
446 printBondSchedule(bond5);
447 checkNominalSchedule(bond5, {1.0E7, 7.5E6, 6.25E6, 5.0E6, 3.75E6});
448
449 QuantLib::ext::shared_ptr<ore::data::Bond> bond6 = vars.makeAmortizingFloatingBondWithChangingAmortisation(
450 "FixedAmount", 2500000, true, "05-02-2018", "RelativeToInitialNotional", 0.1, true);
451 bond6->build(engineFactory);
452 printBondSchedule(bond6);
453 checkNominalSchedule(bond6, {1.0E7, 7.5E6, 6.5E6, 5.5E6, 4.5E6});
454
455 // annuity only allowed in single block setup
456 QuantLib::ext::shared_ptr<ore::data::Bond> bond7 = vars.makeAmortizingFloatingBondWithChangingAmortisation(
457 "RelativeToPreviousNotional", 0.1, true, "05-02-2018", "Annuity", 1E6, true);
458 BOOST_CHECK_THROW(bond7->build(engineFactory), QuantLib::Error);
459}

◆ BOOST_AUTO_TEST_CASE() [4/6]

BOOST_AUTO_TEST_CASE ( testMultiPhaseBond  )

Definition at line 461 of file bond.cpp.

461 {
462 // build market
463 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>();
464 Date today = Date(30, Jan, 2021);
465 Settings::instance().evaluationDate() = today; // market->asofDate();
466
467 // build engine factory
468 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
469 engineData->model("Bond") = "DiscountedCashflows";
470 engineData->engine("Bond") = "DiscountingRiskyBondEngine";
471 map<string, string> engineparams;
472 engineparams["TimestepPeriod"] = "6M";
473 engineData->engineParameters("Bond") = engineparams;
474 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
475
476 // test multi phase bond
477 CommonVars vars;
478 ScheduleData schedule1(ScheduleRules("05-02-2016", "05-02-2018", "1Y", "TARGET", "F", "F", "Forward"));
479 ScheduleData schedule2(ScheduleRules("05-02-2018", "05-02-2020", "6M", "TARGET", "F", "F", "Forward"));
480 auto fixedLegRateData = QuantLib::ext::make_shared<FixedLegData>(vector<double>(1, 0.01));
481 LegData legdata1(fixedLegRateData, vars.isPayer, vars.ccy, schedule1, vars.fixDC, vars.notionals);
482 LegData legdata2(fixedLegRateData, vars.isPayer, vars.ccy, schedule2, vars.fixDC, vars.notionals);
483 Envelope env("CP1");
484 QuantLib::ext::shared_ptr<ore::data::Bond> bond(
485 new ore::data::Bond(env, BondData(vars.issuerId, vars.creditCurveId, vars.securityId, vars.referenceCurveId,
486 vars.settledays, vars.calStr, vars.issue, {legdata1, legdata2})));
487 bond->build(engineFactory);
488 printBondSchedule(bond);
489 auto qlInstr = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(bond->instrument()->qlInstrument());
490 BOOST_REQUIRE(qlInstr != nullptr);
491 // annually
492 BOOST_REQUIRE_EQUAL(qlInstr->cashflows().size(), 7);
493 BOOST_CHECK_EQUAL(qlInstr->cashflows()[0]->date(), Date(6, Feb, 2017));
494 BOOST_CHECK_EQUAL(qlInstr->cashflows()[1]->date(), Date(5, Feb, 2018));
495 // semi annually
496 BOOST_CHECK_EQUAL(qlInstr->cashflows()[2]->date(), Date(6, Aug, 2018));
497 BOOST_CHECK_EQUAL(qlInstr->cashflows()[3]->date(), Date(5, Feb, 2019));
498 BOOST_CHECK_EQUAL(qlInstr->cashflows()[4]->date(), Date(5, Aug, 2019));
499 BOOST_CHECK_EQUAL(qlInstr->cashflows()[5]->date(), Date(5, Feb, 2020));
500 BOOST_CHECK_EQUAL(qlInstr->cashflows()[6]->date(), Date(5, Feb, 2020));
501}
Serializable Bond.
Definition: bond.hpp:153
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
Serializable object holding leg data.
Definition: legdata.hpp:844
Serializable schedule data.
Definition: schedule.hpp:202
Serializable object holding schedule Rules data.
Definition: schedule.hpp:37

◆ BOOST_AUTO_TEST_CASE() [5/6]

BOOST_AUTO_TEST_CASE ( testBondZeroSpreadDefault  )

Definition at line 503 of file bond.cpp.

503 {
504 BOOST_TEST_MESSAGE("Testing Bond price...");
505
506 // build market
507 QuantLib::ext::shared_ptr<Market> market = QuantLib::ext::make_shared<TestMarket>();
508 Settings::instance().evaluationDate() = market->asofDate();
509
510 CommonVars vars;
511 QuantLib::ext::shared_ptr<ore::data::Bond> bond = vars.makeBond();
512
513 // Build and price
514 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
515 engineData->model("Bond") = "DiscountedCashflows";
516 engineData->engine("Bond") = "DiscountingRiskyBondEngine";
517
518 map<string, string> engineparams;
519 engineparams["TimestepPeriod"] = "6M";
520 engineData->engineParameters("Bond") = engineparams;
521
522 QuantLib::ext::shared_ptr<EngineFactory> engineFactory = QuantLib::ext::make_shared<EngineFactory>(engineData, market);
523
524 bond->build(engineFactory);
525
526 Real npv = bond->instrument()->NPV();
527 Real expectedNpv = 11403727.39;
528
529 BOOST_CHECK_CLOSE(npv, expectedNpv, 1.0);
530}

◆ BOOST_AUTO_TEST_CASE() [6/6]

BOOST_AUTO_TEST_CASE ( testBondCompareDefault  )

Definition at line 532 of file bond.cpp.

532 {
533 BOOST_TEST_MESSAGE("Testing Bond price...");
534
535 // build market
536 QuantLib::ext::shared_ptr<Market> market1 = QuantLib::ext::make_shared<TestMarket>(0.0);
537 QuantLib::ext::shared_ptr<Market> market2 = QuantLib::ext::make_shared<TestMarket>(0.5);
538 QuantLib::ext::shared_ptr<Market> market3 = QuantLib::ext::make_shared<TestMarket>(0.99);
539 Settings::instance().evaluationDate() = market1->asofDate();
540
541 CommonVars vars;
542 QuantLib::ext::shared_ptr<ore::data::Bond> bond = vars.makeBond();
543
544 // Build and price
545 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
546 engineData->model("Bond") = "DiscountedCashflows";
547 engineData->engine("Bond") = "DiscountingRiskyBondEngine";
548 map<string, string> engineparams;
549 engineparams["TimestepPeriod"] = "6M";
550 engineData->engineParameters("Bond") = engineparams;
551
552 QuantLib::ext::shared_ptr<EngineFactory> engineFactory1 = QuantLib::ext::make_shared<EngineFactory>(engineData, market1);
553 QuantLib::ext::shared_ptr<EngineFactory> engineFactory2 = QuantLib::ext::make_shared<EngineFactory>(engineData, market2);
554 QuantLib::ext::shared_ptr<EngineFactory> engineFactory3 = QuantLib::ext::make_shared<EngineFactory>(engineData, market3);
555
556 bond->build(engineFactory1);
557 Real npv1 = bond->instrument()->NPV();
558 bond->build(engineFactory2);
559 Real npv2 = bond->instrument()->NPV();
560 bond->build(engineFactory3);
561 Real npv3 = bond->instrument()->NPV();
562
563 BOOST_CHECK((npv1 > npv2) && (npv2 > npv3));
564
565 // BOOST_CHECK_CLOSE(npv, expectedNpv, 1.0);
566}