Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
bonds.cpp File Reference
#include "toplevelfixture.hpp"
#include <boost/test/unit_test.hpp>
#include <ql/cashflows/fixedratecoupon.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/credit/flathazardrate.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/weekendsonly.hpp>
#include <ql/time/schedule.hpp>
#include <qle/instruments/impliedbondspread.hpp>
#include <qle/pricingengines/discountingriskybondengine.hpp>
#include <boost/make_shared.hpp>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testBondSpreads)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE()

BOOST_AUTO_TEST_CASE ( testBondSpreads  )

Definition at line 39 of file bonds.cpp.

39 {
40
41 BOOST_TEST_MESSAGE("Testing QuantExt bond spread helper");
42
43 SavedSettings backup;
44 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
45 Date today = Settings::instance().evaluationDate();
46
47 // market data
48 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.02));
49 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
50 DayCounter dc = Actual365Fixed();
51 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Semiannual));
52 Handle<DefaultProbabilityTermStructure> dpts(QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
53 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(0.005));
54
55 // build the bond
56 Date startDate = today;
57 Date endDate = startDate + Period(10, Years);
58 Period tenor = 6 * Months;
59 Calendar calendar = WeekendsOnly();
60 BusinessDayConvention bdc = Following;
61 BusinessDayConvention bdcEnd = bdc;
62 DateGeneration::Rule rule = DateGeneration::Forward;
63 bool endOfMonth = false;
64 Date firstDate, lastDate;
65 Schedule schedule(startDate, endDate, tenor, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
66
67 Real redemption = 100.0;
68 Real couponRate = 0.04;
69 Leg leg =
70 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
71
72 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, WeekendsOnly(), today, leg));
73 Handle<Quote> recovery;
74 QuantLib::ext::shared_ptr<PricingEngine> pricingEngine(
75 QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, bondSpecificSpread, 1 * Months));
76 bond->setPricingEngine(pricingEngine);
77
78 Real price = bond->dirtyPrice();
79 BOOST_TEST_MESSAGE("Bond price = " << price);
80
81 // now calculated the implied bond spread, given the price
82 QuantLib::ext::shared_ptr<SimpleQuote> tmpSpread = QuantLib::ext::make_shared<SimpleQuote>(0.0);
83 Handle<Quote> tmpSpreadH(tmpSpread);
84 QuantLib::ext::shared_ptr<PricingEngine> tmpEngine;
85 tmpEngine.reset(new QuantExt::DiscountingRiskyBondEngine(yts, dpts, recovery, tmpSpreadH, 1 * Months));
86
87 Real impliedSpread = QuantExt::detail::ImpliedBondSpreadHelper::calculate(bond, tmpEngine, tmpSpread, price, false,
88 1.e-12, 10000, -0.02, 1.00);
89 BOOST_TEST_MESSAGE("Implied spread = " << impliedSpread);
90 BOOST_CHECK_CLOSE(impliedSpread, bondSpecificSpread->value(), 0.0001);
91
92 Real price2 = bond->dirtyPrice();
93 BOOST_CHECK_EQUAL(price, price2);
94
95 // which spread would mean the bond price is par?
96 Real parRedemption = 100.0;
98 bond, tmpEngine, tmpSpread, parRedemption, false, 1.e-12, 10000, -0.02, 1.00);
99 BOOST_TEST_MESSAGE("Par bond price would require spread of " << impliedSpreadPar);
100 BOOST_CHECK_EQUAL(
101 price, bond->dirtyPrice()); // ensure hypothetical impliedSpread calc has not affected the original position
102
103 QuantLib::ext::dynamic_pointer_cast<SimpleQuote>(*bondSpecificSpread)->setValue(impliedSpreadPar);
104 Real pricePar = bond->dirtyPrice();
105 BOOST_TEST_MESSAGE("Bond spread of " << bondSpecificSpread->value() << " means price of " << pricePar);
106 BOOST_CHECK_CLOSE(pricePar, parRedemption, 0.0001);
107
108 // now check that bond pricing works even if no credit curve exists
109
110 dpts = Handle<DefaultProbabilityTermStructure>();
111 pricingEngine.reset(new QuantExt::DiscountingRiskyBondEngine(yts, dpts, recovery, bondSpecificSpread, 1 * Months));
112 tmpEngine.reset(new QuantExt::DiscountingRiskyBondEngine(yts, dpts, recovery, tmpSpreadH, 1 * Months));
113 bond->setPricingEngine(pricingEngine);
114 Real priceNoIssuerCurve = bond->dirtyPrice();
115 BOOST_TEST_MESSAGE("Bond price (ignoring issuer spread) = " << priceNoIssuerCurve);
116 impliedSpread = QuantExt::detail::ImpliedBondSpreadHelper::calculate(bond, tmpEngine, tmpSpread, priceNoIssuerCurve,
117 false, 1.e-12, 10000, -0.02, 1.00);
118 BOOST_TEST_MESSAGE("Bond spread (ignoring issuer spread) = " << impliedSpread);
119 BOOST_CHECK_CLOSE(impliedSpread, bondSpecificSpread->value(), 0.0001);
120
121 // which spread would mean the bond price is par?
122 impliedSpreadPar = QuantExt::detail::ImpliedBondSpreadHelper::calculate(bond, tmpEngine, tmpSpread, parRedemption,
123 false, 1.e-12, 10000, -0.02, 1.00);
124 BOOST_TEST_MESSAGE("Par bond price would require spread of " << impliedSpreadPar);
125 BOOST_CHECK_CLOSE(impliedSpreadPar, bondSpecificSpread->value() + issuerSpreadQuote->value(), 0.0001);
126 QuantLib::ext::dynamic_pointer_cast<SimpleQuote>(*bondSpecificSpread)->setValue(impliedSpreadPar);
127 pricePar = bond->dirtyPrice();
128 BOOST_TEST_MESSAGE("Bond spread of " << bondSpecificSpread->value() << " means price of " << pricePar);
129 BOOST_CHECK_CLOSE(pricePar, parRedemption, 0.0001);
130}
static QuantLib::Real calculate(const QuantLib::ext::shared_ptr< QuantLib::Bond > &bond, const QuantLib::ext::shared_ptr< QuantLib::PricingEngine > &engine, const QuantLib::ext::shared_ptr< QuantLib::SimpleQuote > &spreadQuote, QuantLib::Real targetValue, bool isCleanPrice, QuantLib::Real accuracy, QuantLib::Natural maxEvaluations, QuantLib::Real minSpread, QuantLib::Real maxSpread)
+ Here is the call graph for this function: