1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*!
4 Copyright (C) 2008 Florent Grenier
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18 */
19
20/* This example shows how to set up a term structure and then price
21 some simple bonds. The last part is dedicated to peripherical
22 computations such as "Yield to Price" or "Price to Yield"
23 */
24
25#include <ql/qldefines.hpp>
26#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
27# include <ql/auto_link.hpp>
28#endif
29#include <ql/instruments/bonds/zerocouponbond.hpp>
30#include <ql/instruments/bonds/floatingratebond.hpp>
31#include <ql/pricingengines/bond/discountingbondengine.hpp>
32#include <ql/cashflows/couponpricer.hpp>
33#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
34#include <ql/termstructures/yield/bondhelpers.hpp>
35#include <ql/termstructures/volatility/optionlet/constantoptionletvol.hpp>
36#include <ql/indexes/ibor/euribor.hpp>
37#include <ql/indexes/ibor/usdlibor.hpp>
38#include <ql/time/calendars/target.hpp>
39#include <ql/time/calendars/unitedstates.hpp>
40#include <ql/time/daycounters/actualactual.hpp>
41#include <ql/time/daycounters/actual360.hpp>
42#include <ql/time/daycounters/thirty360.hpp>
43
44#include <iostream>
45#include <iomanip>
46
47using namespace QuantLib;
48
49int main(int, char* []) {
50
51 try {
52
53 std::cout << std::endl;
54
55 /*********************
56 *** MARKET DATA ***
57 *********************/
58
59 Calendar calendar = TARGET();
60
61 Date settlementDate(18, September, 2008);
62 // must be a business day
63 settlementDate = calendar.adjust(settlementDate);
64
65 Integer fixingDays = 3;
66 Natural settlementDays = 3;
67
68 Date todaysDate = calendar.advance(settlementDate, n: -fixingDays, unit: Days);
69 // nothing to do with Date::todaysDate
70 Settings::instance().evaluationDate() = todaysDate;
71
72 std::cout << "Today: " << todaysDate.weekday()
73 << ", " << todaysDate << std::endl;
74
75 std::cout << "Settlement date: " << settlementDate.weekday()
76 << ", " << settlementDate << std::endl;
77
78
79 // Building of the bonds discounting yield curve
80
81 /*********************
82 *** RATE HELPERS ***
83 *********************/
84
85 // RateHelpers are built from the above quotes together with
86 // other instrument dependant infos. Quotes are passed in
87 // relinkable handles which could be relinked to some other
88 // data source later.
89
90 // Common data
91
92 // ZC rates for the short end
93 Rate zc3mQuote=0.0096;
94 Rate zc6mQuote=0.0145;
95 Rate zc1yQuote=0.0194;
96
97 auto zc3mRate = ext::make_shared<SimpleQuote>(args&: zc3mQuote);
98 auto zc6mRate = ext::make_shared<SimpleQuote>(args&: zc6mQuote);
99 auto zc1yRate = ext::make_shared<SimpleQuote>(args&: zc1yQuote);
100
101 DayCounter zcBondsDayCounter = Actual365Fixed();
102
103 auto zc3m = ext::make_shared<DepositRateHelper>(
104 args: Handle<Quote>(zc3mRate),
105 args: 3*Months, args&: fixingDays,
106 args&: calendar, args: ModifiedFollowing,
107 args: true, args&: zcBondsDayCounter);
108 auto zc6m = ext::make_shared<DepositRateHelper>(
109 args: Handle<Quote>(zc6mRate),
110 args: 6*Months, args&: fixingDays,
111 args&: calendar, args: ModifiedFollowing,
112 args: true, args&: zcBondsDayCounter);
113 auto zc1y = ext::make_shared<DepositRateHelper>(
114 args: Handle<Quote>(zc1yRate),
115 args: 1*Years, args&: fixingDays,
116 args&: calendar, args: ModifiedFollowing,
117 args: true, args&: zcBondsDayCounter);
118
119 // setup bonds
120 Real redemption = 100.0;
121
122 const Size numberOfBonds = 5;
123
124 Date issueDates[] = {
125 Date (15, March, 2005),
126 Date (15, June, 2005),
127 Date (30, June, 2006),
128 Date (15, November, 2002),
129 Date (15, May, 1987)
130 };
131
132 Date maturities[] = {
133 Date (31, August, 2010),
134 Date (31, August, 2011),
135 Date (31, August, 2013),
136 Date (15, August, 2018),
137 Date (15, May, 2038)
138 };
139
140 Real couponRates[] = {
141 0.02375,
142 0.04625,
143 0.03125,
144 0.04000,
145 0.04500
146 };
147
148 Real marketQuotes[] = {
149 100.390625,
150 106.21875,
151 100.59375,
152 101.6875,
153 102.140625
154 };
155
156 std::vector<ext::shared_ptr<SimpleQuote>> quote;
157 for (Real marketQuote : marketQuotes) {
158 quote.push_back(x: ext::make_shared<SimpleQuote>(args&: marketQuote));
159 }
160
161 RelinkableHandle<Quote> quoteHandle[numberOfBonds];
162 for (Size i=0; i<numberOfBonds; i++) {
163 quoteHandle[i].linkTo(h: quote[i]);
164 }
165
166 // Definition of the rate helpers
167 std::vector<ext::shared_ptr<BondHelper>> bondsHelpers;
168
169 for (Size i=0; i<numberOfBonds; i++) {
170
171 Schedule schedule(issueDates[i], maturities[i], Period(Semiannual), UnitedStates(UnitedStates::GovernmentBond),
172 Unadjusted, Unadjusted, DateGeneration::Backward, false);
173
174 auto bondHelper = ext::make_shared<FixedRateBondHelper>(
175 args&: quoteHandle[i],
176 args&: settlementDays,
177 args: 100.0,
178 args&: schedule,
179 args: std::vector<Rate>(1,couponRates[i]),
180 args: ActualActual(ActualActual::Bond),
181 args: Unadjusted,
182 args&: redemption,
183 args&: issueDates[i]);
184
185 // the above could also be done by creating a
186 // FixedRateBond instance and writing:
187 //
188 // auto bondHelper = ext::make_shared<BondHelper>(quoteHandle[i], bond);
189 //
190 // This would also work for bonds that still don't have a
191 // specialized helper, such as floating-rate bonds.
192
193
194 bondsHelpers.push_back(x: bondHelper);
195 }
196
197 /*********************
198 ** CURVE BUILDING **
199 *********************/
200
201 // Any DayCounter would be fine.
202 // ActualActual::ISDA ensures that 30 years is 30.0
203 DayCounter termStructureDayCounter =
204 ActualActual(ActualActual::ISDA);
205
206 // A depo-bond curve
207 std::vector<ext::shared_ptr<RateHelper>> bondInstruments;
208
209 // Adding the ZC bonds to the curve for the short end
210 bondInstruments.push_back(x: zc3m);
211 bondInstruments.push_back(x: zc6m);
212 bondInstruments.push_back(x: zc1y);
213
214 // Adding the Fixed rate bonds to the curve for the long end
215 for (Size i=0; i<numberOfBonds; i++) {
216 bondInstruments.push_back(x: bondsHelpers[i]);
217 }
218
219 auto bondDiscountingTermStructure = ext::make_shared<PiecewiseYieldCurve<Discount,LogLinear>>(
220 args&: settlementDate, args&: bondInstruments, args&: termStructureDayCounter);
221
222 // Building of the Libor forecasting curve
223 // deposits
224 Rate d1wQuote=0.043375;
225 Rate d1mQuote=0.031875;
226 Rate d3mQuote=0.0320375;
227 Rate d6mQuote=0.03385;
228 Rate d9mQuote=0.0338125;
229 Rate d1yQuote=0.0335125;
230 // swaps
231 Rate s2yQuote=0.0295;
232 Rate s3yQuote=0.0323;
233 Rate s5yQuote=0.0359;
234 Rate s10yQuote=0.0412;
235 Rate s15yQuote=0.0433;
236
237
238 /********************
239 *** QUOTES ***
240 ********************/
241
242 // SimpleQuote stores a value which can be manually changed;
243 // other Quote subclasses could read the value from a database
244 // or some kind of data feed.
245
246 // deposits
247 auto d1wRate = ext::make_shared<SimpleQuote>(args&: d1wQuote);
248 auto d1mRate = ext::make_shared<SimpleQuote>(args&: d1mQuote);
249 auto d3mRate = ext::make_shared<SimpleQuote>(args&: d3mQuote);
250 auto d6mRate = ext::make_shared<SimpleQuote>(args&: d6mQuote);
251 auto d9mRate = ext::make_shared<SimpleQuote>(args&: d9mQuote);
252 auto d1yRate = ext::make_shared<SimpleQuote>(args&: d1yQuote);
253 // swaps
254 auto s2yRate = ext::make_shared<SimpleQuote>(args&: s2yQuote);
255 auto s3yRate = ext::make_shared<SimpleQuote>(args&: s3yQuote);
256 auto s5yRate = ext::make_shared<SimpleQuote>(args&: s5yQuote);
257 auto s10yRate = ext::make_shared<SimpleQuote>(args&: s10yQuote);
258 auto s15yRate = ext::make_shared<SimpleQuote>(args&: s15yQuote);
259
260 /*********************
261 *** RATE HELPERS ***
262 *********************/
263
264 // RateHelpers are built from the above quotes together with
265 // other instrument dependant infos. Quotes are passed in
266 // relinkable handles which could be relinked to some other
267 // data source later.
268
269 // deposits
270 DayCounter depositDayCounter = Actual360();
271
272 auto d1w = ext::make_shared<DepositRateHelper>(
273 args: Handle<Quote>(d1wRate),
274 args: 1*Weeks, args&: fixingDays,
275 args&: calendar, args: ModifiedFollowing,
276 args: true, args&: depositDayCounter);
277 auto d1m = ext::make_shared<DepositRateHelper>(
278 args: Handle<Quote>(d1mRate),
279 args: 1*Months, args&: fixingDays,
280 args&: calendar, args: ModifiedFollowing,
281 args: true, args&: depositDayCounter);
282 auto d3m = ext::make_shared<DepositRateHelper>(
283 args: Handle<Quote>(d3mRate),
284 args: 3*Months, args&: fixingDays,
285 args&: calendar, args: ModifiedFollowing,
286 args: true, args&: depositDayCounter);
287 auto d6m = ext::make_shared<DepositRateHelper>(
288 args: Handle<Quote>(d6mRate),
289 args: 6*Months, args&: fixingDays,
290 args&: calendar, args: ModifiedFollowing,
291 args: true, args&: depositDayCounter);
292 auto d9m = ext::make_shared<DepositRateHelper>(
293 args: Handle<Quote>(d9mRate),
294 args: 9*Months, args&: fixingDays,
295 args&: calendar, args: ModifiedFollowing,
296 args: true, args&: depositDayCounter);
297 auto d1y = ext::make_shared<DepositRateHelper>(
298 args: Handle<Quote>(d1yRate),
299 args: 1*Years, args&: fixingDays,
300 args&: calendar, args: ModifiedFollowing,
301 args: true, args&: depositDayCounter);
302
303 // setup swaps
304 auto swFixedLegFrequency = Annual;
305 auto swFixedLegConvention = Unadjusted;
306 auto swFixedLegDayCounter = Thirty360(Thirty360::European);
307 auto swFloatingLegIndex = ext::make_shared<Euribor6M>();
308
309 const Period forwardStart(1*Days);
310
311 auto s2y = ext::make_shared<SwapRateHelper>(
312 args: Handle<Quote>(s2yRate), args: 2*Years,
313 args&: calendar, args&: swFixedLegFrequency,
314 args&: swFixedLegConvention, args&: swFixedLegDayCounter,
315 args&: swFloatingLegIndex, args: Handle<Quote>(), args: forwardStart);
316 auto s3y = ext::make_shared<SwapRateHelper>(
317 args: Handle<Quote>(s3yRate), args: 3*Years,
318 args&: calendar, args&: swFixedLegFrequency,
319 args&: swFixedLegConvention, args&: swFixedLegDayCounter,
320 args&: swFloatingLegIndex, args: Handle<Quote>(), args: forwardStart);
321 auto s5y = ext::make_shared<SwapRateHelper>(
322 args: Handle<Quote>(s5yRate), args: 5*Years,
323 args&: calendar, args&: swFixedLegFrequency,
324 args&: swFixedLegConvention, args&: swFixedLegDayCounter,
325 args&: swFloatingLegIndex, args: Handle<Quote>(), args: forwardStart);
326 auto s10y = ext::make_shared<SwapRateHelper>(
327 args: Handle<Quote>(s10yRate), args: 10*Years,
328 args&: calendar, args&: swFixedLegFrequency,
329 args&: swFixedLegConvention, args&: swFixedLegDayCounter,
330 args&: swFloatingLegIndex, args: Handle<Quote>(), args: forwardStart);
331 auto s15y = ext::make_shared<SwapRateHelper>(
332 args: Handle<Quote>(s15yRate), args: 15*Years,
333 args&: calendar, args&: swFixedLegFrequency,
334 args&: swFixedLegConvention, args&: swFixedLegDayCounter,
335 args&: swFloatingLegIndex, args: Handle<Quote>(), args: forwardStart);
336
337
338 /*********************
339 ** CURVE BUILDING **
340 *********************/
341
342 // Any DayCounter would be fine.
343 // ActualActual::ISDA ensures that 30 years is 30.0
344
345 // A depo-swap curve
346 std::vector<ext::shared_ptr<RateHelper>> depoSwapInstruments;
347 depoSwapInstruments.push_back(x: d1w);
348 depoSwapInstruments.push_back(x: d1m);
349 depoSwapInstruments.push_back(x: d3m);
350 depoSwapInstruments.push_back(x: d6m);
351 depoSwapInstruments.push_back(x: d9m);
352 depoSwapInstruments.push_back(x: d1y);
353 depoSwapInstruments.push_back(x: s2y);
354 depoSwapInstruments.push_back(x: s3y);
355 depoSwapInstruments.push_back(x: s5y);
356 depoSwapInstruments.push_back(x: s10y);
357 depoSwapInstruments.push_back(x: s15y);
358 auto depoSwapTermStructure = ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear>>(
359 args&: settlementDate, args&: depoSwapInstruments,
360 args&: termStructureDayCounter);
361
362 // Term structures that will be used for pricing:
363 // the one used for discounting cash flows
364 RelinkableHandle<YieldTermStructure> discountingTermStructure;
365 // the one used for forward rate forecasting
366 RelinkableHandle<YieldTermStructure> forecastingTermStructure;
367
368 /*********************
369 * BONDS TO BE PRICED *
370 **********************/
371
372 // Common data
373 Real faceAmount = 100;
374
375 // Pricing engine
376 auto bondEngine = ext::make_shared<DiscountingBondEngine>(args&: discountingTermStructure);
377
378 // Zero coupon bond
379 ZeroCouponBond zeroCouponBond(
380 settlementDays,
381 UnitedStates(UnitedStates::GovernmentBond),
382 faceAmount,
383 Date(15,August,2013),
384 Following,
385 Real(116.92),
386 Date(15,August,2003));
387
388 zeroCouponBond.setPricingEngine(bondEngine);
389
390 // Fixed 4.5% US Treasury Note
391 Schedule fixedBondSchedule(Date(15, May, 2007),
392 Date(15,May,2017), Period(Semiannual),
393 UnitedStates(UnitedStates::GovernmentBond),
394 Unadjusted, Unadjusted, DateGeneration::Backward, false);
395
396 FixedRateBond fixedRateBond(
397 settlementDays,
398 faceAmount,
399 fixedBondSchedule,
400 std::vector<Rate>(1, 0.045),
401 ActualActual(ActualActual::Bond),
402 ModifiedFollowing,
403 100.0, Date(15, May, 2007));
404
405 fixedRateBond.setPricingEngine(bondEngine);
406
407 // Floating rate bond (3M USD Libor + 0.1%)
408 // Should and will be priced on another curve later...
409
410 RelinkableHandle<YieldTermStructure> liborTermStructure;
411 const auto libor3m = ext::make_shared<USDLibor>(args: Period(3, Months), args&: liborTermStructure);
412 libor3m->addFixing(fixingDate: Date(17, July, 2008),fixing: 0.0278625);
413
414 Schedule floatingBondSchedule(Date(21, October, 2005),
415 Date(21, October, 2010), Period(Quarterly),
416 UnitedStates(UnitedStates::NYSE),
417 Unadjusted, Unadjusted, DateGeneration::Backward, true);
418
419 FloatingRateBond floatingRateBond(
420 settlementDays,
421 faceAmount,
422 floatingBondSchedule,
423 libor3m,
424 Actual360(),
425 ModifiedFollowing,
426 Natural(2),
427 // Gearings
428 std::vector<Real>(1, 1.0),
429 // Spreads
430 std::vector<Rate>(1, 0.001),
431 // Caps
432 std::vector<Rate>(),
433 // Floors
434 std::vector<Rate>(),
435 // Fixing in arrears
436 true,
437 Real(100.0),
438 Date(21, October, 2005));
439
440 floatingRateBond.setPricingEngine(bondEngine);
441
442 // Coupon pricers
443 auto pricer = ext::make_shared<BlackIborCouponPricer>();
444
445 // optionLet volatilities
446 Volatility volatility = 0.0;
447 Handle<OptionletVolatilityStructure> vol;
448 vol = Handle<OptionletVolatilityStructure>(
449 ext::make_shared<ConstantOptionletVolatility>(
450 args&: settlementDays,
451 args&: calendar,
452 args: ModifiedFollowing,
453 args&: volatility,
454 args: Actual365Fixed()));
455
456 pricer->setCapletVolatility(vol);
457 setCouponPricer(leg: floatingRateBond.cashflows(),pricer);
458
459 // Yield curve bootstrapping
460 forecastingTermStructure.linkTo(h: depoSwapTermStructure);
461 discountingTermStructure.linkTo(h: bondDiscountingTermStructure);
462
463 // We are using the depo & swap curve to estimate the future Libor rates
464 liborTermStructure.linkTo(h: depoSwapTermStructure);
465
466 /***************
467 * BOND PRICING *
468 ****************/
469
470 std::cout << std::endl;
471
472 // write column headings
473 Size widths[] = { 18, 10, 10, 10 };
474
475 std::cout << std::setw(widths[0]) << " "
476 << std::setw(widths[1]) << "ZC"
477 << std::setw(widths[2]) << "Fixed"
478 << std::setw(widths[3]) << "Floating"
479 << std::endl;
480
481 Size width = widths[0] + widths[1] + widths[2] + widths[3];
482 std::string rule(width, '-');
483
484 std::cout << rule << std::endl;
485
486 std::cout << std::fixed;
487 std::cout << std::setprecision(2);
488
489 std::cout << std::setw(widths[0]) << "Net present value"
490 << std::setw(widths[1]) << zeroCouponBond.NPV()
491 << std::setw(widths[2]) << fixedRateBond.NPV()
492 << std::setw(widths[3]) << floatingRateBond.NPV()
493 << std::endl;
494
495 std::cout << std::setw(widths[0]) << "Clean price"
496 << std::setw(widths[1]) << zeroCouponBond.cleanPrice()
497 << std::setw(widths[2]) << fixedRateBond.cleanPrice()
498 << std::setw(widths[3]) << floatingRateBond.cleanPrice()
499 << std::endl;
500
501 std::cout << std::setw(widths[0]) << "Dirty price"
502 << std::setw(widths[1]) << zeroCouponBond.dirtyPrice()
503 << std::setw(widths[2]) << fixedRateBond.dirtyPrice()
504 << std::setw(widths[3]) << floatingRateBond.dirtyPrice()
505 << std::endl;
506
507 std::cout << std::setw(widths[0]) << "Accrued coupon"
508 << std::setw(widths[1]) << zeroCouponBond.accruedAmount()
509 << std::setw(widths[2]) << fixedRateBond.accruedAmount()
510 << std::setw(widths[3]) << floatingRateBond.accruedAmount()
511 << std::endl;
512
513 std::cout << std::setw(widths[0]) << "Previous coupon"
514 << std::setw(widths[1]) << "N/A" // zeroCouponBond
515 << std::setw(widths[2]) << io::rate(r: fixedRateBond.previousCouponRate())
516 << std::setw(widths[3]) << io::rate(r: floatingRateBond.previousCouponRate())
517 << std::endl;
518
519 std::cout << std::setw(widths[0]) << "Next coupon"
520 << std::setw(widths[1]) << "N/A" // zeroCouponBond
521 << std::setw(widths[2]) << io::rate(r: fixedRateBond.nextCouponRate())
522 << std::setw(widths[3]) << io::rate(r: floatingRateBond.nextCouponRate())
523 << std::endl;
524
525 std::cout << std::setw(widths[0]) << "Yield"
526 << std::setw(widths[1])
527 << io::rate(r: zeroCouponBond.yield(dc: Actual360(),comp: Compounded,freq: Annual))
528 << std::setw(widths[2])
529 << io::rate(r: fixedRateBond.yield(dc: Actual360(),comp: Compounded,freq: Annual))
530 << std::setw(widths[3])
531 << io::rate(r: floatingRateBond.yield(dc: Actual360(),comp: Compounded,freq: Annual))
532 << std::endl;
533
534 std::cout << std::endl;
535
536 // Other computations
537 std::cout << "Sample indirect computations (for the floating rate bond): " << std::endl;
538 std::cout << rule << std::endl;
539
540 std::cout << "Yield to Clean Price: "
541 << floatingRateBond.cleanPrice(yield: floatingRateBond.yield(dc: Actual360(),comp: Compounded,freq: Annual),dc: Actual360(),comp: Compounded,freq: Annual,settlementDate) << std::endl;
542
543 std::cout << "Clean Price to Yield: "
544 << io::rate(r: floatingRateBond.yield(cleanPrice: floatingRateBond.cleanPrice(),dc: Actual360(),comp: Compounded,freq: Annual,settlementDate)) << std::endl;
545
546 /* "Yield to Price"
547 "Price to Yield" */
548
549 return 0;
550
551 } catch (std::exception& e) {
552 std::cerr << e.what() << std::endl;
553 return 1;
554 } catch (...) {
555 std::cerr << "unknown error" << std::endl;
556 return 1;
557 }
558}
559
560

source code of quantlib/Examples/Bonds/Bonds.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.