Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
forwardbond.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/forwardbond.hpp>
#include <qle/pricingengines/discountingforwardbondengine.hpp>
#include <qle/pricingengines/discountingriskybondengine.hpp>
#include <boost/make_shared.hpp>
#include <iomanip>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testForwardBond1)
 
 BOOST_AUTO_TEST_CASE (testForwardBond2)
 
 BOOST_AUTO_TEST_CASE (testForwardBond3)
 
 BOOST_AUTO_TEST_CASE (testForwardBond4)
 
 BOOST_AUTO_TEST_CASE (testForwardBond5)
 
 BOOST_AUTO_TEST_CASE (testForwardBond6)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/6]

BOOST_AUTO_TEST_CASE ( testForwardBond1  )

Definition at line 41 of file forwardbond.cpp.

41 { // test if bond and forwardbond comp coincide at maturity
42 BOOST_TEST_MESSAGE("Testing QuantExt Forward Bond pricing. Case 1");
43
44 SavedSettings backup;
45
46 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
47 Date today = Settings::instance().evaluationDate();
48 Settings::instance().includeReferenceDateEvents() = true;
49
50 // bond market data
51 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.02));
52 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
53 DayCounter dc = Actual365Fixed();
54 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Semiannual));
55 Handle<DefaultProbabilityTermStructure> dpts(QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
56 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(0.005));
57
58 // build the underlying fixed rate bond
59 Date startDate = today;
60 Date endDate = startDate + Period(10, Years);
61 Period tenor = 6 * Months;
62 Calendar calendar = WeekendsOnly();
63 BusinessDayConvention bdc = Following;
64 BusinessDayConvention bdcEnd = bdc;
65 DateGeneration::Rule rule = DateGeneration::Forward;
66 bool endOfMonth = false;
67 Date firstDate, lastDate;
68 Schedule schedule(startDate, endDate, tenor, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
69
70 Real redemption = 100.0;
71 Real couponRate = 0.04;
72 bool settlementDirty = true;
73 Real compensationPayment = 0.0;
74 Date compensationPaymentDate = today;
75
76 Leg leg =
77 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
78
79 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, WeekendsOnly(), today, leg));
80 Handle<Quote> recovery;
81 QuantLib::ext::shared_ptr<PricingEngine> pricingEngine(
82 QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, bondSpecificSpread, 1 * Months));
83 bond->setPricingEngine(pricingEngine);
84
85 Real price = bond->NPV();
86 BOOST_TEST_MESSAGE("Bond price = " << price);
87
88 // additional forward bond market data
89 Handle<Quote> discountQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
90 Handle<YieldTermStructure> discountTS(
91 QuantLib::ext::make_shared<FlatForward>(today, discountQuote, dc, Compounded, Semiannual));
92 Handle<Quote> incomeQuote(QuantLib::ext::make_shared<SimpleQuote>(0.005));
93 Handle<YieldTermStructure> incomeTS(
94 QuantLib::ext::make_shared<FlatForward>(today, incomeQuote, dc, Compounded, Semiannual));
95 // Handle<Quote> recoveryRate(QuantLib::ext::make_shared<SimpleQuote>(0.4));
96
97 // build the forward bond
98 // Date valueDate = today;
99 Date fwdMaturityDate = today;
100 Real strikePrice = 103.0;
101 QuantLib::ext::shared_ptr<Payoff> payoff = QuantLib::ext::make_shared<QuantExt::ForwardBondTypePayoff>(Position::Long, strikePrice);
102 // Natural settlementDays = 0; // why do we need this if we specify the value date explicitly ?
103 QuantLib::ext::shared_ptr<QuantExt::ForwardBond> fwdBond(
104 new QuantExt::ForwardBond(bond, payoff, fwdMaturityDate, fwdMaturityDate, true, settlementDirty,
105 compensationPayment, compensationPaymentDate));
106 QuantLib::ext::shared_ptr<PricingEngine> fwdBondEngine(new QuantExt::DiscountingForwardBondEngine(
107 discountTS, incomeTS, yts, bondSpecificSpread, dpts, recovery, 2 * Months));
108 fwdBond->setPricingEngine(fwdBondEngine);
109
110 BOOST_TEST_MESSAGE("Forward Bond price = " << fwdBond->NPV());
111 BOOST_CHECK_CLOSE(fwdBond->NPV() + strikePrice, bond->dirtyPrice(), 0.000001);
112}
Forward Bond class.
Definition: forwardbond.hpp:41

◆ BOOST_AUTO_TEST_CASE() [2/6]

BOOST_AUTO_TEST_CASE ( testForwardBond2  )

Definition at line 114 of file forwardbond.cpp.

114 { // same testcase as above, but different setting of params
115
116 BOOST_TEST_MESSAGE("Testing QuantExt Forward Bond pricing. Case 2");
117
118 SavedSettings backup;
119
120 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
121 Date today = Settings::instance().evaluationDate();
122 Settings::instance().includeReferenceDateEvents() = true;
123
124 // bond market data
125 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.02));
126 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
127 DayCounter dc = Actual365Fixed();
128 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Semiannual));
129 Handle<DefaultProbabilityTermStructure> dpts(QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
130 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(0.005));
131
132 // build the underlying fixed rate bond
133 Date startDate = today;
134 Date endDate = startDate + Period(10, Years);
135 Period tenor = 6 * Months;
136 Calendar calendar = WeekendsOnly();
137 BusinessDayConvention bdc = Following;
138 BusinessDayConvention bdcEnd = bdc;
139 DateGeneration::Rule rule = DateGeneration::Forward;
140 bool endOfMonth = false;
141 Date firstDate, lastDate;
142 Schedule schedule(startDate, endDate, tenor, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
143
144 Real redemption = 95.0;
145 Real couponRate = 0.04;
146 bool settlementDirty = true;
147 Real compensationPayment = 0.0;
148 Date compensationPaymentDate = today;
149 Leg leg =
150 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
151
152 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, WeekendsOnly(), today, leg));
153 Handle<Quote> recovery; /*Handle<Quote> recovery(QuantLib::ext::make_shared<SimpleQuote>(0.4));*/
154 QuantLib::ext::shared_ptr<PricingEngine> pricingEngine(
155 QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, bondSpecificSpread, 2 * Months));
156 bond->setPricingEngine(pricingEngine);
157
158 Real price = bond->NPV();
159 BOOST_TEST_MESSAGE("Bond price = " << price);
160
161 // additional forward bond market data
162 Handle<Quote> discountQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
163 Handle<YieldTermStructure> discountTS(
164 QuantLib::ext::make_shared<FlatForward>(today, discountQuote, dc, Compounded, Semiannual));
165 Handle<Quote> incomeQuote(QuantLib::ext::make_shared<SimpleQuote>(0.005));
166 Handle<YieldTermStructure> incomeTS(
167 QuantLib::ext::make_shared<FlatForward>(today, incomeQuote, dc, Compounded, Semiannual));
168
169 // build the forward bond
170 // Date valueDate = today;
171 Date fwdMaturityDate = today;
172 Real strikePrice = 98.0;
173 QuantLib::ext::shared_ptr<Payoff> payoff = QuantLib::ext::make_shared<QuantExt::ForwardBondTypePayoff>(Position::Long, strikePrice);
174 // Natural settlementDays = 0; // why do we need this if we specify the value date explicitly ?
175
176 QuantLib::ext::shared_ptr<QuantExt::ForwardBond> fwdBond(
177 new QuantExt::ForwardBond(bond, payoff, fwdMaturityDate, fwdMaturityDate, true, settlementDirty,
178 compensationPayment, compensationPaymentDate));
179
180 QuantLib::ext::shared_ptr<PricingEngine> fwdBondEngine(new QuantExt::DiscountingForwardBondEngine(
181 discountTS, incomeTS, yts, bondSpecificSpread, dpts, recovery, 2 * Months));
182 fwdBond->setPricingEngine(fwdBondEngine);
183
184 BOOST_TEST_MESSAGE("Forward Bond price = " << fwdBond->NPV());
185 BOOST_CHECK_CLOSE(fwdBond->NPV() + strikePrice, bond->NPV(), 0.000001);
186}

◆ BOOST_AUTO_TEST_CASE() [3/6]

BOOST_AUTO_TEST_CASE ( testForwardBond3  )

Definition at line 188 of file forwardbond.cpp.

188 { // now true forward bond, but coupon payments are excluded
189
190 BOOST_TEST_MESSAGE("Testing QuantExt Forward Bond pricing. Case 3");
191
192 SavedSettings backup;
193
194 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
195 Date today = Settings::instance().evaluationDate();
196 Settings::instance().includeReferenceDateEvents() = true;
197
198 // bond market data
199 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.02));
200 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.0));
201 DayCounter dc = Actual365Fixed();
202 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Semiannual));
203 Handle<DefaultProbabilityTermStructure> dpts(QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
204 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(0.005));
205
206 // build the underlying fixed rate bond
207 Date startDate = today;
208 Date endDate = startDate + Period(10, Years);
209 Period tenor = 6 * Months;
210 Calendar calendar = WeekendsOnly();
211 BusinessDayConvention bdc = Following;
212 BusinessDayConvention bdcEnd = bdc;
213 DateGeneration::Rule rule = DateGeneration::Forward;
214 bool endOfMonth = false;
215 Date firstDate, lastDate;
216 Schedule schedule(startDate, endDate, tenor, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
217
218 Real redemption = 100.0;
219 Real couponRate = 0.04;
220 bool settlementDirty = true;
221 Real compensationPayment = 0.0;
222 Date compensationPaymentDate = today;
223 Leg leg =
224 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
225
226 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, WeekendsOnly(), today, leg));
227 Handle<Quote> recovery(QuantLib::ext::make_shared<SimpleQuote>(0.0));
228 QuantLib::ext::shared_ptr<PricingEngine> pricingEngine(
229 QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, bondSpecificSpread, 2 * Months));
230 bond->setPricingEngine(pricingEngine);
231
232 Real price = bond->NPV();
233 BOOST_TEST_MESSAGE("Bond price = " << price);
234
235 // additional forward bond market data
236 Handle<Quote> discountQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
237 Handle<YieldTermStructure> discountTS(
238 QuantLib::ext::make_shared<FlatForward>(today, discountQuote, dc, Compounded, Semiannual));
239 Handle<Quote> incomeQuote(QuantLib::ext::make_shared<SimpleQuote>(0.005));
240 Handle<YieldTermStructure> incomeTS(
241 QuantLib::ext::make_shared<FlatForward>(today, incomeQuote, dc, Compounded, Semiannual));
242
243 // build the forward bond
244 // Date valueDate = today;
245 Date fwdMaturityDate = today + 2 * Months; // there are no cfs in these two months.
246 Real strikePrice = 98.0;
247 QuantLib::ext::shared_ptr<Payoff> payoff = QuantLib::ext::make_shared<QuantExt::ForwardBondTypePayoff>(Position::Long, strikePrice);
248 // Natural settlementDays = 0; // why do we need this if we specify the value date explicitly ?
249
250 QuantLib::ext::shared_ptr<QuantExt::ForwardBond> fwdBond(
251 new QuantExt::ForwardBond(bond, payoff, fwdMaturityDate, fwdMaturityDate, true, settlementDirty,
252 compensationPayment, compensationPaymentDate));
253
254 QuantLib::ext::shared_ptr<PricingEngine> fwdBondEngine(new QuantExt::DiscountingForwardBondEngine(
255 discountTS, incomeTS, yts, bondSpecificSpread, dpts, recovery, 2 * Months));
256 fwdBond->setPricingEngine(fwdBondEngine);
257
258 BOOST_TEST_MESSAGE("Forward Bond price = " << fwdBond->NPV());
259 BOOST_CHECK_CLOSE((fwdBond->NPV() / (discountTS->discount(fwdMaturityDate)) + strikePrice) *
260 (incomeTS->discount(fwdMaturityDate)),
261 bond->NPV(), 0.000001); // no differnce in cfs. only check compounding factors
262}

◆ BOOST_AUTO_TEST_CASE() [4/6]

BOOST_AUTO_TEST_CASE ( testForwardBond4  )

Definition at line 264 of file forwardbond.cpp.

264 { // now true forward bond, one coupon before maturity
265
266 BOOST_TEST_MESSAGE("Testing QuantExt Forward Bond pricing. Case 4");
267
268 SavedSettings backup;
269
270 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
271 Date today = Settings::instance().evaluationDate();
272 Settings::instance().includeReferenceDateEvents() = true;
273
274 // bond market data
275 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.02));
276 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.00));
277 DayCounter dc = Actual365Fixed();
278 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Semiannual));
279 Handle<DefaultProbabilityTermStructure> dpts(QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
280 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(0.000));
281
282 // build the underlying fixed rate bond
283 Date startDate = today;
284 Date endDate = startDate + Period(10, Years);
285 Period tenor = 6 * Months;
286 Calendar calendar = WeekendsOnly();
287 BusinessDayConvention bdc = Following;
288 BusinessDayConvention bdcEnd = bdc;
289 DateGeneration::Rule rule = DateGeneration::Forward;
290 bool endOfMonth = false;
291 Date firstDate, lastDate;
292 Schedule schedule(startDate, endDate, tenor, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
293
294 Real redemption = 100.0;
295 Real couponRate = 0.04;
296 bool settlementDirty = true;
297 Real compensationPayment = 0.0;
298 Date compensationPaymentDate = today;
299 Leg leg =
300 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
301
302 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, WeekendsOnly(), today, leg));
303 Handle<Quote> recovery(QuantLib::ext::make_shared<SimpleQuote>(0.0));
304 QuantLib::ext::shared_ptr<PricingEngine> pricingEngine(
305 QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, bondSpecificSpread, 2 * Months));
306 bond->setPricingEngine(pricingEngine);
307
308 Real price = bond->NPV();
309 BOOST_TEST_MESSAGE("Bond price = " << std::setprecision(12) << price);
310
311 // additional forward bond market data
312 Handle<Quote> discountQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
313 Handle<YieldTermStructure> discountTS(
314 QuantLib::ext::make_shared<FlatForward>(today, discountQuote, dc, Compounded, Semiannual));
315 Handle<Quote> incomeQuote(QuantLib::ext::make_shared<SimpleQuote>(0.005));
316 Handle<YieldTermStructure> incomeTS(
317 QuantLib::ext::make_shared<FlatForward>(today, incomeQuote, dc, Compounded, Semiannual));
318
319 // build the forward bond
320 // Date valueDate = today;
321 Date fwdMaturityDate = today + 7 * Months + 7 * Days; // there is one CF in those two months. today+7*Months happens
322 // to be a saturday, thus two days are added.
323
324 Real strikePrice = 98.0;
325 QuantLib::ext::shared_ptr<Payoff> payoff = QuantLib::ext::make_shared<QuantExt::ForwardBondTypePayoff>(Position::Long, strikePrice);
326 // Natural settlementDays = 0; // why do we need this if we specify the value date explicitly ?
327
328 QuantLib::ext::shared_ptr<QuantExt::ForwardBond> fwdBond(
329 new QuantExt::ForwardBond(bond, payoff, fwdMaturityDate, fwdMaturityDate, true, settlementDirty,
330 compensationPayment, compensationPaymentDate));
331
332 QuantLib::ext::shared_ptr<PricingEngine> fwdBondEngine(new QuantExt::DiscountingForwardBondEngine(
333 discountTS, incomeTS, yts, bondSpecificSpread, dpts, recovery, 2 * Months));
334 fwdBond->setPricingEngine(fwdBondEngine);
335
336 BOOST_TEST_MESSAGE("Forward Bond price = " << std::setprecision(12) << fwdBond->NPV());
337 BOOST_CHECK_CLOSE((fwdBond->NPV() / (discountTS->discount(fwdMaturityDate)) + strikePrice) *
338 (incomeTS->discount(fwdMaturityDate)),
339 bond->NPV() - (0.04 * 100.0 * 182 / 365 * (yts->discount(Date(8, Jun, 2017))) *
340 (dpts->survivalProbability(Date(8, Jun, 2017)))),
341 0.000001); // one cf before maturity factors; the cf occurs at today+6*Months
342 BOOST_TEST_MESSAGE("Present discount factors:");
343
344 BOOST_TEST_MESSAGE("ytsDiscountFactors = " << std::setprecision(12) << yts->discount(Date(8, Jun, 2017)));
345 BOOST_TEST_MESSAGE("ytsDiscountFactors = " << std::setprecision(12)
346 << yts->discount(Date(8, Jun, 2017) + 1 * Days));
347 BOOST_TEST_MESSAGE("ytsDiscountFactors = " << std::setprecision(12)
348 << yts->discount(Date(8, Jun, 2017) + 5 * Days));
349
350 BOOST_TEST_MESSAGE("incDiscountFactors = " << std::setprecision(12) << incomeTS->discount(Date(8, Jun, 2017)));
351 BOOST_TEST_MESSAGE("incDiscountFactors = " << std::setprecision(12)
352 << incomeTS->discount(Date(8, Jun, 2017) + 1 * Days));
353 BOOST_TEST_MESSAGE("incDiscountFactors = " << std::setprecision(12)
354 << incomeTS->discount(Date(8, Jun, 2017) + 5 * Days));
355
356 BOOST_TEST_MESSAGE("disDiscountFactors = " << std::setprecision(12) << discountTS->discount(Date(8, Jun, 2017)));
357 BOOST_TEST_MESSAGE("disDiscountFactors = " << std::setprecision(12)
358 << discountTS->discount(Date(8, Jun, 2017) + 1 * Days));
359 BOOST_TEST_MESSAGE("disDiscountFactors = " << std::setprecision(12)
360 << discountTS->discount(Date(8, Jun, 2017) + 5 * Days));
361}

◆ BOOST_AUTO_TEST_CASE() [5/6]

BOOST_AUTO_TEST_CASE ( testForwardBond5  )

Definition at line 363 of file forwardbond.cpp.

363 { // now true forward bond, one coupon before maturity
364
365 BOOST_TEST_MESSAGE("Testing QuantExt Forward Bond pricing. Case 5");
366
367 SavedSettings backup;
368
369 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
370 Date today = Settings::instance().evaluationDate();
371 Settings::instance().includeReferenceDateEvents() = true;
372
373 // bond market data
374 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.02));
375 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.00));
376 DayCounter dc = Actual365Fixed();
377 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Semiannual));
378 Handle<DefaultProbabilityTermStructure> dpts(QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
379 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(0.000));
380
381 // build the underlying fixed rate bond
382 Date startDate = today;
383 Date endDate = startDate + Period(10, Years);
384 Period tenor = 6 * Months;
385 Calendar calendar = WeekendsOnly();
386 BusinessDayConvention bdc = Following;
387 BusinessDayConvention bdcEnd = bdc;
388 DateGeneration::Rule rule = DateGeneration::Forward;
389 bool endOfMonth = false;
390 Date firstDate, lastDate;
391 Schedule schedule(startDate, endDate, tenor, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
392
393 Real redemption = 100.0;
394 Real couponRate = 0.04;
395 bool settlementDirty = true;
396 Real compensationPayment = 5.0;
397 Date compensationPaymentDate = today + 2 * Days;
398 Leg leg =
399 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
400
401 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, WeekendsOnly(), today, leg));
402 Handle<Quote> recovery(QuantLib::ext::make_shared<SimpleQuote>(0.0));
403 QuantLib::ext::shared_ptr<PricingEngine> pricingEngine(
404 QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, bondSpecificSpread, 2 * Months));
405 bond->setPricingEngine(pricingEngine);
406
407 Real price = bond->NPV();
408 BOOST_TEST_MESSAGE("Bond price = " << std::setprecision(12) << price);
409
410 // additional forward bond market data
411 Handle<Quote> discountQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
412 Handle<YieldTermStructure> discountTS(
413 QuantLib::ext::make_shared<FlatForward>(today, discountQuote, dc, Compounded, Semiannual));
414 Handle<Quote> incomeQuote(QuantLib::ext::make_shared<SimpleQuote>(0.005));
415 Handle<YieldTermStructure> incomeTS(
416 QuantLib::ext::make_shared<FlatForward>(today, incomeQuote, dc, Compounded, Semiannual));
417
418 // build the forward bond
419 // Date valueDate = today;
420 Date fwdMaturityDate = today + 7 * Months + 7 * Days; // there is one CF in those two months. today+7*Months happens
421 // to be a saturday, thus two days are added.
422
423 Real strikePrice = 98.0;
424 QuantLib::ext::shared_ptr<Payoff> payoff = QuantLib::ext::make_shared<QuantExt::ForwardBondTypePayoff>(Position::Long, strikePrice);
425 // Natural settlementDays = 0; // why do we need this if we specify the value date explicitly ?
426
427 QuantLib::ext::shared_ptr<QuantExt::ForwardBond> fwdBond(
428 new QuantExt::ForwardBond(bond, payoff, fwdMaturityDate, fwdMaturityDate, true, settlementDirty,
429 compensationPayment, compensationPaymentDate));
430
431 QuantLib::ext::shared_ptr<PricingEngine> fwdBondEngine(new QuantExt::DiscountingForwardBondEngine(
432 discountTS, incomeTS, yts, bondSpecificSpread, dpts, recovery, 2 * Months));
433 fwdBond->setPricingEngine(fwdBondEngine);
434
435 BOOST_TEST_MESSAGE("Forward Bond price = " << std::setprecision(12) << fwdBond->NPV());
436 BOOST_CHECK_CLOSE(((fwdBond->NPV() + compensationPayment * discountTS->discount(compensationPaymentDate)) /
437 (discountTS->discount(fwdMaturityDate)) +
438 strikePrice) *
439 (incomeTS->discount(fwdMaturityDate)),
440 bond->NPV() - (0.04 * 100.0 * 182 / 365 * (yts->discount(Date(8, Jun, 2017))) *
441 (dpts->survivalProbability(Date(8, Jun, 2017)))),
442 0.000001); // one cf before maturity factors; the cf occurs at today+6*Months
443}

◆ BOOST_AUTO_TEST_CASE() [6/6]

BOOST_AUTO_TEST_CASE ( testForwardBond6  )

Definition at line 445 of file forwardbond.cpp.

445 { // now true forward bond, but coupon payments are excluded
446
447 BOOST_TEST_MESSAGE("Testing QuantExt Forward Bond pricing: Clean vs dirty Strike. Case 6");
448 BOOST_TEST_MESSAGE("This is like case 3 but with clean strike. Check long/short in particular.");
449
450 SavedSettings backup;
451
452 Settings::instance().evaluationDate() = Date(8, Dec, 2016);
453 Date today = Settings::instance().evaluationDate();
454 Settings::instance().includeReferenceDateEvents() = true;
455
456 // bond market data
457 Handle<Quote> rateQuote(QuantLib::ext::make_shared<SimpleQuote>(0.02));
458 Handle<Quote> issuerSpreadQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
459 DayCounter dc = Actual365Fixed();
460 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(today, rateQuote, dc, Compounded, Semiannual));
461 Handle<DefaultProbabilityTermStructure> dpts(QuantLib::ext::make_shared<FlatHazardRate>(today, issuerSpreadQuote, dc));
462 Handle<Quote> bondSpecificSpread(QuantLib::ext::make_shared<SimpleQuote>(0.005));
463
464 // build the underlying fixed rate bond
465 Date startDate = today;
466 Date endDate = startDate + Period(10, Years);
467 Period tenor = 6 * Months;
468 Calendar calendar = WeekendsOnly();
469 BusinessDayConvention bdc = Following;
470 BusinessDayConvention bdcEnd = bdc;
471 DateGeneration::Rule rule = DateGeneration::Forward;
472 bool endOfMonth = false;
473 Date firstDate, lastDate;
474 Schedule schedule(startDate, endDate, tenor, calendar, bdc, bdcEnd, rule, endOfMonth, firstDate, lastDate);
475
476 Real redemption = 100.0;
477 Real couponRate = 0.04;
478 bool settlementDirty = false;
479 Real compensationPayment = 0.0;
480 Date compensationPaymentDate = today;
481 Leg leg =
482 FixedRateLeg(schedule).withNotionals(redemption).withCouponRates(couponRate, dc).withPaymentAdjustment(bdc);
483
484 QuantLib::ext::shared_ptr<QuantLib::Bond> bond(QuantLib::ext::make_shared<QuantLib::Bond>(0, WeekendsOnly(), today, leg));
485 Handle<Quote> recovery(QuantLib::ext::make_shared<SimpleQuote>(0.0));
486 QuantLib::ext::shared_ptr<PricingEngine> pricingEngine(
487 QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, bondSpecificSpread, 2 * Months));
488 bond->setPricingEngine(pricingEngine);
489
490 Real price = bond->NPV();
491 BOOST_TEST_MESSAGE("Bond price = " << price);
492
493 // additional forward bond market data
494 Handle<Quote> discountQuote(QuantLib::ext::make_shared<SimpleQuote>(0.01));
495 Handle<YieldTermStructure> discountTS(
496 QuantLib::ext::make_shared<FlatForward>(today, discountQuote, dc, Compounded, Semiannual));
497 Handle<Quote> incomeQuote(QuantLib::ext::make_shared<SimpleQuote>(0.005));
498 Handle<YieldTermStructure> incomeTS(
499 QuantLib::ext::make_shared<FlatForward>(today, incomeQuote, dc, Compounded, Semiannual));
500
501 // build the forward bond
502 // Date valueDate = today;
503 Date fwdMaturityDate = today + 2 * Months; // there are no cfs in these two months.
504 Real strikePrice = 98.0;
505 QuantLib::ext::shared_ptr<Payoff> payoff = QuantLib::ext::make_shared<QuantExt::ForwardBondTypePayoff>(Position::Long, strikePrice);
506 // Natural settlementDays = 0; // why do we need this if we specify the value date explicitly ?
507
508 QuantLib::ext::shared_ptr<QuantExt::ForwardBond> fwdBond_sh(
509 new QuantExt::ForwardBond(bond, payoff, fwdMaturityDate, fwdMaturityDate, true, settlementDirty,
510 compensationPayment, compensationPaymentDate));
511
512 QuantLib::ext::shared_ptr<PricingEngine> fwdBondEngine_sh(new QuantExt::DiscountingForwardBondEngine(
513 discountTS, incomeTS, yts, bondSpecificSpread, dpts, recovery, 2 * Months));
514 fwdBond_sh->setPricingEngine(fwdBondEngine_sh);
515
516 BOOST_TEST_MESSAGE("Forward Bond price long = " << fwdBond_sh->NPV());
517
518 Real fwdBondNPV = fwdBond_sh->NPV(); // save result of long computation.
519
520 QuantLib::ext::shared_ptr<Payoff> payoff_sh =
521 QuantLib::ext::make_shared<QuantExt::ForwardBondTypePayoff>(Position::Short, strikePrice);
522 // Natural settlementDays = 0; // why do we need this if we specify the value date explicitly ?
523
524 QuantLib::ext::shared_ptr<QuantExt::ForwardBond> fwdBond(
525 new QuantExt::ForwardBond(bond, payoff_sh, fwdMaturityDate, fwdMaturityDate, true, settlementDirty,
526 compensationPayment, compensationPaymentDate));
527
528 QuantLib::ext::shared_ptr<PricingEngine> fwdBondEngine(new QuantExt::DiscountingForwardBondEngine(
529 discountTS, incomeTS, yts, bondSpecificSpread, dpts, recovery, 2 * Months));
530 fwdBond->setPricingEngine(fwdBondEngine);
531
532 BOOST_TEST_MESSAGE("Forward Bond price short = " << fwdBond->NPV());
533
534 BOOST_CHECK_CLOSE(fwdBondNPV, (-1.0) * fwdBond->NPV(), 0.000001);
535}