1	/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2	
3	/*!
4	 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5	 Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
6	 Copyright (C) 2004 Ferdinando Ametrano
7	 Copyright (C) 2018 Jose Garcia
8	
9	 This file is part of QuantLib, a free-software/open-source library
10	 for financial quantitative analysts and developers - http://quantlib.org/
11	
12	 QuantLib is free software: you can redistribute it and/or modify it
13	 under the terms of the QuantLib license.  You should have received a
14	 copy of the license along with this program; if not, please email
15	 <quantlib-dev@lists.sf.net>. The license is also available online at
16	 <http://quantlib.org/license.shtml>.
17	
18	 This program is distributed in the hope that it will be useful, but WITHOUT
19	 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20	 FOR A PARTICULAR PURPOSE.  See the license for more details.
21	*/
22	
23	/*  This example shows how to set up a term structure with OIS discounting
24	    and then price a simple 5 year swap.
25	
26	    Example based on market data in paper by F. M. Ametrano and M. Bianchetti,
27	    Everything You Always Wanted to Know About Multiple Interest Rate Curve Boostrapping
28	    but Were Afraid to Ask (April 2, 2013).
29	    http://ssrn.com/abstract=2219548
30	    Eonia curve was taken from Figure 25 and Euribor 6m from figure 31.
31	*/
32	
33	#include <ql/qldefines.hpp>
34	#ifdef BOOST_MSVC
35	#  include <ql/auto_link.hpp>
36	#endif
37	#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
38	#include <ql/termstructures/yieldtermstructure.hpp>
39	#include <ql/termstructures/yield/ratehelpers.hpp>
40	#include <ql/termstructures/yield/oisratehelper.hpp>
41	#include <ql/pricingengines/swap/discountingswapengine.hpp>
42	#include <ql/indexes/ibor/eonia.hpp>
43	#include <ql/indexes/ibor/euribor.hpp>
44	#include <ql/time/imm.hpp>
45	#include <ql/time/calendars/target.hpp>
46	#include <ql/time/daycounters/actual360.hpp>
47	#include <ql/time/daycounters/thirty360.hpp>
48	#include <ql/time/daycounters/actualactual.hpp>
49	#include <ql/math/interpolations/cubicinterpolation.hpp>
50	#include <ql/math/interpolations/loginterpolation.hpp>
51	
52	#include <boost/timer.hpp>
53	#include <iostream>
54	#include <iomanip>
55	
56	using namespace QuantLib;
57	
58	#if defined(QL_ENABLE_SESSIONS)
59	namespace QuantLib {
60	
61	    Integer sessionId() { return 0; }
62	
63	}
64	#endif
65	
66	
67	int main(int, char* []) {
68	
69	    try {
70	
71	        boost::timer timer;
72	        std::cout << std::endl;
73	
74	        /*********************
75	         ***  MARKET DATA  ***
76	         *********************/
77	
78	        Calendar calendar = TARGET();
79	
80	        Date todaysDate(11, December, 2012);
81	        Settings::instance().evaluationDate() = todaysDate;
82	        todaysDate = Settings::instance().evaluationDate();
83	
84	        Integer fixingDays = 2;
85	        Date settlementDate = calendar.advance(todaysDate, fixingDays, Days);
86	        // must be a business day
87	        settlementDate = calendar.adjust(settlementDate);
88	
89	
90	        std::cout << "Today: " << todaysDate.weekday()
91	                  << ", " << todaysDate << std::endl;
92	
93	        std::cout << "Settlement date: " << settlementDate.weekday()
94	                  << ", " << settlementDate << std::endl;
95	
96	        /********************
97	         ***    QUOTES    ***
98	         ********************/
99	
100	        // SimpleQuote stores a value which can be manually changed;
101	        // other Quote subclasses could read the value from a database
102	        // or some kind of data feed.
103	
104	        // deposits
105	        ext::shared_ptr<Quote> dONRate(new SimpleQuote(0.0004));
106	        ext::shared_ptr<Quote> dTNRate(new SimpleQuote(0.0004));
107	        ext::shared_ptr<Quote> dSNRate(new SimpleQuote(0.0004));
108	
109	        // OIS
110	        ext::shared_ptr<Quote> ois1WRate(new SimpleQuote(0.00070));
111	        ext::shared_ptr<Quote> ois2WRate(new SimpleQuote(0.00069));
112	        ext::shared_ptr<Quote> ois3WRate(new SimpleQuote(0.00078));
113	        ext::shared_ptr<Quote> ois1MRate(new SimpleQuote(0.00074));
114	
115	        // Dated OIS
116	        ext::shared_ptr<Quote> oisDated1Rate(new SimpleQuote( 0.000460));
117	        ext::shared_ptr<Quote> oisDated2Rate(new SimpleQuote( 0.000160));
118	        ext::shared_ptr<Quote> oisDated3Rate(new SimpleQuote(-0.000070));
119	        ext::shared_ptr<Quote> oisDated4Rate(new SimpleQuote(-0.000130));
120	        ext::shared_ptr<Quote> oisDated5Rate(new SimpleQuote(-0.000140));
121	
122	        // OIS
123	        ext::shared_ptr<Quote> ois15MRate(new SimpleQuote(0.00002));
124	        ext::shared_ptr<Quote> ois18MRate(new SimpleQuote(0.00008));
125	        ext::shared_ptr<Quote> ois21MRate(new SimpleQuote(0.00021));
126	        ext::shared_ptr<Quote> ois2YRate(new SimpleQuote(0.00036));
127	        ext::shared_ptr<Quote> ois3YRate(new SimpleQuote(0.00127));
128	        ext::shared_ptr<Quote> ois4YRate(new SimpleQuote(0.00274));
129	        ext::shared_ptr<Quote> ois5YRate(new SimpleQuote(0.00456));
130	        ext::shared_ptr<Quote> ois6YRate(new SimpleQuote(0.00647));
131	        ext::shared_ptr<Quote> ois7YRate(new SimpleQuote(0.00827));
132	        ext::shared_ptr<Quote> ois8YRate(new SimpleQuote(0.00996));
133	        ext::shared_ptr<Quote> ois9YRate(new SimpleQuote(0.01147));
134	        ext::shared_ptr<Quote> ois10YRate(new SimpleQuote(0.0128));
135	        ext::shared_ptr<Quote> ois11YRate(new SimpleQuote(0.01404));
136	        ext::shared_ptr<Quote> ois12YRate(new SimpleQuote(0.01516));
137	        ext::shared_ptr<Quote> ois15YRate(new SimpleQuote(0.01764));
138	        ext::shared_ptr<Quote> ois20YRate(new SimpleQuote(0.01939));
139	        ext::shared_ptr<Quote> ois25YRate(new SimpleQuote(0.02003));
140	        ext::shared_ptr<Quote> ois30YRate(new SimpleQuote(0.02038));
141	
142	        /*********************
143	         ***  RATE HELPERS ***
144	         *********************/
145	
146	        // RateHelpers are built from the above quotes together with
147	        // other instrument dependant infos.  Quotes are passed in
148	        // relinkable handles which could be relinked to some other
149	        // data source later.
150	
151	        // deposits
152	        DayCounter depositDayCounter = Actual360();
153	
154	        ext::shared_ptr<RateHelper> dON(new DepositRateHelper(
155	            Handle<Quote>(dONRate),
156	            1 * Days, 0,
157	            calendar, Following,
158	            false, depositDayCounter));
159	        ext::shared_ptr<RateHelper> dTN(new DepositRateHelper(
160	            Handle<Quote>(dTNRate),
161	            1 * Days, 1,
162	            calendar, Following,
163	            false, depositDayCounter));
164	        ext::shared_ptr<RateHelper> dSN(new DepositRateHelper(
165	            Handle<Quote>(dSNRate),
166	            1 * Days, 2,
167	            calendar, Following,
168	            false, depositDayCounter));
169	
170	        // OIS
171	
172	        ext::shared_ptr<Eonia> eonia(new Eonia);
173	
174	        ext::shared_ptr<RateHelper> ois1W(new OISRateHelper(
175	            2, 1 * Weeks,
176	            Handle<Quote>(ois1WRate), eonia));
177	        ext::shared_ptr<RateHelper> ois2W(new OISRateHelper(
178	            2, 2 * Weeks,
179	            Handle<Quote>(ois1WRate), eonia));
180	        ext::shared_ptr<RateHelper> ois3W(new OISRateHelper(
181	            2, 3 * Weeks,
182	            Handle<Quote>(ois1WRate), eonia));
183	        ext::shared_ptr<RateHelper> ois1M(new OISRateHelper(
184	            2, 1 * Months,
185	            Handle<Quote>(ois1WRate), eonia));
186	
187	
188	        // Dated OIS
189	
190	        ext::shared_ptr<RateHelper> oisDated1(new DatedOISRateHelper(
191	            Date(16, January, 2013), Date(13, February, 2013),
192	            Handle<Quote>(oisDated1Rate), eonia));
193	        ext::shared_ptr<RateHelper> oisDated2(new DatedOISRateHelper(
194	            Date(13, February, 2013), Date(13, March, 2013),
195	            Handle<Quote>(oisDated2Rate), eonia));
196	        ext::shared_ptr<RateHelper> oisDated3(new DatedOISRateHelper(
197	            Date(13, March, 2013), Date(10, April, 2013),
198	            Handle<Quote>(oisDated3Rate), eonia));
199	        ext::shared_ptr<RateHelper> oisDated4(new DatedOISRateHelper(
200	            Date(10, April, 2013), Date(8, May, 2013),
201	            Handle<Quote>(oisDated4Rate), eonia));
202	        ext::shared_ptr<RateHelper> oisDated5(new DatedOISRateHelper(
203	            Date(8, May, 2013), Date(12, June, 2013),
204	            Handle<Quote>(oisDated5Rate), eonia));
205	
206	        // OIS
207	        ext::shared_ptr<RateHelper> ois15M(new OISRateHelper(
208	            2, 15*Months,
209	            Handle<Quote>(ois15MRate), eonia));
210	        ext::shared_ptr<RateHelper> ois18M(new OISRateHelper(
211	            2, 18*Months,
212	            Handle<Quote>(ois18MRate), eonia));
213	        ext::shared_ptr<RateHelper> ois21M(new OISRateHelper(
214	            2, 21*Months,
215	            Handle<Quote>(ois21MRate), eonia));
216	        ext::shared_ptr<RateHelper> ois2Y(new OISRateHelper(
217	            2, 2*Years,
218	            Handle<Quote>(ois2YRate), eonia));
219	        ext::shared_ptr<RateHelper> ois3Y(new OISRateHelper(
220	            2, 3*Years,
221	            Handle<Quote>(ois3YRate), eonia));
222	        ext::shared_ptr<RateHelper> ois4Y(new OISRateHelper(
223	            2, 4*Years,
224	            Handle<Quote>(ois4YRate), eonia));
225	        ext::shared_ptr<RateHelper> ois5Y(new OISRateHelper(
226	            2, 5*Years,
227	            Handle<Quote>(ois5YRate), eonia));
228	        ext::shared_ptr<RateHelper> ois6Y(new OISRateHelper(
229	            2, 6*Years,
230	            Handle<Quote>(ois6YRate), eonia));
231	        ext::shared_ptr<RateHelper> ois7Y(new OISRateHelper(
232	            2, 7*Years,
233	            Handle<Quote>(ois7YRate), eonia));
234	        ext::shared_ptr<RateHelper> ois8Y(new OISRateHelper(
235	            2, 8*Years,
236	            Handle<Quote>(ois8YRate), eonia));
237	        ext::shared_ptr<RateHelper> ois9Y(new OISRateHelper(
238	            2, 9*Years,
239	            Handle<Quote>(ois9YRate), eonia));
240	        ext::shared_ptr<RateHelper> ois10Y(new OISRateHelper(
241	            2, 10*Years,
242	            Handle<Quote>(ois10YRate), eonia));
243	        ext::shared_ptr<RateHelper> ois11Y(new OISRateHelper(
244	            2, 11*Years,
245	            Handle<Quote>(ois11YRate), eonia));
246	        ext::shared_ptr<RateHelper> ois12Y(new OISRateHelper(
247	            2, 12*Years,
248	            Handle<Quote>(ois12YRate), eonia));
249	        ext::shared_ptr<RateHelper> ois15Y(new OISRateHelper(
250	            2, 15*Years,
251	            Handle<Quote>(ois15YRate), eonia));
252	        ext::shared_ptr<RateHelper> ois20Y(new OISRateHelper(
253	            2, 20*Years,
254	            Handle<Quote>(ois20YRate), eonia));
255	        ext::shared_ptr<RateHelper> ois25Y(new OISRateHelper(
256	            2, 25*Years,
257	            Handle<Quote>(ois25YRate), eonia));
258	        ext::shared_ptr<RateHelper> ois30Y(new OISRateHelper(
259	            2, 30*Years,
260	            Handle<Quote>(ois30YRate), eonia));
261	
262	
263	        /*********************
264	        **  CURVE BUILDING **
265	        *********************/
266	
267	        /*********************
268	        **   EONIA CURVE    **
269	        *********************/
270	
271	        DayCounter termStructureDayCounter = Actual365Fixed();
272	
273	
274	        double tolerance = 1.0e-15;
275	
276	        // Eonia curve
277	        std::vector<ext::shared_ptr<RateHelper> > eoniaInstruments;
278	        eoniaInstruments.push_back(dON);
279	        eoniaInstruments.push_back(dTN);
280	        eoniaInstruments.push_back(dSN);
281	        eoniaInstruments.push_back(ois1W);
282	        eoniaInstruments.push_back(ois2W);
283	        eoniaInstruments.push_back(ois3W);
284	        eoniaInstruments.push_back(ois1M);
285	        eoniaInstruments.push_back(oisDated1);
286	        eoniaInstruments.push_back(oisDated2);
287	        eoniaInstruments.push_back(oisDated3);
288	        eoniaInstruments.push_back(oisDated4);
289	        eoniaInstruments.push_back(oisDated5);
290	        eoniaInstruments.push_back(ois15M);
291	        eoniaInstruments.push_back(ois18M);
292	        eoniaInstruments.push_back(ois21M);
293	        eoniaInstruments.push_back(ois2Y);
294	        eoniaInstruments.push_back(ois3Y);
295	        eoniaInstruments.push_back(ois4Y);
296	        eoniaInstruments.push_back(ois5Y);
297	        eoniaInstruments.push_back(ois6Y);
298	        eoniaInstruments.push_back(ois7Y);
299	        eoniaInstruments.push_back(ois8Y);
300	        eoniaInstruments.push_back(ois9Y);
301	        eoniaInstruments.push_back(ois10Y);
302	        eoniaInstruments.push_back(ois11Y);
303	        eoniaInstruments.push_back(ois12Y);
304	        eoniaInstruments.push_back(ois15Y);
305	        eoniaInstruments.push_back(ois20Y);
306	        eoniaInstruments.push_back(ois25Y);
307	        eoniaInstruments.push_back(ois30Y);
308	
309	
310	        ext::shared_ptr<YieldTermStructure> eoniaTermStructure(
311	            new PiecewiseYieldCurve<Discount, Cubic>(
312	                todaysDate, eoniaInstruments,
313	                termStructureDayCounter,
314	                tolerance) );
315	
316	        eoniaTermStructure->enableExtrapolation();
317	
318	
319	        // Term structures that will be used for pricing:
320	        // the one used for discounting cash flows
321	        RelinkableHandle<YieldTermStructure> discountingTermStructure;
322	        // the one used for forward rate forecasting
323	        RelinkableHandle<YieldTermStructure> forecastingTermStructure;
324	
325	        discountingTermStructure.linkTo(eoniaTermStructure);
326	
327	
328	        /*********************
329	        **    EURIBOR 6M    **
330	        *********************/
331	        ext::shared_ptr<IborIndex> euribor6M(new Euribor6M);
332	
333	        // deposits
334	        ext::shared_ptr<Quote> d6MRate(new SimpleQuote(0.00312));
335	
336	        // FRAs
337	        ext::shared_ptr<Quote> fra1Rate(new SimpleQuote(0.002930));
338	        ext::shared_ptr<Quote> fra2Rate(new SimpleQuote(0.002720));
339	        ext::shared_ptr<Quote> fra3Rate(new SimpleQuote(0.002600));
340	        ext::shared_ptr<Quote> fra4Rate(new SimpleQuote(0.002560));
341	        ext::shared_ptr<Quote> fra5Rate(new SimpleQuote(0.002520));
342	        ext::shared_ptr<Quote> fra6Rate(new SimpleQuote(0.002480));
343	        ext::shared_ptr<Quote> fra7Rate(new SimpleQuote(0.002540));
344	        ext::shared_ptr<Quote> fra8Rate(new SimpleQuote(0.002610));
345	        ext::shared_ptr<Quote> fra9Rate(new SimpleQuote(0.002670));
346	        ext::shared_ptr<Quote> fra10Rate(new SimpleQuote(0.002790));
347	        ext::shared_ptr<Quote> fra11Rate(new SimpleQuote(0.002910));
348	        ext::shared_ptr<Quote> fra12Rate(new SimpleQuote(0.003030));
349	        ext::shared_ptr<Quote> fra13Rate(new SimpleQuote(0.003180));
350	        ext::shared_ptr<Quote> fra14Rate(new SimpleQuote(0.003350));
351	        ext::shared_ptr<Quote> fra15Rate(new SimpleQuote(0.003520));
352	        ext::shared_ptr<Quote> fra16Rate(new SimpleQuote(0.003710));
353	        ext::shared_ptr<Quote> fra17Rate(new SimpleQuote(0.003890));
354	        ext::shared_ptr<Quote> fra18Rate(new SimpleQuote(0.004090));
355	
356	        //swaps
357	        ext::shared_ptr<Quote> s3yRate(new SimpleQuote(0.004240));
358	        ext::shared_ptr<Quote> s4yRate(new SimpleQuote(0.005760));
359	        ext::shared_ptr<Quote> s5yRate(new SimpleQuote(0.007620));
360	        ext::shared_ptr<Quote> s6yRate(new SimpleQuote(0.009540));
361	        ext::shared_ptr<Quote> s7yRate(new SimpleQuote(0.011350));
362	        ext::shared_ptr<Quote> s8yRate(new SimpleQuote(0.013030));
363	        ext::shared_ptr<Quote> s9yRate(new SimpleQuote(0.014520));
364	        ext::shared_ptr<Quote> s10yRate(new SimpleQuote(0.015840));
365	        ext::shared_ptr<Quote> s12yRate(new SimpleQuote(0.018090));
366	        ext::shared_ptr<Quote> s15yRate(new SimpleQuote(0.020370));
367	        ext::shared_ptr<Quote> s20yRate(new SimpleQuote(0.021870));
368	        ext::shared_ptr<Quote> s25yRate(new SimpleQuote(0.022340));
369	        ext::shared_ptr<Quote> s30yRate(new SimpleQuote(0.022560));
370	        ext::shared_ptr<Quote> s35yRate(new SimpleQuote(0.022950));
371	        ext::shared_ptr<Quote> s40yRate(new SimpleQuote(0.023480));
372	        ext::shared_ptr<Quote> s50yRate(new SimpleQuote(0.024210));
373	        ext::shared_ptr<Quote> s60yRate(new SimpleQuote(0.024630));
374	
375	
376	        ext::shared_ptr<RateHelper> d6M(new DepositRateHelper(
377	            Handle<Quote>(d6MRate),
378	            6 * Months, 3,
379	            calendar, Following,
380	            false, depositDayCounter));
381	
382	        ext::shared_ptr<RateHelper> fra1(new FraRateHelper(
383	            Handle<Quote>(fra1Rate),
384	            1, euribor6M));
385	        ext::shared_ptr<RateHelper> fra2(new FraRateHelper(
386	            Handle<Quote>(fra2Rate),
387	            2, euribor6M));
388	        ext::shared_ptr<RateHelper> fra3(new FraRateHelper(
389	            Handle<Quote>(fra3Rate),
390	            3, euribor6M));
391	        ext::shared_ptr<RateHelper> fra4(new FraRateHelper(
392	            Handle<Quote>(fra4Rate),
393	            4, euribor6M));
394	        ext::shared_ptr<RateHelper> fra5(new FraRateHelper(
395	            Handle<Quote>(fra5Rate),
396	            5, euribor6M));
397	        ext::shared_ptr<RateHelper> fra6(new FraRateHelper(
398	            Handle<Quote>(fra6Rate),
399	            6, euribor6M));
400	        ext::shared_ptr<RateHelper> fra7(new FraRateHelper(
401	            Handle<Quote>(fra7Rate),
402	            7, euribor6M));
403	        ext::shared_ptr<RateHelper> fra8(new FraRateHelper(
404	            Handle<Quote>(fra8Rate),
405	            8, euribor6M));
406	        ext::shared_ptr<RateHelper> fra9(new FraRateHelper(
407	            Handle<Quote>(fra9Rate),
408	            9, euribor6M));
409	        ext::shared_ptr<RateHelper> fra10(new FraRateHelper(
410	            Handle<Quote>(fra10Rate),
411	            10, euribor6M));
412	        ext::shared_ptr<RateHelper> fra11(new FraRateHelper(
413	            Handle<Quote>(fra11Rate),
414	            11, euribor6M));
415	        ext::shared_ptr<RateHelper> fra12(new FraRateHelper(
416	            Handle<Quote>(fra12Rate),
417	            12, euribor6M));
418	        ext::shared_ptr<RateHelper> fra13(new FraRateHelper(
419	            Handle<Quote>(fra13Rate),
420	            13, euribor6M));
421	        ext::shared_ptr<RateHelper> fra14(new FraRateHelper(
422	            Handle<Quote>(fra14Rate),
423	            14, euribor6M));
424	        ext::shared_ptr<RateHelper> fra15(new FraRateHelper(
425	            Handle<Quote>(fra15Rate),
426	            15, euribor6M));
427	        ext::shared_ptr<RateHelper> fra16(new FraRateHelper(
428	            Handle<Quote>(fra16Rate),
429	            16, euribor6M));
430	        ext::shared_ptr<RateHelper> fra17(new FraRateHelper(
431	            Handle<Quote>(fra17Rate),
432	            17, euribor6M));
433	        ext::shared_ptr<RateHelper> fra18(new FraRateHelper(
434	            Handle<Quote>(fra18Rate),
435	            18, euribor6M));
436	
437	
438	        // setup swaps
439	
440	        Frequency swFixedLegFrequency = Annual;
441	        BusinessDayConvention swFixedLegConvention = Unadjusted;
442	        DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European);
443	
444	        ext::shared_ptr<IborIndex> swFloatingLegIndex(new Euribor6M);
445	
446	        ext::shared_ptr<RateHelper> s3y(new SwapRateHelper(
447	            Handle<Quote>(s3yRate), 3 * Years,
448	            calendar, swFixedLegFrequency,
449	            swFixedLegConvention, swFixedLegDayCounter,
450	            swFloatingLegIndex,
451	            Handle<Quote>(), 0 * Days, discountingTermStructure));
452	
453	        ext::shared_ptr<RateHelper> s4y(new SwapRateHelper(
454	            Handle<Quote>(s4yRate), 4 * Years,
455	            calendar, swFixedLegFrequency,
456	            swFixedLegConvention, swFixedLegDayCounter,
457	            swFloatingLegIndex,
458	            Handle<Quote>(), 0 * Days, discountingTermStructure));
459	
460	        ext::shared_ptr<RateHelper> s5y(new SwapRateHelper(
461	            Handle<Quote>(s5yRate), 5 * Years,
462	            calendar, swFixedLegFrequency,
463	            swFixedLegConvention, swFixedLegDayCounter,
464	            swFloatingLegIndex,
465	            Handle<Quote>(), 0 * Days, discountingTermStructure));
466	
467	        ext::shared_ptr<RateHelper> s6y(new SwapRateHelper(
468	            Handle<Quote>(s6yRate), 6 * Years,
469	            calendar, swFixedLegFrequency,
470	            swFixedLegConvention, swFixedLegDayCounter,
471	            swFloatingLegIndex,
472	            Handle<Quote>(), 0 * Days, discountingTermStructure));
473	
474	        ext::shared_ptr<RateHelper> s7y(new SwapRateHelper(
475	            Handle<Quote>(s7yRate), 7 * Years,
476	            calendar, swFixedLegFrequency,
477	            swFixedLegConvention, swFixedLegDayCounter,
478	            swFloatingLegIndex,
479	            Handle<Quote>(), 0 * Days, discountingTermStructure));
480	
481	        ext::shared_ptr<RateHelper> s8y(new SwapRateHelper(
482	            Handle<Quote>(s8yRate), 8 * Years,
483	            calendar, swFixedLegFrequency,
484	            swFixedLegConvention, swFixedLegDayCounter,
485	            swFloatingLegIndex,
486	            Handle<Quote>(), 0 * Days, discountingTermStructure));
487	
488	        ext::shared_ptr<RateHelper> s9y(new SwapRateHelper(
489	            Handle<Quote>(s9yRate), 9 * Years,
490	            calendar, swFixedLegFrequency,
491	            swFixedLegConvention, swFixedLegDayCounter,
492	            swFloatingLegIndex,
493	            Handle<Quote>(), 0 * Days, discountingTermStructure));
494	
495	        ext::shared_ptr<RateHelper> s10y(new SwapRateHelper(
496	            Handle<Quote>(s10yRate), 10 * Years,
497	            calendar, swFixedLegFrequency,
498	            swFixedLegConvention, swFixedLegDayCounter,
499	            swFloatingLegIndex,
500	            Handle<Quote>(), 0 * Days, discountingTermStructure));
501	
502	        ext::shared_ptr<RateHelper> s12y(new SwapRateHelper(
503	            Handle<Quote>(s12yRate), 12 * Years,
504	            calendar, swFixedLegFrequency,
505	            swFixedLegConvention, swFixedLegDayCounter,
506	            swFloatingLegIndex,
507	            Handle<Quote>(), 0 * Days, discountingTermStructure));
508	
509	        ext::shared_ptr<RateHelper> s15y(new SwapRateHelper(
510	            Handle<Quote>(s15yRate), 15 * Years,
511	            calendar, swFixedLegFrequency,
512	            swFixedLegConvention, swFixedLegDayCounter,
513	            swFloatingLegIndex,
514	            Handle<Quote>(), 0 * Days, discountingTermStructure));
515	
516	        ext::shared_ptr<RateHelper> s20y(new SwapRateHelper(
517	            Handle<Quote>(s20yRate), 20 * Years,
518	            calendar, swFixedLegFrequency,
519	            swFixedLegConvention, swFixedLegDayCounter,
520	            swFloatingLegIndex,
521	            Handle<Quote>(), 0 * Days, discountingTermStructure));
522	
523	        ext::shared_ptr<RateHelper> s25y(new SwapRateHelper(
524	            Handle<Quote>(s25yRate), 25 * Years,
525	            calendar, swFixedLegFrequency,
526	            swFixedLegConvention, swFixedLegDayCounter,
527	            swFloatingLegIndex,
528	            Handle<Quote>(), 0 * Days, discountingTermStructure));
529	
530	        ext::shared_ptr<RateHelper> s30y(new SwapRateHelper(
531	            Handle<Quote>(s30yRate), 30 * Years,
532	            calendar, swFixedLegFrequency,
533	            swFixedLegConvention, swFixedLegDayCounter,
534	            swFloatingLegIndex,
535	            Handle<Quote>(), 0 * Days, discountingTermStructure));
536	
537	        ext::shared_ptr<RateHelper> s35y(new SwapRateHelper(
538	            Handle<Quote>(s35yRate), 35 * Years,
539	            calendar, swFixedLegFrequency,
540	            swFixedLegConvention, swFixedLegDayCounter,
541	            swFloatingLegIndex,
542	            Handle<Quote>(), 0 * Days, discountingTermStructure));
543	
544	        ext::shared_ptr<RateHelper> s40y(new SwapRateHelper(
545	            Handle<Quote>(s40yRate), 40 * Years,
546	            calendar, swFixedLegFrequency,
547	            swFixedLegConvention, swFixedLegDayCounter,
548	            swFloatingLegIndex,
549	            Handle<Quote>(), 0 * Days, discountingTermStructure));
550	
551	        ext::shared_ptr<RateHelper> s50y(new SwapRateHelper(
552	            Handle<Quote>(s50yRate), 50 * Years,
553	            calendar, swFixedLegFrequency,
554	            swFixedLegConvention, swFixedLegDayCounter,
555	            swFloatingLegIndex,
556	            Handle<Quote>(), 0 * Days, discountingTermStructure));
557	
558	        ext::shared_ptr<RateHelper> s60y(new SwapRateHelper(
559	            Handle<Quote>(s60yRate), 60 * Years,
560	            calendar, swFixedLegFrequency,
561	            swFixedLegConvention, swFixedLegDayCounter,
562	            swFloatingLegIndex,
563	            Handle<Quote>(), 0 * Days, discountingTermStructure));
564	
565	        // Euribor 6M curve
566	        std::vector<ext::shared_ptr<RateHelper> > euribor6MInstruments;
567	        euribor6MInstruments.push_back(d6M);
568	        euribor6MInstruments.push_back(fra1);
569	        euribor6MInstruments.push_back(fra2);
570	        euribor6MInstruments.push_back(fra3);
571	        euribor6MInstruments.push_back(fra4);
572	        euribor6MInstruments.push_back(fra5);
573	        euribor6MInstruments.push_back(fra6);
574	        euribor6MInstruments.push_back(fra7);
575	        euribor6MInstruments.push_back(fra8);
576	        euribor6MInstruments.push_back(fra9);
577	        euribor6MInstruments.push_back(fra10);
578	        euribor6MInstruments.push_back(fra11);
579	        euribor6MInstruments.push_back(fra12);
580	        euribor6MInstruments.push_back(fra13);
581	        euribor6MInstruments.push_back(fra14);
582	        euribor6MInstruments.push_back(fra15);
583	        euribor6MInstruments.push_back(fra16);
584	        euribor6MInstruments.push_back(fra17);
585	        euribor6MInstruments.push_back(fra18);
586	        euribor6MInstruments.push_back(s3y);
587	        euribor6MInstruments.push_back(s4y);
588	        euribor6MInstruments.push_back(s5y);
589	        euribor6MInstruments.push_back(s6y);
590	        euribor6MInstruments.push_back(s7y);
591	        euribor6MInstruments.push_back(s8y);
592	        euribor6MInstruments.push_back(s9y);
593	        euribor6MInstruments.push_back(s10y);
594	        euribor6MInstruments.push_back(s12y);
595	        euribor6MInstruments.push_back(s15y);
596	        euribor6MInstruments.push_back(s20y);
597	        euribor6MInstruments.push_back(s25y);
598	        euribor6MInstruments.push_back(s30y);
599	        euribor6MInstruments.push_back(s35y);
600	        euribor6MInstruments.push_back(s40y);
601	        euribor6MInstruments.push_back(s50y);
602	        euribor6MInstruments.push_back(s60y);
603	
604	        ext::shared_ptr<YieldTermStructure> euribor6MTermStructure(
605	            new PiecewiseYieldCurve<Discount, Cubic>(
606	                settlementDate, euribor6MInstruments,
607	                termStructureDayCounter,
608	                tolerance));
609	
610	
611	        /*********************
612	        * SWAPS TO BE PRICED *
613	        **********************/
614	
615	        // constant nominal 1,000,000 Euro
616	        Real nominal = 1000000.0;
617	        // fixed leg
618	        Frequency fixedLegFrequency = Annual;
619	        BusinessDayConvention fixedLegConvention = Unadjusted;
620	        BusinessDayConvention floatingLegConvention = ModifiedFollowing;
621	        DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
622	        Rate fixedRate = 0.007;
623	        DayCounter floatingLegDayCounter = Actual360();
624	
625	        // floating leg
626	        Frequency floatingLegFrequency = Semiannual;
627	        ext::shared_ptr<IborIndex> euriborIndex(
628	                                     new Euribor6M(forecastingTermStructure));
629	        Spread spread = 0.0;
630	
631	        Integer lenghtInYears = 5;
632	        VanillaSwap::Type swapType = VanillaSwap::Payer;
633	
634	        Date maturity = settlementDate + lenghtInYears*Years;
635	        Schedule fixedSchedule(settlementDate, maturity,
636	                               Period(fixedLegFrequency),
637	                               calendar, fixedLegConvention,
638	                               fixedLegConvention,
639	                               DateGeneration::Forward, false);
640	        Schedule floatSchedule(settlementDate, maturity,
641	                               Period(floatingLegFrequency),
642	                               calendar, floatingLegConvention,
643	                               floatingLegConvention,
644	                               DateGeneration::Forward, false);
645	        VanillaSwap spot5YearSwap(swapType, nominal,
646	            fixedSchedule, fixedRate, fixedLegDayCounter,
647	            floatSchedule, euriborIndex, spread,
648	            floatingLegDayCounter);
649	
650	        Date fwdStart = calendar.advance(settlementDate, 1, Years);
651	        Date fwdMaturity = fwdStart + lenghtInYears*Years;
652	        Schedule fwdFixedSchedule(fwdStart, fwdMaturity,
653	                                  Period(fixedLegFrequency),
654	                                  calendar, fixedLegConvention,
655	                                  fixedLegConvention,
656	                                  DateGeneration::Forward, false);
657	        Schedule fwdFloatSchedule(fwdStart, fwdMaturity,
658	                                  Period(floatingLegFrequency),
659	                                  calendar, floatingLegConvention,
660	                                  floatingLegConvention,
661	                                  DateGeneration::Forward, false);
662	        VanillaSwap oneYearForward5YearSwap(swapType, nominal,
663	            fwdFixedSchedule, fixedRate, fixedLegDayCounter,
664	            fwdFloatSchedule, euriborIndex, spread,
665	            floatingLegDayCounter);
666	
667	
668	        /***************
669	        * SWAP PRICING *
670	        ****************/
671	
672	        // utilities for reporting
673	        std::vector<std::string> headers(4);
674	        headers[0] = "term structure";
675	        headers[1] = "net present value";
676	        headers[2] = "fair spread";
677	        headers[3] = "fair fixed rate";
678	        std::string separator = " | ";
679	        Size width = headers[0].size() + separator.size()
680	                   + headers[1].size() + separator.size()
681	                   + headers[2].size() + separator.size()
682	                   + headers[3].size() + separator.size() - 1;
683	        std::string rule(width, '-'), dblrule(width, '=');
684	        std::string tab(8, ' ');
685	
686	        // calculations
687	        std::cout << dblrule << std::endl;
688	        std::cout <<  "5-year market swap-rate = "
689	                  << std::setprecision(2) << io::rate(s5yRate->value())
690	                  << std::endl;
691	        std::cout << dblrule << std::endl;
692	
693	        std::cout << tab << "5-years swap paying "
694	                  << io::rate(fixedRate) << std::endl;
695	        std::cout << headers[0] << separator
696	                  << headers[1] << separator
697	                  << headers[2] << separator
698	                  << headers[3] << separator << std::endl;
699	        std::cout << rule << std::endl;
700	
701	        Real NPV;
702	        Rate fairRate;
703	        Spread fairSpread;
704	
705	        ext::shared_ptr<PricingEngine> swapEngine(
706	                         new DiscountingSwapEngine(discountingTermStructure));
707	
708	        spot5YearSwap.setPricingEngine(swapEngine);
709	        oneYearForward5YearSwap.setPricingEngine(swapEngine);
710	
711	        // Of course, you're not forced to really use different curves
712	        forecastingTermStructure.linkTo(euribor6MTermStructure);
713	        discountingTermStructure.linkTo(eoniaTermStructure);
714	
715	        NPV = spot5YearSwap.NPV();
716	        fairSpread = spot5YearSwap.fairSpread();
717	        fairRate = spot5YearSwap.fairRate();
718	
719	        std::cout << std::setw(headers[0].size())
720	                  << "eonia disc" << separator;
721	        std::cout << std::setw(headers[1].size())
722	                  << std::fixed << std::setprecision(2) << NPV << separator;
723	        std::cout << std::setw(headers[2].size())
724	                  << io::rate(fairSpread) << separator;
725	        std::cout << std::setw(headers[3].size())
726	                  << io::rate(fairRate) << separator;
727	        std::cout << std::endl;
728	
729	
730	        // let's check that the 5 years swap has been correctly re-priced
731	        QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
732	                   "5-years swap mispriced by "
733	                   << io::rate(std::fabs(fairRate-s5yRate->value())));
734	
735	
736	        forecastingTermStructure.linkTo(euribor6MTermStructure);
737	        discountingTermStructure.linkTo(euribor6MTermStructure);
738	
739	        NPV = spot5YearSwap.NPV();
740	        fairSpread = spot5YearSwap.fairSpread();
741	        fairRate = spot5YearSwap.fairRate();
742	
743	        std::cout << std::setw(headers[0].size())
744	                  << "euribor disc" << separator;
745	        std::cout << std::setw(headers[1].size())
746	                  << std::fixed << std::setprecision(2) << NPV << separator;
747	        std::cout << std::setw(headers[2].size())
748	                  << io::rate(fairSpread) << separator;
749	        std::cout << std::setw(headers[3].size())
750	                  << io::rate(fairRate) << separator;
751	        std::cout << std::endl;
752	
753	        QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
754	                  "5-years swap mispriced!");
755	
756	
757	        std::cout << rule << std::endl;
758	
759	        // now let's price the 1Y forward 5Y swap
760	
761	        std::cout << tab << "5-years, 1-year forward swap paying "
762	                  << io::rate(fixedRate) << std::endl;
763	        std::cout << headers[0] << separator
764	                  << headers[1] << separator
765	                  << headers[2] << separator
766	                  << headers[3] << separator << std::endl;
767	        std::cout << rule << std::endl;
768	
769	
770	        forecastingTermStructure.linkTo(euribor6MTermStructure);
771	        discountingTermStructure.linkTo(eoniaTermStructure);
772	
773	        NPV = oneYearForward5YearSwap.NPV();
774	        fairSpread = oneYearForward5YearSwap.fairSpread();
775	        fairRate = oneYearForward5YearSwap.fairRate();
776	
777	        std::cout << std::setw(headers[0].size())
778	                  << "eonia disc" << separator;
779	        std::cout << std::setw(headers[1].size())
780	                  << std::fixed << std::setprecision(2) << NPV << separator;
781	        std::cout << std::setw(headers[2].size())
782	                  << io::rate(fairSpread) << separator;
783	        std::cout << std::setw(headers[3].size())
784	                  << io::rate(fairRate) << separator;
785	        std::cout << std::endl;
786	
787	        forecastingTermStructure.linkTo(euribor6MTermStructure);
788	        discountingTermStructure.linkTo(euribor6MTermStructure);
789	
790	        NPV = oneYearForward5YearSwap.NPV();
791	        fairSpread = oneYearForward5YearSwap.fairSpread();
792	        fairRate = oneYearForward5YearSwap.fairRate();
793	
794	        std::cout << std::setw(headers[0].size())
795	            << "euribor disc" << separator;
796	        std::cout << std::setw(headers[1].size())
797	            << std::fixed << std::setprecision(2) << NPV << separator;
798	        std::cout << std::setw(headers[2].size())
799	            << io::rate(fairSpread) << separator;
800	        std::cout << std::setw(headers[3].size())
801	            << io::rate(fairRate) << separator;
802	        std::cout << std::endl;
803	
804	
805	
806	        // now let's say that the 5-years swap rate goes up to 0.009%.
807	        // A smarter market element--say, connected to a data source-- would
808	        // notice the change itself. Since we're using SimpleQuotes,
809	        // we'll have to change the value manually--which forces us to
810	        // downcast the handle and use the SimpleQuote
811	        // interface. In any case, the point here is that a change in the
812	        // value contained in the Quote triggers a new bootstrapping
813	        // of the curve and a repricing of the swap.
814	
815	        ext::shared_ptr<SimpleQuote> fiveYearsRate =
816	            ext::dynamic_pointer_cast<SimpleQuote>(s5yRate);
817	        fiveYearsRate->setValue(0.0090);
818	
819	        std::cout << dblrule << std::endl;
820	        std::cout <<  "5-year market swap-rate = "
821	                  << io::rate(s5yRate->value()) << std::endl;
822	        std::cout << dblrule << std::endl;
823	
824	        std::cout << tab << "5-years swap paying "
825	                  << io::rate(fixedRate) << std::endl;
826	        std::cout << headers[0] << separator
827	                  << headers[1] << separator
828	                  << headers[2] << separator
829	                  << headers[3] << separator << std::endl;
830	        std::cout << rule << std::endl;
831	
832	        // now get the updated results
833	        forecastingTermStructure.linkTo(euribor6MTermStructure);
834	        discountingTermStructure.linkTo(eoniaTermStructure);
835	
836	        NPV = spot5YearSwap.NPV();
837	        fairSpread = spot5YearSwap.fairSpread();
838	        fairRate = spot5YearSwap.fairRate();
839	
840	        std::cout << std::setw(headers[0].size())
841	                  << "eonia disc" << separator;
842	        std::cout << std::setw(headers[1].size())
843	                  << std::fixed << std::setprecision(2) << NPV << separator;
844	        std::cout << std::setw(headers[2].size())
845	                  << io::rate(fairSpread) << separator;
846	        std::cout << std::setw(headers[3].size())
847	                  << io::rate(fairRate) << separator;
848	        std::cout << std::endl;
849	
850	        QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
851	                   "5-years swap mispriced!");
852	
853	
854	        forecastingTermStructure.linkTo(euribor6MTermStructure);
855	        discountingTermStructure.linkTo(euribor6MTermStructure);
856	
857	        NPV = spot5YearSwap.NPV();
858	        fairSpread = spot5YearSwap.fairSpread();
859	        fairRate = spot5YearSwap.fairRate();
860	
861	        std::cout << std::setw(headers[0].size())
862	                  << "euribor disc" << separator;
863	        std::cout << std::setw(headers[1].size())
864	                  << std::fixed << std::setprecision(2) << NPV << separator;
865	        std::cout << std::setw(headers[2].size())
866	                  << io::rate(fairSpread) << separator;
867	        std::cout << std::setw(headers[3].size())
868	                  << io::rate(fairRate) << separator;
869	        std::cout << std::endl;
870	
871	        QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8,
872	                   "5-years swap mispriced!");
873	
874	
875	        std::cout << rule << std::endl;
876	
877	        // the 1Y forward 5Y swap changes as well
878	
879	        std::cout << tab << "5-years, 1-year forward swap paying "
880	                  << io::rate(fixedRate) << std::endl;
881	        std::cout << headers[0] << separator
882	                  << headers[1] << separator
883	                  << headers[2] << separator
884	                  << headers[3] << separator << std::endl;
885	        std::cout << rule << std::endl;
886	
887	
888	        forecastingTermStructure.linkTo(euribor6MTermStructure);
889	        discountingTermStructure.linkTo(eoniaTermStructure);
890	
891	        NPV = oneYearForward5YearSwap.NPV();
892	        fairSpread = oneYearForward5YearSwap.fairSpread();
893	        fairRate = oneYearForward5YearSwap.fairRate();
894	
895	        std::cout << std::setw(headers[0].size())
896	                  << "eonia disc" << separator;
897	        std::cout << std::setw(headers[1].size())
898	                  << std::fixed << std::setprecision(2) << NPV << separator;
899	        std::cout << std::setw(headers[2].size())
900	                  << io::rate(fairSpread) << separator;
901	        std::cout << std::setw(headers[3].size())
902	                  << io::rate(fairRate) << separator;
903	        std::cout << std::endl;
904	
905	
906	        forecastingTermStructure.linkTo(euribor6MTermStructure);
907	        discountingTermStructure.linkTo(euribor6MTermStructure);
908	
909	        NPV = oneYearForward5YearSwap.NPV();
910	        fairSpread = oneYearForward5YearSwap.fairSpread();
911	        fairRate = oneYearForward5YearSwap.fairRate();
912	
913	        std::cout << std::setw(headers[0].size())
914	                  << "euribor disc" << separator;
915	        std::cout << std::setw(headers[1].size())
916	                  << std::fixed << std::setprecision(2) << NPV << separator;
917	        std::cout << std::setw(headers[2].size())
918	                  << io::rate(fairSpread) << separator;
919	        std::cout << std::setw(headers[3].size())
920	                  << io::rate(fairRate) << separator;
921	        std::cout << std::endl;
922	
923	
924	        double seconds = timer.elapsed();
925	        Integer hours = int(seconds/3600);
926	        seconds -= hours * 3600;
927	        Integer minutes = int(seconds/60);
928	        seconds -= minutes * 60;
929	        std::cout << " \nRun completed in ";
930	        if (hours > 0)
931	            std::cout << hours << " h ";
932	        if (hours > 0 || minutes > 0)
933	            std::cout << minutes << " m ";
934	        std::cout << std::fixed << std::setprecision(0)
935	                  << seconds << " s\n" << std::endl;
936	
937	        return 0;
938	
939	    } catch (std::exception& e) {
940	        std::cerr << e.what() << std::endl;
941	        return 1;
942	    } catch (...) {
943	        std::cerr << "unknown error" << std::endl;
944	        return 1;
945	    }
946	}
947