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
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
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
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;
86
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
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());
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
109
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);
120
121
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}
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)