1	/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2	
3	/*!
4	 Copyright (C) 2007 Allen Kuo
5	 Copyright (C) 2015 Andres Hernandez
6	
7	 This file is part of QuantLib, a free-software/open-source library
8	 for financial quantitative analysts and developers - http://quantlib.org/
9	
10	 QuantLib is free software: you can redistribute it and/or modify it
11	 under the terms of the QuantLib license.  You should have received a
12	 copy of the license along with this program; if not, please email
13	 <quantlib-dev@lists.sf.net>. The license is also available online at
14	 <http://quantlib.org/license.shtml>.
15	
16	 This program is distributed in the hope that it will be useful, but WITHOUT
17	 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18	 FOR A PARTICULAR PURPOSE.  See the license for more details.
19	*/
20	
21	/*  This example shows how to fit a term structure to a set of bonds
22	    using four different fitting methodologies. Though fitting is most
23	    useful for large numbers of bonds with non-smooth yield tenor
24	    structures, for comparison purposes, relatively smooth bond yields
25	    are fit here and compared to known solutions (par coupons), or
26	    results generated from the bootstrap fitting method.
27	*/
28	
29	#include <ql/qldefines.hpp>
30	#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
31	#  include <ql/auto_link.hpp>
32	#endif
33	#include <ql/termstructures/yield/fittedbonddiscountcurve.hpp>
34	#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
35	#include <ql/termstructures/yield/flatforward.hpp>
36	#include <ql/termstructures/yield/bondhelpers.hpp>
37	#include <ql/termstructures/yield/nonlinearfittingmethods.hpp>
38	#include <ql/pricingengines/bond/bondfunctions.hpp>
39	#include <ql/time/calendars/target.hpp>
40	#include <ql/time/daycounters/simpledaycounter.hpp>
41	
42	#include <iostream>
43	#include <iomanip>
44	
45	#define LENGTH(a) (sizeof(a)/sizeof(a[0]))
46	
47	using namespace std;
48	using namespace QuantLib;
49	
50	// par-rate approximation
51	Rate parRate(const YieldTermStructure& yts,
52	             const std::vector<Date>& dates,
53	             const DayCounter& resultDayCounter) {
54	    QL_REQUIRE(dates.size() >= 2, "at least two dates are required");
55	    Real sum = 0.0;
56	    Time dt;
57	    for (Size i=1; i<dates.size(); ++i) {
58	        dt = resultDayCounter.yearFraction(dates[i-1], dates[i]);
59	        QL_REQUIRE(dt>=0.0, "unsorted dates");
60	        sum += yts.discount(dates[i]) * dt;
61	    }
62	    Real result = yts.discount(dates.front()) - yts.discount(dates.back());
63	    return result/sum;
64	}
65	
66	void printOutput(const std::string& tag,
67	                 const ext::shared_ptr<FittedBondDiscountCurve>& curve) {
68	    cout << tag << endl;
69	    cout << "reference date : "
70	         << curve->referenceDate()
71	         << endl;
72	    cout << "number of iterations : "
73	         << curve->fitResults().numberOfIterations()
74	         << endl
75	         << endl;
76	}
77	
78	
79	int main(int, char* []) {
80	
81	    try {
82	
83	        const Size numberOfBonds = 15;
84	        Real cleanPrice[numberOfBonds];
85	
86	        for (Real& i : cleanPrice) {
87	            i = 100.0;
88	        }
89	
90	        std::vector< ext::shared_ptr<SimpleQuote>> quote;
91	        for (Real i : cleanPrice) {
92	            quote.push_back(ext::make_shared<SimpleQuote>(i));
93	        }
94	
95	        RelinkableHandle<Quote> quoteHandle[numberOfBonds];
96	        for (Size i=0; i<numberOfBonds; i++) {
97	            quoteHandle[i].linkTo(quote[i]);
98	        }
99	
100	        Integer lengths[] = { 2, 4, 6, 8, 10, 12, 14, 16,
101	                              18, 20, 22, 24, 26, 28, 30 };
102	        Real coupons[] = { 0.0200, 0.0225, 0.0250, 0.0275, 0.0300,
103	                           0.0325, 0.0350, 0.0375, 0.0400, 0.0425,
104	                           0.0450, 0.0475, 0.0500, 0.0525, 0.0550 };
105	
106	        Frequency frequency = Annual;
107	        DayCounter dc = SimpleDayCounter();
108	        BusinessDayConvention accrualConvention = ModifiedFollowing;
109	        BusinessDayConvention convention = ModifiedFollowing;
110	        Real redemption = 100.0;
111	
112	        Calendar calendar = TARGET();
113	        Date today = calendar.adjust(Date::todaysDate());
114	        Date origToday = today;
115	        Settings::instance().evaluationDate() = today;
116	
117	        // changing bondSettlementDays=3 increases calculation
118	        // time of exponentialsplines fitting method
119	        Natural bondSettlementDays = 0;
120	        Natural curveSettlementDays = 0;
121	
122	        Date bondSettlementDate = calendar.advance(today, bondSettlementDays*Days);
123	
124	        cout << endl;
125	        cout << "Today's date: " << today << endl;
126	        cout << "Bonds' settlement date: " << bondSettlementDate << endl;
127	        cout << "Calculating fit for 15 bonds....." << endl << endl;
128	
129	        std::vector<ext::shared_ptr<BondHelper>> instrumentsA;
130	        std::vector<ext::shared_ptr<RateHelper>> instrumentsB;
131	
132	        for (Size j=0; j<LENGTH(lengths); j++) {
133	
134	            Date maturity = calendar.advance(bondSettlementDate, lengths[j]*Years);
135	
136	            Schedule schedule(bondSettlementDate, maturity, Period(frequency),
137	                              calendar, accrualConvention, accrualConvention,
138	                              DateGeneration::Backward, false);
139	
140	            auto helperA = ext::make_shared<FixedRateBondHelper>(quoteHandle[j],
141	                                             bondSettlementDays,
142	                                             100.0,
143	                                             schedule,
144	                                             std::vector<Rate>(1,coupons[j]),
145	                                             dc,
146	                                             convention,
147	                                             redemption);
148	
149	            auto helperB = ext::make_shared<FixedRateBondHelper>(quoteHandle[j],
150	                                             bondSettlementDays,
151	                                             100.0,
152	                                             schedule,
153	                                             std::vector<Rate>(1, coupons[j]),
154	                                             dc,
155	                                             convention,
156	                                             redemption);
157	            instrumentsA.push_back(helperA);
158	            instrumentsB.push_back(helperB);
159	        }
160	
161	
162	        bool constrainAtZero = true;
163	        Real tolerance = 1.0e-10;
164	        Size max = 5000;
165	
166	        auto ts0 = ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear>>(curveSettlementDays,
167	                                                          calendar,
168	                                                          instrumentsB,
169	                                                          dc);
170	
171	        ExponentialSplinesFitting exponentialSplines(constrainAtZero);
172	
173	        auto ts1 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
174	                                              calendar,
175	                                              instrumentsA,
176	                                              dc,
177	                                              exponentialSplines,
178	                                              tolerance,
179	                                              max);
180	
181	        printOutput("(a) exponential splines", ts1);
182	
183	
184	        SimplePolynomialFitting simplePolynomial(3, constrainAtZero);
185	
186	        auto ts2 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
187	                                                calendar,
188	                                                instrumentsA,
189	                                                dc,
190	                                                simplePolynomial,
191	                                                tolerance,
192	                                                max);
193	
194	        printOutput("(b) simple polynomial", ts2);
195	
196	
197	        NelsonSiegelFitting nelsonSiegel;
198	
199	        auto ts3 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
200	                                                    calendar,
201	                                                    instrumentsA,
202	                                                    dc,
203	                                                    nelsonSiegel,
204	                                                    tolerance,
205	                                                    max);
206	
207	        printOutput("(c) Nelson-Siegel", ts3);
208	
209	
210	        // a cubic bspline curve with 11 knot points, implies
211	        // n=6 (constrained problem) basis functions
212	
213	        Time knots[] =  { -30.0, -20.0,  0.0,  5.0, 10.0, 15.0,
214	                           20.0,  25.0, 30.0, 40.0, 50.0 };
215	
216	        std::vector<Time> knotVector;
217	        for (Real& knot : knots) {
218	            knotVector.push_back(knot);
219	        }
220	
221	        CubicBSplinesFitting cubicBSplines(knotVector, constrainAtZero);
222	
223	        auto ts4 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
224	                                                   calendar,
225	                                                   instrumentsA,
226	                                                   dc,
227	                                                   cubicBSplines,
228	                                                   tolerance,
229	                                                   max);
230	
231	        printOutput("(d) cubic B-splines", ts4);
232	
233	        SvenssonFitting svensson;
234	
235	        auto ts5 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
236	                                                    calendar,
237	                                                    instrumentsA,
238	                                                    dc,
239	                                                    svensson,
240	                                                    tolerance,
241	                                                    max);
242	
243	        printOutput("(e) Svensson", ts5);
244	
245	        Handle<YieldTermStructure> discountCurve(
246	            ext::make_shared<FlatForward>(
247	                                    curveSettlementDays, calendar, 0.01, dc));
248	        SpreadFittingMethod nelsonSiegelSpread(
249	                                    ext::make_shared<NelsonSiegelFitting>(),
250	                                    discountCurve);
251	
252	        auto ts6 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
253	                                                    calendar,
254	                                                    instrumentsA,
255	                                                    dc,
256	                                                    nelsonSiegelSpread,
257	                                                    tolerance,
258	                                                    max);
259	
260	        printOutput("(f) Nelson-Siegel spread", ts6);
261	
262	        //Fixed kappa, and 7 coefficients
263	        ExponentialSplinesFitting exponentialSplinesFixed(constrainAtZero,7,0.02);
264	
265	        auto ts7 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
266	                                                    calendar, 
267	                                                    instrumentsA, 
268	                                                    dc, 
269	                                                    exponentialSplinesFixed, 
270	                                                    tolerance, 
271	                                                    max);
272	
273	        printOutput("(g) exponential splines, fixed kappa", ts7);
274	
275	        cout << "Output par rates for each curve. In this case, "
276	             << endl
277	             << "par rates should equal coupons for these par bonds."
278	             << endl
279	             << endl;
280	
281	        cout << setw(6) << "tenor" << " | "
282	             << setw(6) << "coupon" << " | "
283	             << setw(6) << "bstrap" << " | "
284	             << setw(6) << "(a)" << " | "
285	             << setw(6) << "(b)" << " | "
286	             << setw(6) << "(c)" << " | "
287	             << setw(6) << "(d)" << " | "
288	             << setw(6) << "(e)" << " | "
289	             << setw(6) << "(f)" << " | "
290	             << setw(6) << "(g)" << endl;
291	
292	        for (Size i=0; i<instrumentsA.size(); i++) {
293	
294	            std::vector<ext::shared_ptr<CashFlow>> cfs =
295	                instrumentsA[i]->bond()->cashflows();
296	
297	            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
298	            std::vector<Date> keyDates;
299	            keyDates.push_back(bondSettlementDate);
300	
301	            for (Size j=0; j<cfSize-1; j++) {
302	                if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
303	                    Date myDate =  cfs[j]->date();
304	                    keyDates.push_back(myDate);
305	                }
306	            }
307	
308	            Real tenor = dc.yearFraction(today, cfs[cfSize-1]->date());
309	
310	            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
311	                 << setw(6) << fixed << setprecision(3)
312	                 << 100.*coupons[i] << " | "
313	                 // piecewise bootstrap
314	                 << setw(6) << fixed << setprecision(3)
315	                 << 100.*parRate(*ts0,keyDates,dc) << " | "
316	                 // exponential splines
317	                 << setw(6) << fixed << setprecision(3)
318	                 << 100.*parRate(*ts1,keyDates,dc) << " | "
319	                 // simple polynomial
320	                 << setw(6) << fixed << setprecision(3)
321	                 << 100.*parRate(*ts2,keyDates,dc) << " | "
322	                 // Nelson-Siegel
323	                 << setw(6) << fixed << setprecision(3)
324	                 << 100.*parRate(*ts3,keyDates,dc) << " | "
325	                 // cubic bsplines
326	                 << setw(6) << fixed << setprecision(3)
327	                 << 100.*parRate(*ts4,keyDates,dc) << " | "
328	                 // Svensson
329	                 << setw(6) << fixed << setprecision(3)
330	                 << 100.*parRate(*ts5,keyDates,dc)  << " | "
331	                 // Nelson-Siegel Spread
332	                 << setw(6) << fixed << setprecision(3)
333	                 << 100.*parRate(*ts6,keyDates,dc) << " | "
334	                 // Exponential, fixed kappa
335	                 << setw(6) << fixed << setprecision(3) 
336	                 << 100. *parRate(*ts7, keyDates, dc) << endl;
337	        }
338	
339	        cout << endl << endl << endl;
340	        cout << "Now add 23 months to today. Par rates should be "  << endl
341	             << "automatically recalculated because today's date "  << endl
342	             << "changes.  Par rates will NOT equal coupons (YTM "  << endl
343	             << "will, with the correct compounding), but the "     << endl
344	             << "piecewise yield curve par rates can be used as "   << endl
345	             << "a benchmark for correct par rates."
346	             << endl
347	             << endl;
348	
349	        today = calendar.advance(origToday,23,Months,convention);
350	        Settings::instance().evaluationDate() = today;
351	        bondSettlementDate = calendar.advance(today, bondSettlementDays*Days);
352	
353	        printOutput("(a) exponential splines", ts1);
354	
355	        printOutput("(b) simple polynomial", ts2);
356	
357	        printOutput("(c) Nelson-Siegel", ts3);
358	
359	        printOutput("(d) cubic B-splines", ts4);
360	
361	        printOutput("(e) Svensson", ts5);
362	
363	        printOutput("(f) Nelson-Siegel spread", ts6);
364	
365	        printOutput("(g) exponential spline, fixed kappa", ts7);
366	
367	        cout << endl
368	             << endl;
369	
370	
371	        cout << setw(6) << "tenor" << " | "
372	             << setw(6) << "coupon" << " | "
373	             << setw(6) << "bstrap" << " | "
374	             << setw(6) << "(a)" << " | "
375	             << setw(6) << "(b)" << " | "
376	             << setw(6) << "(c)" << " | "
377	             << setw(6) << "(d)" << " | "
378	             << setw(6) << "(e)" << " | "
379	             << setw(6) << "(f)" << " | "
380	             << setw(6) << "(g)" << endl;
381	
382	        for (Size i=0; i<instrumentsA.size(); i++) {
383	
384	            std::vector<ext::shared_ptr<CashFlow>> cfs =
385	                instrumentsA[i]->bond()->cashflows();
386	
387	            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
388	            std::vector<Date> keyDates;
389	            keyDates.push_back(bondSettlementDate);
390	
391	            for (Size j=0; j<cfSize-1; j++) {
392	                if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
393	                    Date myDate =  cfs[j]->date();
394	                    keyDates.push_back(myDate);
395	                }
396	            }
397	
398	            Real tenor = dc.yearFraction(today, cfs[cfSize-1]->date());
399	
400	            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
401	                 << setw(6) << fixed << setprecision(3)
402	                 << 100.*coupons[i] << " | "
403	                 // piecewise bootstrap
404	                 << setw(6) << fixed << setprecision(3)
405	                 << 100.*parRate(*ts0,keyDates,dc) << " | "
406	                 // exponential splines
407	                 << setw(6) << fixed << setprecision(3)
408	                 << 100.*parRate(*ts1,keyDates,dc) << " | "
409	                 // simple polynomial
410	                 << setw(6) << fixed << setprecision(3)
411	                 << 100.*parRate(*ts2,keyDates,dc) << " | "
412	                 // Nelson-Siegel
413	                 << setw(6) << fixed << setprecision(3)
414	                 << 100.*parRate(*ts3,keyDates,dc) << " | "
415	                 // cubic bsplines
416	                 << setw(6) << fixed << setprecision(3)
417	                 << 100.*parRate(*ts4,keyDates,dc) << " | "
418	                 // Svensson
419	                 << setw(6) << fixed << setprecision(3)
420	                 << 100.*parRate(*ts5,keyDates,dc) << " | "
421	                 // Nelson-Siegel Spread
422	                 << setw(6) << fixed << setprecision(3)
423	                 << 100.*parRate(*ts6,keyDates,dc) << " | "
424	                 // exponential, fixed kappa
425	                 << setw(6) << fixed << setprecision(3) 
426	                 << 100. * parRate(*ts7, keyDates, dc) << endl;
427	        }
428	
429	        cout << endl << endl << endl;
430	        cout << "Now add one more month, for a total of two years " << endl
431	             << "from the original date. The first instrument is "  << endl
432	             << "now expired and par rates should again equal "     << endl
433	             << "coupon values, since clean prices did not change."
434	             << endl
435	             << endl;
436	
437	        instrumentsA.erase(instrumentsA.begin(),
438	                           instrumentsA.begin()+1);
439	        instrumentsB.erase(instrumentsB.begin(),
440	                           instrumentsB.begin()+1);
441	
442	        today = calendar.advance(origToday,24,Months,convention);
443	        Settings::instance().evaluationDate() = today;
444	        bondSettlementDate = calendar.advance(today, bondSettlementDays*Days);
445	
446	        auto ts00 = ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear>>(curveSettlementDays,
447	                                                          calendar,
448	                                                          instrumentsB,
449	                                                          dc);
450	
451	        auto ts11 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
452	                                              calendar,
453	                                              instrumentsA,
454	                                              dc,
455	                                              exponentialSplines,
456	                                              tolerance,
457	                                              max);
458	
459	        printOutput("(a) exponential splines", ts11);
460	
461	
462	        auto ts22 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
463	                                                calendar,
464	                                                instrumentsA,
465	                                                dc,
466	                                                simplePolynomial,
467	                                                tolerance,
468	                                                max);
469	
470	        printOutput("(b) simple polynomial", ts22);
471	
472	
473	        auto ts33 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
474	                                                    calendar,
475	                                                    instrumentsA,
476	                                                    dc,
477	                                                    nelsonSiegel,
478	                                                    tolerance,
479	                                                    max);
480	
481	        printOutput("(c) Nelson-Siegel", ts33);
482	
483	
484	        auto ts44 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
485	                                                   calendar,
486	                                                   instrumentsA,
487	                                                   dc,
488	                                                   cubicBSplines,
489	                                                   tolerance,
490	                                                   max);
491	
492	        printOutput("(d) cubic B-splines", ts44);
493	
494	        auto ts55 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
495	                                                   calendar,
496	                                                   instrumentsA,
497	                                                   dc,
498	                                                   svensson,
499	                                                   tolerance,
500	                                                   max);
501	
502	        printOutput("(e) Svensson", ts55);
503	
504	        auto ts66 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays,
505	                                                    calendar,
506	                                                    instrumentsA,
507	                                                    dc,
508	                                                    nelsonSiegelSpread,
509	                                                    tolerance,
510	                                                    max);
511	
512	        printOutput("(f) Nelson-Siegel spread", ts66);
513	
514	        auto ts77 = ext::make_shared<FittedBondDiscountCurve>(curveSettlementDays, 
515	                                                    calendar, 
516	                                                    instrumentsA, 
517	                                                    dc, 
518	                                                    exponentialSplinesFixed, 
519	                                                    tolerance, 
520	                                                    max);
521	
522	        printOutput("(g) exponential, fixed kappa", ts77);
523	
524	        cout << setw(6) << "tenor" << " | "
525	             << setw(6) << "coupon" << " | "
526	             << setw(6) << "bstrap" << " | "
527	             << setw(6) << "(a)" << " | "
528	             << setw(6) << "(b)" << " | "
529	             << setw(6) << "(c)" << " | "
530	             << setw(6) << "(d)" << " | "
531	             << setw(6) << "(e)" << " | "
532	             << setw(6) << "(f)" << " | "
533	             << setw(6) << "(g)" << endl;
534	
535	        for (Size i=0; i<instrumentsA.size(); i++) {
536	
537	            std::vector<ext::shared_ptr<CashFlow>> cfs =
538	                instrumentsA[i]->bond()->cashflows();
539	
540	            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
541	            std::vector<Date> keyDates;
542	            keyDates.push_back(bondSettlementDate);
543	
544	            for (Size j=0; j<cfSize-1; j++) {
545	                if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
546	                    Date myDate =  cfs[j]->date();
547	                    keyDates.push_back(myDate);
548	                }
549	            }
550	
551	            Real tenor = dc.yearFraction(today, cfs[cfSize-1]->date());
552	
553	            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
554	                 << setw(6) << fixed << setprecision(3)
555	                 << 100.*coupons[i+1] << " | "
556	                 // piecewise bootstrap
557	                 << setw(6) << fixed << setprecision(3)
558	                 << 100.*parRate(*ts00,keyDates,dc) << " | "
559	                 // exponential splines
560	                 << setw(6) << fixed << setprecision(3)
561	                 << 100.*parRate(*ts11,keyDates,dc) << " | "
562	                 // simple polynomial
563	                 << setw(6) << fixed << setprecision(3)
564	                 << 100.*parRate(*ts22,keyDates,dc) << " | "
565	                 // Nelson-Siegel
566	                 << setw(6) << fixed << setprecision(3)
567	                 << 100.*parRate(*ts33,keyDates,dc) << " | "
568	                 // cubic bsplines
569	                 << setw(6) << fixed << setprecision(3)
570	                 << 100.*parRate(*ts44,keyDates,dc) << " | "
571	                 // Svensson
572	                 << setw(6) << fixed << setprecision(3)
573	                 << 100.*parRate(*ts55,keyDates,dc) << " | "
574	                 // Nelson-Siegel Spread
575	                 << setw(6) << fixed << setprecision(3)
576	                 << 100.*parRate(*ts66,keyDates,dc) << " | "
577	                 // exponential, fixed kappa
578	                 << setw(6) << fixed << setprecision(3) 
579	                 << 100. *parRate(*ts77, keyDates, dc) << endl;
580	        }
581	
582	
583	        cout << endl << endl << endl;
584	        cout << "Now decrease prices by a small amount, corresponding"  << endl
585	             << "to a theoretical five basis point parallel + shift of" << endl
586	             << "the yield curve. Because bond quotes change, the new " << endl
587	             << "par rates should be recalculated automatically."
588	             << endl
589	             << endl;
590	
591	        for (Size k=0; k<LENGTH(lengths)-1; k++) {
592	
593	            Real P = instrumentsA[k]->quote()->value();
594	            const Bond& b = *instrumentsA[k]->bond();
595	            Rate ytm = BondFunctions::yield(b, P,
596	                                            dc, Compounded, frequency,
597	                                            today);
598	            Time dur = BondFunctions::duration(b, ytm,
599	                                               dc, Compounded, frequency,
600	                                               Duration::Modified,
601	                                               today);
602	
603	            const Real bpsChange = 5.;
604	            // dP = -dur * P * dY
605	            Real deltaP = -dur * P * (bpsChange/10000.);
606	            quote[k+1]->setValue(P + deltaP);
607	        }
608	
609	
610	        cout << setw(6) << "tenor" << " | "
611	             << setw(6) << "coupon" << " | "
612	             << setw(6) << "bstrap" << " | "
613	             << setw(6) << "(a)" << " | "
614	             << setw(6) << "(b)" << " | "
615	             << setw(6) << "(c)" << " | "
616	             << setw(6) << "(d)" << " | "
617	             << setw(6) << "(e)" << " | "
618	             << setw(6) << "(f)" << " | "
619	             << setw(6) << "(g)" << endl;
620	
621	        for (Size i=0; i<instrumentsA.size(); i++) {
622	
623	            std::vector<ext::shared_ptr<CashFlow>> cfs =
624	                instrumentsA[i]->bond()->cashflows();
625	
626	            Size cfSize = instrumentsA[i]->bond()->cashflows().size();
627	            std::vector<Date> keyDates;
628	            keyDates.push_back(bondSettlementDate);
629	
630	            for (Size j=0; j<cfSize-1; j++) {
631	                if (!cfs[j]->hasOccurred(bondSettlementDate, false)) {
632	                    Date myDate =  cfs[j]->date();
633	                    keyDates.push_back(myDate);
634	                }
635	            }
636	
637	            Real tenor = dc.yearFraction(today, cfs[cfSize-1]->date());
638	
639	            cout << setw(6) << fixed << setprecision(3) << tenor << " | "
640	                 << setw(6) << fixed << setprecision(3)
641	                 << 100.*coupons[i+1] << " | "
642	                 // piecewise bootstrap
643	                 << setw(6) << fixed << setprecision(3)
644	                 << 100.*parRate(*ts00,keyDates,dc) << " | "
645	                 // exponential splines
646	                 << setw(6) << fixed << setprecision(3)
647	                 << 100.*parRate(*ts11,keyDates,dc) << " | "
648	                 // simple polynomial
649	                 << setw(6) << fixed << setprecision(3)
650	                 << 100.*parRate(*ts22,keyDates,dc) << " | "
651	                 // Nelson-Siegel
652	                 << setw(6) << fixed << setprecision(3)
653	                 << 100.*parRate(*ts33,keyDates,dc) << " | "
654	                 // cubic bsplines
655	                 << setw(6) << fixed << setprecision(3)
656	                 << 100.*parRate(*ts44,keyDates,dc) << " | "
657	                 // Svensson
658	                 << setw(6) << fixed << setprecision(3)
659	                 << 100.*parRate(*ts55,keyDates,dc) << " | "
660	                 // Nelson-Siegel Spread
661	                 << setw(6) << fixed << setprecision(3)
662	                 << 100.*parRate(*ts66,keyDates,dc) << " | "
663	                 // exponential spline, fixed kappa
664	                 << setw(6) << fixed << setprecision(3) 
665	                 << 100. *parRate(*ts77, keyDates, dc) << endl;
666	        }
667	
668	        return 0;
669	
670	    } catch (std::exception& e) {
671	        cerr << e.what() << endl;
672	        return 1;
673	    } catch (...) {
674	        cerr << "unknown error" << endl;
675	        return 1;
676	    }
677	
678	}