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