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	
47	using namespace QuantLib;
48	
49	int 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, -fixingDays, 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>(zc3mQuote);
98	         auto zc6mRate = ext::make_shared<SimpleQuote>(zc6mQuote);
99	         auto zc1yRate = ext::make_shared<SimpleQuote>(zc1yQuote);
100	
101	         DayCounter zcBondsDayCounter = Actual365Fixed();
102	
103	         auto zc3m = ext::make_shared<DepositRateHelper>(
104	                 Handle<Quote>(zc3mRate),
105	                 3*Months, fixingDays,
106	                 calendar, ModifiedFollowing,
107	                 true, zcBondsDayCounter);
108	         auto zc6m = ext::make_shared<DepositRateHelper>(
109	                 Handle<Quote>(zc6mRate),
110	                 6*Months, fixingDays,
111	                 calendar, ModifiedFollowing,
112	                 true, zcBondsDayCounter);
113	         auto zc1y = ext::make_shared<DepositRateHelper>(
114	                 Handle<Quote>(zc1yRate),
115	                 1*Years, fixingDays,
116	                 calendar, ModifiedFollowing,
117	                 true, 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.045
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(ext::make_shared<SimpleQuote>(marketQuote));
159	        }
160	
161	        RelinkableHandle<Quote> quoteHandle[numberOfBonds];
162	        for (Size i=0; i<numberOfBonds; i++) {
163	            quoteHandle[i].linkTo(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	                    quoteHandle[i],
176	                    settlementDays,
177	                    100.0,
178	                    schedule,
179	                    std::vector<Rate>(1,couponRates[i]),
180	                    ActualActual(ActualActual::Bond),
181	                    Unadjusted,
182	                    redemption,
183	                    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(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(zc3m);
211	         bondInstruments.push_back(zc6m);
212	         bondInstruments.push_back(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(bondsHelpers[i]);
217	         }
218	
219	         auto bondDiscountingTermStructure = ext::make_shared<PiecewiseYieldCurve<Discount,LogLinear>>(
220	                         settlementDate, bondInstruments, 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>(d1wQuote);
248	         auto d1mRate = ext::make_shared<SimpleQuote>(d1mQuote);
249	         auto d3mRate = ext::make_shared<SimpleQuote>(d3mQuote);
250	         auto d6mRate = ext::make_shared<SimpleQuote>(d6mQuote);
251	         auto d9mRate = ext::make_shared<SimpleQuote>(d9mQuote);
252	         auto d1yRate = ext::make_shared<SimpleQuote>(d1yQuote);
253	         // swaps
254	         auto s2yRate = ext::make_shared<SimpleQuote>(s2yQuote);
255	         auto s3yRate = ext::make_shared<SimpleQuote>(s3yQuote);
256	         auto s5yRate = ext::make_shared<SimpleQuote>(s5yQuote);
257	         auto s10yRate = ext::make_shared<SimpleQuote>(s10yQuote);
258	         auto s15yRate = ext::make_shared<SimpleQuote>(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	                 Handle<Quote>(d1wRate),
274	                 1*Weeks, fixingDays,
275	                 calendar, ModifiedFollowing,
276	                 true, depositDayCounter);
277	         auto d1m = ext::make_shared<DepositRateHelper>(
278	                 Handle<Quote>(d1mRate),
279	                 1*Months, fixingDays,
280	                 calendar, ModifiedFollowing,
281	                 true, depositDayCounter);
282	         auto d3m = ext::make_shared<DepositRateHelper>(
283	                 Handle<Quote>(d3mRate),
284	                 3*Months, fixingDays,
285	                 calendar, ModifiedFollowing,
286	                 true, depositDayCounter);
287	         auto d6m = ext::make_shared<DepositRateHelper>(
288	                 Handle<Quote>(d6mRate),
289	                 6*Months, fixingDays,
290	                 calendar, ModifiedFollowing,
291	                 true, depositDayCounter);
292	         auto d9m = ext::make_shared<DepositRateHelper>(
293	                 Handle<Quote>(d9mRate),
294	                 9*Months, fixingDays,
295	                 calendar, ModifiedFollowing,
296	                 true, depositDayCounter);
297	         auto d1y = ext::make_shared<DepositRateHelper>(
298	                 Handle<Quote>(d1yRate),
299	                 1*Years, fixingDays,
300	                 calendar, ModifiedFollowing,
301	                 true, 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	                 Handle<Quote>(s2yRate), 2*Years,
313	                 calendar, swFixedLegFrequency,
314	                 swFixedLegConvention, swFixedLegDayCounter,
315	                 swFloatingLegIndex, Handle<Quote>(), forwardStart);
316	         auto s3y = ext::make_shared<SwapRateHelper>(
317	                 Handle<Quote>(s3yRate), 3*Years,
318	                 calendar, swFixedLegFrequency,
319	                 swFixedLegConvention, swFixedLegDayCounter,
320	                 swFloatingLegIndex, Handle<Quote>(), forwardStart);
321	         auto s5y = ext::make_shared<SwapRateHelper>(
322	                 Handle<Quote>(s5yRate), 5*Years,
323	                 calendar, swFixedLegFrequency,
324	                 swFixedLegConvention, swFixedLegDayCounter,
325	                 swFloatingLegIndex, Handle<Quote>(), forwardStart);
326	         auto s10y = ext::make_shared<SwapRateHelper>(
327	                 Handle<Quote>(s10yRate), 10*Years,
328	                 calendar, swFixedLegFrequency,
329	                 swFixedLegConvention, swFixedLegDayCounter,
330	                 swFloatingLegIndex, Handle<Quote>(), forwardStart);
331	         auto s15y = ext::make_shared<SwapRateHelper>(
332	                 Handle<Quote>(s15yRate), 15*Years,
333	                 calendar, swFixedLegFrequency,
334	                 swFixedLegConvention, swFixedLegDayCounter,
335	                 swFloatingLegIndex, Handle<Quote>(), 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(d1w);
348	         depoSwapInstruments.push_back(d1m);
349	         depoSwapInstruments.push_back(d3m);
350	         depoSwapInstruments.push_back(d6m);
351	         depoSwapInstruments.push_back(d9m);
352	         depoSwapInstruments.push_back(d1y);
353	         depoSwapInstruments.push_back(s2y);
354	         depoSwapInstruments.push_back(s3y);
355	         depoSwapInstruments.push_back(s5y);
356	         depoSwapInstruments.push_back(s10y);
357	         depoSwapInstruments.push_back(s15y);
358	         auto depoSwapTermStructure = ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear>>(
359	                         settlementDate, depoSwapInstruments,
360	                         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>(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>(Period(3, Months), liborTermStructure);
412	         libor3m->addFixing(Date(17, July, 2008),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	                                 settlementDays,
451	                                 calendar,
452	                                 ModifiedFollowing,
453	                                 volatility,
454	                                 Actual365Fixed()));
455	
456	         pricer->setCapletVolatility(vol);
457	         setCouponPricer(floatingRateBond.cashflows(),pricer);
458	
459	         // Yield curve bootstrapping
460	         forecastingTermStructure.linkTo(depoSwapTermStructure);
461	         discountingTermStructure.linkTo(bondDiscountingTermStructure);
462	
463	         // We are using the depo & swap curve to estimate the future Libor rates
464	         liborTermStructure.linkTo(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(fixedRateBond.previousCouponRate())
516	         << std::setw(widths[3]) << io::rate(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(fixedRateBond.nextCouponRate())
522	         << std::setw(widths[3]) << io::rate(floatingRateBond.nextCouponRate())
523	         << std::endl;
524	
525	         std::cout << std::setw(widths[0]) << "Yield"
526	         << std::setw(widths[1])
527	         << io::rate(zeroCouponBond.yield(Actual360(),Compounded,Annual))
528	         << std::setw(widths[2])
529	         << io::rate(fixedRateBond.yield(Actual360(),Compounded,Annual))
530	         << std::setw(widths[3])
531	         << io::rate(floatingRateBond.yield(Actual360(),Compounded,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(floatingRateBond.yield(Actual360(),Compounded,Annual),Actual360(),Compounded,Annual,settlementDate) << std::endl;
542	
543	         std::cout << "Clean Price to Yield: "
544	         << io::rate(floatingRateBond.yield(floatingRateBond.cleanPrice(),Actual360(),Compounded,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	}