20#include <boost/test/unit_test.hpp>
21#include <ql/cashflows/fixedratecoupon.hpp>
22#include <ql/quotes/simplequote.hpp>
23#include <ql/termstructures/credit/flathazardrate.hpp>
24#include <ql/termstructures/yield/flatforward.hpp>
25#include <ql/time/calendars/weekendsonly.hpp>
26#include <ql/time/schedule.hpp>
30#include <boost/make_shared.hpp>
32using namespace boost::unit_test_framework;
37BOOST_AUTO_TEST_SUITE(BondsTest)
41 BOOST_TEST_MESSAGE(
"Testing QuantExt bond spread helper");
44 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
45 Date today = Settings::instance().evaluationDate();
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));
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);
67 Real redemption = 100.0;
68 Real couponRate = 0.04;
70 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
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);
78 Real price = bond->dirtyPrice();
79 BOOST_TEST_MESSAGE(
"Bond price = " << 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;
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);
92 Real price2 = bond->dirtyPrice();
93 BOOST_CHECK_EQUAL(price, price2);
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);
101 price, bond->dirtyPrice());
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);
110 dpts = Handle<DefaultProbabilityTermStructure>();
113 bond->setPricingEngine(pricingEngine);
114 Real priceNoIssuerCurve = bond->dirtyPrice();
115 BOOST_TEST_MESSAGE(
"Bond price (ignoring issuer spread) = " << 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);
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);
131BOOST_AUTO_TEST_SUITE_END()
133BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(testBondSpreads)
Discounting Risky Bond Engine.
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)
utilities for implied bond credit spread calculation
Fixture that can be used at top level.