1	/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2	
3	/*
4	 Copyright (C) 2014 Peter Caspers
5	
6	 This file is part of QuantLib, a free-software/open-source library
7	 for financial quantitative analysts and developers - http://quantlib.org/
8	
9	 QuantLib is free software: you can redistribute it and/or modify it
10	 under the terms of the QuantLib license.  You should have received a
11	 copy of the license along with this program; if not, please email
12	 <quantlib-dev@lists.sf.net>. The license is also available online at
13	 <http://quantlib.org/license.shtml>.
14	
15	 This program is distributed in the hope that it will be useful, but WITHOUT
16	 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17	 FOR A PARTICULAR PURPOSE.  See the license for more details.
18	*/
19	
20	#include <ql/qldefines.hpp>
21	#ifdef BOOST_MSVC
22	#  include <ql/auto_link.hpp>
23	#endif
24	#include <ql/instruments/floatfloatswap.hpp>
25	#include <ql/instruments/floatfloatswaption.hpp>
26	#include <ql/instruments/nonstandardswaption.hpp>
27	#include <ql/pricingengines/swap/discountingswapengine.hpp>
28	#include <ql/pricingengines/swaption/gaussian1dswaptionengine.hpp>
29	#include <ql/pricingengines/swaption/gaussian1dnonstandardswaptionengine.hpp>
30	#include <ql/pricingengines/swaption/gaussian1dfloatfloatswaptionengine.hpp>
31	#include <ql/models/shortrate/onefactormodels/gsr.hpp>
32	#include <ql/models/shortrate/onefactormodels/markovfunctional.hpp>
33	#include <ql/models/shortrate/calibrationhelpers/swaptionhelper.hpp>
34	#include <ql/math/optimization/levenbergmarquardt.hpp>
35	#include <ql/cashflows/lineartsrpricer.hpp>
36	#include <ql/indexes/ibor/euribor.hpp>
37	#include <ql/indexes/swap/euriborswap.hpp>
38	#include <ql/termstructures/yield/flatforward.hpp>
39	#include <ql/termstructures/volatility/swaption/swaptionconstantvol.hpp>
40	#include <ql/rebatedexercise.hpp>
41	#include <ql/quotes/simplequote.hpp>
42	#include <ql/time/calendars/target.hpp>
43	#include <ql/time/daycounters/actual360.hpp>
44	#include <ql/time/daycounters/thirty360.hpp>
45	
46	#include <iostream>
47	#include <iomanip>
48	
49	using namespace QuantLib;
50	
51	#if defined(QL_ENABLE_SESSIONS)
52	namespace QuantLib {
53	
54	    ThreadKey sessionId() { return 0; }
55	
56	}
57	#endif
58	
59	// helper function that prints a basket of calibrating swaptions to std::cout
60	
61	void printBasket(
62	    const std::vector<ext::shared_ptr<BlackCalibrationHelper> > &basket) {
63	    std::cout << "\n" << std::left << std::setw(20) << "Expiry" << std::setw(20)
64	              << "Maturity" << std::setw(20) << "Nominal" << std::setw(14)
65	              << "Rate" << std::setw(12) << "Pay/Rec" << std::setw(14)
66	              << "Market ivol" << std::fixed << std::setprecision(6)
67	              << std::endl;
68	    std::cout << "===================="
69	                 "===================="
70	                 "===================="
71	                 "===================="
72	                 "==================" << std::endl;
73	    for (Size j = 0; j < basket.size(); ++j) {
74	        ext::shared_ptr<SwaptionHelper> helper =
75	            ext::dynamic_pointer_cast<SwaptionHelper>(basket[j]);
76	        Date endDate = helper->underlyingSwap()->fixedSchedule().dates().back();
77	        Real nominal = helper->underlyingSwap()->nominal();
78	        Real vol = helper->volatility()->value();
79	        Real rate = helper->underlyingSwap()->fixedRate();
80	        Date expiry = helper->swaption()->exercise()->date(0);
81	        VanillaSwap::Type type = helper->swaption()->type();
82	        std::ostringstream expiryString, endDateString;
83	        expiryString << expiry;
84	        endDateString << endDate;
85	        std::cout << std::setw(20) << expiryString.str() << std::setw(20)
86	                  << endDateString.str() << std::setw(20) << nominal
87	                  << std::setw(14) << rate << std::setw(12)
88	                  << (type == VanillaSwap::Payer ? "Payer" : "Receiver")
89	                  << std::setw(14) << vol << std::endl;
90	    }
91	}
92	
93	// helper function that prints the result of a model calibraiton to std::cout
94	
95	void printModelCalibration(
96	    const std::vector<ext::shared_ptr<BlackCalibrationHelper> > &basket,
97	    const Array &volatility) {
98	
99	    std::cout << "\n" << std::left << std::setw(20) << "Expiry" << std::setw(14)
100	              << "Model sigma" << std::setw(20) << "Model price"
101	              << std::setw(20) << "market price" << std::setw(14)
102	              << "Model ivol" << std::setw(14) << "Market ivol" << std::fixed
103	              << std::setprecision(6) << std::endl;
104	    std::cout << "===================="
105	                 "===================="
106	                 "===================="
107	                 "===================="
108	                 "====================" << std::endl;
109	
110	    for (Size j = 0; j < basket.size(); ++j) {
111	        ext::shared_ptr<SwaptionHelper> helper =
112	            ext::dynamic_pointer_cast<SwaptionHelper>(basket[j]);
113	        Date expiry = helper->swaption()->exercise()->date(0);
114	        std::ostringstream expiryString;
115	        expiryString << expiry;
116	        std::cout << std::setw(20) << expiryString.str() << std::setw(14)
117	                  << volatility[j] << std::setw(20) << basket[j]->modelValue()
118	                  << std::setw(20) << basket[j]->marketValue() << std::setw(14)
119	                  << basket[j]->impliedVolatility(basket[j]->modelValue(), 1E-6,
120	                                                  1000, 0.0, 2.0)
121	                  << std::setw(14) << basket[j]->volatility()->value()
122	                  << std::endl;
123	    }
124	    if (volatility.size() > basket.size()) // only for markov model
125	        std::cout << std::setw(20) << " " << volatility.back() << std::endl;
126	}
127	
128	
129	// here the main part of the code starts
130	
131	int main(int argc, char *argv[]) {
132	
133	    try {
134	
135	        std::cout << "\nGaussian1dModel Examples" << std::endl;
136	
137	        std::cout << "\nThis is some example code showing how to use the GSR "
138		                     "\n(Gaussian short rate) and Markov Functional model."
139	                  << std::endl;
140	
141	        Date refDate(30, April, 2014);
142	        Settings::instance().evaluationDate() = refDate;
143	
144	        std::cout << "\nThe evaluation date for this example is set to "
145	                  << Settings::instance().evaluationDate() << std::endl;
146	
147	        Real forward6mLevel = 0.025;
148	        Real oisLevel = 0.02;
149	
150	        Handle<Quote> forward6mQuote(
151	            ext::make_shared<SimpleQuote>(forward6mLevel));
152	        Handle<Quote> oisQuote(ext::make_shared<SimpleQuote>(oisLevel));
153	
154	        Handle<YieldTermStructure> yts6m(ext::make_shared<FlatForward>(
155	            0, TARGET(), forward6mQuote, Actual365Fixed()));
156	        Handle<YieldTermStructure> ytsOis(ext::make_shared<FlatForward>(
157	            0, TARGET(), oisQuote, Actual365Fixed()));
158	
159	        ext::shared_ptr<IborIndex> euribor6m =
160	            ext::make_shared<Euribor>(6 * Months, yts6m);
161	
162	        std::cout
163	            << "\nWe assume a multicurve setup, for simplicity with flat yield "
164	               "\nterm structures. The discounting curve is an Eonia curve at"
165	               "\na level of " << oisLevel
166	            << " and the forwarding curve is an Euribior 6m curve"
167	            << "\nat a level of " << forward6mLevel << std::endl;
168	
169	        Real volLevel = 0.20;
170	        Handle<Quote> volQuote(ext::make_shared<SimpleQuote>(volLevel));
171	        Handle<SwaptionVolatilityStructure> swaptionVol(
172	            ext::make_shared<ConstantSwaptionVolatility>(
173	                0, TARGET(), ModifiedFollowing, volQuote, Actual365Fixed()));
174	
175	        std::cout
176	            << "\nFor the volatility we assume a flat swaption volatility at "
177	            << volLevel << std::endl;
178	
179	        Real strike = 0.04;
180	        std::cout << "\nWe consider a standard 10y bermudan payer swaption "
181	                     "\nwith yearly exercises at a strike of " << strike
182	                  << std::endl;
183	
184	        Date effectiveDate = TARGET().advance(refDate, 2 * Days);
185	        Date maturityDate = TARGET().advance(effectiveDate, 10 * Years);
186	
187	        Schedule fixedSchedule(effectiveDate, maturityDate, 1 * Years, TARGET(),
188	                               ModifiedFollowing, ModifiedFollowing,
189	                               DateGeneration::Forward, false);
190	        Schedule floatingSchedule(effectiveDate, maturityDate, 6 * Months,
191	                                  TARGET(), ModifiedFollowing,
192	                                  ModifiedFollowing, DateGeneration::Forward,
193	                                  false);
194	
195	        ext::shared_ptr<NonstandardSwap> underlying =
196	            ext::make_shared<NonstandardSwap>(VanillaSwap(
197	                VanillaSwap::Payer, 1.0, fixedSchedule, strike, Thirty360(),
198	                floatingSchedule, euribor6m, 0.00, Actual360()));
199	
200	        std::vector<Date> exerciseDates;
201	        for (Size i = 1; i < 10; ++i)
202	            exerciseDates.push_back(
203	                TARGET().advance(fixedSchedule[i], -2 * Days));
204	
205	        ext::shared_ptr<Exercise> exercise =
206	            ext::make_shared<BermudanExercise>(exerciseDates, false);
207	        ext::shared_ptr<NonstandardSwaption> swaption =
208	            ext::make_shared<NonstandardSwaption>(underlying, exercise);
209	
210	        std::cout
211	            << "\nThe model is a one factor Hull White model with piecewise "
212	               "\nvolatility adapted to our exercise dates." << std::endl;
213	
214	        std::vector<Date> stepDates(exerciseDates.begin(),
215	                                    exerciseDates.end() - 1);
216	        std::vector<Real> sigmas(stepDates.size() + 1, 0.01);
217	        Real reversion = 0.01;
218	
219	        std::cout << "\nThe reversion is just kept constant at a level of "
220	                  << reversion << std::endl;
221	
222	        std::cout
223	            << "\nThe model's curve is set to the 6m forward curve. Note that "
224	               "\nthe model adapts automatically to other curves where "
225	               "appropriate "
226	               "\n(e.g. if an index requires a different forwarding curve) or "
227	               "\nwhere explicitly specified (e.g. in a swaption pricing "
228	               "engine)." << std::endl;
229	
230	        ext::shared_ptr<Gsr> gsr = ext::make_shared<Gsr>(
231	            yts6m, stepDates, sigmas, reversion);
232	
233	        ext::shared_ptr<PricingEngine> swaptionEngine =
234	            ext::make_shared<Gaussian1dSwaptionEngine>(gsr, 64, 7.0, true,
235	                                                         false, ytsOis);
236	        ext::shared_ptr<PricingEngine> nonstandardSwaptionEngine =
237	            ext::make_shared<Gaussian1dNonstandardSwaptionEngine>(
238	                gsr, 64, 7.0, true, false, Handle<Quote>(), ytsOis);
239	
240	        swaption->setPricingEngine(nonstandardSwaptionEngine);
241	
242	        std::cout
243	            << "\nThe engine can generate a calibration basket in two modes."
244	               "\nThe first one is called Naive and generates ATM swaptions "
245	               "adapted to"
246	               "\nthe exercise dates of the swaption and its maturity date"
247	            << std::endl;
248	
249	        std::cout << "\nThe resulting basket looks as follows:" << std::endl;
250	
251	        ext::shared_ptr<SwapIndex> swapBase =
252	            ext::make_shared<EuriborSwapIsdaFixA>(10 * Years, yts6m, ytsOis);
253	
254	        
255	        std::vector<ext::shared_ptr<BlackCalibrationHelper> > basket =
256	            swaption->calibrationBasket(swapBase, *swaptionVol,
257	                                        BasketGeneratingEngine::Naive);
258	        printBasket(basket);
259	        
260	
261	        std::cout
262	            << "\nLet's calibrate our model to this basket. We use a "
263	               "specialized"
264	               "\ncalibration method calibrating the sigma function one by one "
265	               "to"
266	               "\nthe calibrating vanilla swaptions. The result of this is as "
267	               "follows:" << std::endl;
268	
269	        for (Size i = 0; i < basket.size(); ++i)
270	            basket[i]->setPricingEngine(swaptionEngine);
271	
272	        LevenbergMarquardt method;
273	        EndCriteria ec(1000, 10, 1E-8, 1E-8,
274	                       1E-8); // only max iterations use actually used by LM
275	
276	        
277	        gsr->calibrateVolatilitiesIterative(basket, method, ec);
278	        
279	
280	        printModelCalibration(basket, gsr->volatility());
281	        
282	
283	        std::cout << "\nFinally we price our bermudan swaption in the "
284	                     "calibrated model:" << std::endl;
285	
286	        
287	        Real npv = swaption->NPV();
288	        
289	
290	        std::cout << "\nBermudan swaption NPV (ATM calibrated GSR) = "
291	                  << std::fixed << std::setprecision(6) << npv << std::endl;
292	        
293	
294	        std::cout << "\nThere is another mode to generate a calibration basket called"
295	                     "\nMaturityStrikeByDeltaGamma. This means that the maturity,"
296	                     "\nthe strike and the nominal of the calibrating swaptions are"
297	                     "\nobtained matching the NPV, first derivative and second derivative"
298	                     "\nof the swap you will exercise into at at each bermudan call date."
299	                     "\nThe derivatives are taken with respect to the model's state variable."
300	                     "\nLet's try this in our case."
301	                  << std::endl;
302	
303	        
304	        basket = swaption->calibrationBasket(
305	            swapBase, *swaptionVol,
306	            BasketGeneratingEngine::MaturityStrikeByDeltaGamma);
307	        
308	
309	        printBasket(basket);
310	        
311	
312	        std::cout
313	            << "\nThe calibrated nominal is close to the exotics nominal."
314	               "\nThe expiries and maturity dates of the vanillas are the same"
315	               "\nas in the case above. The difference is the strike which"
316	               "\nis now equal to the exotics strike." << std::endl;
317	
318	        std::cout << "\nLet's see how this affects the exotics npv. The "
319	                     "\nrecalibrated model is:" << std::endl;
320	
321	        for (Size i = 0; i < basket.size(); ++i)
322	            basket[i]->setPricingEngine(swaptionEngine);
323	
324	        
325	        gsr->calibrateVolatilitiesIterative(basket, method, ec);
326	        
327	
328	        printModelCalibration(basket, gsr->volatility());
329	        
330	
331	        std::cout << "\nAnd the bermudan's price becomes:" << std::endl;
332	
333	        
334	        npv = swaption->NPV();
335	        
336	
337	        std::cout << "\nBermudan swaption NPV (deal strike calibrated GSR) = "
338	                  << std::setprecision(6) << npv << std::endl;
339	
340	        
341	
342	        std::cout
343	            << "\nWe can do more complicated things, let's e.g. modify the"
344	               "\nnominal schedule to be linear amortizing and see what"
345	               "\nthe effect on the generated calibration basket is:"
346	            << std::endl;
347	
348	        std::vector<Real> nominalFixed, nominalFloating;
349	        for (Size i = 0; i < fixedSchedule.size() - 1; ++i) {
350	            Real tmpNom = 1.0 - (Real)i / (fixedSchedule.size() - 1);
351	            nominalFixed.push_back(tmpNom);
352	            nominalFloating.push_back(tmpNom);
353	            nominalFloating.push_back(
354	                tmpNom); // we use that the swap is 6m vs. 1y here
355	        }
356	        std::vector<Real> strikes(nominalFixed.size(), strike);
357	
358	        ext::shared_ptr<NonstandardSwap> underlying2(new NonstandardSwap(
359	            VanillaSwap::Payer, nominalFixed, nominalFloating, fixedSchedule,
360	            strikes, Thirty360(), floatingSchedule, euribor6m, 1.0, 0.0,
361	            Actual360()));
362	        ext::shared_ptr<NonstandardSwaption> swaption2 =
363	            ext::make_shared<NonstandardSwaption>(underlying2, exercise);
364	
365	        swaption2->setPricingEngine(nonstandardSwaptionEngine);
366	
367	        
368	        basket = swaption2->calibrationBasket(
369	            swapBase, *swaptionVol,
370	            BasketGeneratingEngine::MaturityStrikeByDeltaGamma);
371	        
372	
373	        printBasket(basket);
374	        
375	
376	        std::cout << "\nThe notional is weighted over the underlying exercised "
377	                     "\ninto and the maturity is adjusted downwards. The rate"
378	                     "\non the other hand is not affected." << std::endl;
379	
380	        std::cout
381	           << "\nYou can also price exotic bond's features. If you have e.g. a"
382	             "\nbermudan callable fixed bond you can set up the call right "
383	               "\nas a swaption to enter into a one leg swap with notional"
384	               "\nreimbursement at maturity."
385	               "\nThe exercise should then be written as a rebated exercise"
386	               "\npaying the notional in case of exercise." << std::endl;
387	
388	        std::cout << "\nThe calibration basket looks like this:" << std::endl;
389	
390	        std::vector<Real> nominalFixed2(nominalFixed.size(), 1.0);
391	        std::vector<Real> nominalFloating2(nominalFloating.size(),
392	                                           0.0); // null the second leg
393	
394	        ext::shared_ptr<NonstandardSwap> underlying3(new NonstandardSwap(
395	            VanillaSwap::Receiver, nominalFixed2, nominalFloating2,
396	            fixedSchedule, strikes, Thirty360(), floatingSchedule, euribor6m,
397	            1.0, 0.0, Actual360(), false,
398	            true)); // final capital exchange
399	
400	        ext::shared_ptr<RebatedExercise> exercise2 =
401	            ext::make_shared<RebatedExercise>(*exercise, -1.0, 2, TARGET());
402	
403	        ext::shared_ptr<NonstandardSwaption> swaption3 =
404	            ext::make_shared<NonstandardSwaption>(underlying3, exercise2);
405	
406	        ext::shared_ptr<SimpleQuote> oas0 =
407	            ext::make_shared<SimpleQuote>(0.0);
408	        ext::shared_ptr<SimpleQuote> oas100 =
409	            ext::make_shared<SimpleQuote>(0.01);
410	        RelinkableHandle<Quote> oas(oas0);
411	
412	        ext::shared_ptr<PricingEngine> nonstandardSwaptionEngine2 =
413	            ext::make_shared<Gaussian1dNonstandardSwaptionEngine>(
414	                gsr, 64, 7.0, true, false, oas); // change discounting to 6m
415	
416	        swaption3->setPricingEngine(nonstandardSwaptionEngine2);
417	
418	        
419	
420	        basket = swaption3->calibrationBasket(
421	            swapBase, *swaptionVol,
422	            BasketGeneratingEngine::MaturityStrikeByDeltaGamma);
423	        
424	
425	        printBasket(basket);
426	        
427	
428	        std::cout
429	            << "\nNote that nominals are not exactly 1.0 here. This is"
430	            << "\nbecause we do our bond discounting on 6m level while"
431	            << "\nthe swaptions are still discounted on OIS level."
432	            << "\n(You can try this by changing the OIS level to the "
433	            << "\n6m level, which will produce nominals near 1.0)."
434	            << "\nThe npv of the call right is (after recalibrating the model)"
435	            << std::endl;
436	
437	        for (Size i = 0; i < basket.size(); i++)
438	            basket[i]->setPricingEngine(swaptionEngine);
439	
440	        
441	        gsr->calibrateVolatilitiesIterative(basket, method, ec);
442	        Real npv3 = swaption3->NPV();
443	        
444	
445	        std::cout << "\nBond's bermudan call right npv = "
446	                  << std::setprecision(6) << npv3 << std::endl;
447	        
448	
449	        std::cout
450	            << "\nUp to now, no credit spread is included in the pricing."
451	               "\nWe can do so by specifying an oas in the pricing engine."
452	               "\nLet's set the spread level to 100bp and regenerate"
453	               "\nthe calibration basket." << std::endl;
454	
455	        oas.linkTo(oas100);
456	
457	        
458	        basket = swaption3->calibrationBasket(
459	            swapBase, *swaptionVol,
460	            BasketGeneratingEngine::MaturityStrikeByDeltaGamma);
461	        
462	        printBasket(basket);
463	        
464	
465	        std::cout
466	            << "\nThe adjusted basket takes the credit spread into account."
467	               "\nThis is consistent to a hedge where you would have a"
468	               "\nmargin on the float leg around 100bp,too." << std::endl;
469	
470	        std::cout << "\nThe npv becomes:" << std::endl;
471	
472	        for (Size i = 0; i < basket.size(); i++)
473	            basket[i]->setPricingEngine(swaptionEngine);
474	
475	        
476	        gsr->calibrateVolatilitiesIterative(basket, method, ec);
477	        Real npv4 = swaption3->NPV();
478	        
479	
480	        std::cout << "\nBond's bermudan call right npv (oas = 100bp) = "
481	                  << std::setprecision(6) << npv4 << std::endl;
482	        
483	
484	        std::cout
485	            << "\nThe next instrument we look at is a CMS 10Y vs Euribor "
486	               "\n6M swaption. The maturity is again 10 years and the option"
487	               "\nis exercisable on a yearly basis" << std::endl;
488	
489	        ext::shared_ptr<FloatFloatSwap> underlying4(new FloatFloatSwap(
490	                VanillaSwap::Payer, 1.0, 1.0, fixedSchedule, swapBase,
491	                Thirty360(), floatingSchedule, euribor6m, Actual360(), false,
492	                false, 1.0, 0.0, Null<Real>(), Null<Real>(), 1.0, 0.0010));
493	
494	        ext::shared_ptr<FloatFloatSwaption> swaption4 =
495	            ext::make_shared<FloatFloatSwaption>(underlying4, exercise);
496	
497	        ext::shared_ptr<Gaussian1dFloatFloatSwaptionEngine>
498	            floatSwaptionEngine(new Gaussian1dFloatFloatSwaptionEngine(
499	                    gsr, 64, 7.0, true, false, Handle<Quote>(), ytsOis, true));
500	
501	        swaption4->setPricingEngine(floatSwaptionEngine);
502	
503	        std::cout
504	            << "\nSince the underlying is quite exotic already, we start with"
505	               "\npricing this using the LinearTsrPricer for CMS coupon "
506	               "estimation" << std::endl;
507	
508	        Handle<Quote> reversionQuote(
509	            ext::make_shared<SimpleQuote>(reversion));
510	
511	        const Leg &leg0 = underlying4->leg(0);
512	        const Leg &leg1 = underlying4->leg(1);
513	        ext::shared_ptr<CmsCouponPricer> cmsPricer =
514	            ext::make_shared<LinearTsrPricer>(swaptionVol, reversionQuote);
515	        ext::shared_ptr<IborCouponPricer> iborPricer(new BlackIborCouponPricer);
516	
517	        setCouponPricer(leg0, cmsPricer);
518	        setCouponPricer(leg1, iborPricer);
519	
520	        ext::shared_ptr<PricingEngine> swapPricer =
521	            ext::make_shared<DiscountingSwapEngine>(ytsOis);
522	
523	        underlying4->setPricingEngine(swapPricer);
524	
525	        
526	        Real npv5 = underlying4->NPV();
527	        
528	
529	        std::cout << "Underlying CMS Swap NPV = " << std::setprecision(6)
530	                  << npv5 << std::endl;
531	        std::cout << "       CMS     Leg  NPV = " << underlying4->legNPV(0)
532	                  << std::endl;
533	        std::cout << "       Euribor Leg  NPV = " << underlying4->legNPV(1)
534	                  << std::endl;
535	
536	        
537	
538	        std::cout << "\nWe generate a naive calibration basket and calibrate "
539	                     "\nthe GSR model to it:" << std::endl;
540	
541	        
542	        basket = swaption4->calibrationBasket(swapBase, *swaptionVol,
543	                                              BasketGeneratingEngine::Naive);
544	        for (Size i = 0; i < basket.size(); ++i)
545	            basket[i]->setPricingEngine(swaptionEngine);
546	        gsr->calibrateVolatilitiesIterative(basket, method, ec);
547	        
548	
549	        printBasket(basket);
550	        printModelCalibration(basket, gsr->volatility());
551	        
552	
553	        std::cout << "\nThe npv of the bermudan swaption is" << std::endl;
554	
555	        
556	        Real npv6 = swaption4->NPV();
557	        
558	
559	        std::cout << "\nFloat swaption NPV (GSR) = " << std::setprecision(6)
560	                  << npv6 << std::endl;
561	        
562	
563	        std::cout << "\nIn this case it is also interesting to look at the "
564	                     "\nunderlying swap npv in the GSR model." << std::endl;
565	
566	        std::cout << "\nFloat swap NPV (GSR) = " << std::setprecision(6)
567	                  << swaption4->result<Real>("underlyingValue") << std::endl;
568	
569	        std::cout << "\nNot surprisingly, the underlying is priced differently"
570	                     "\ncompared to the LinearTsrPricer, since a different"
571	                     "\nsmile is implied by the GSR model." << std::endl;
572	
573	        std::cout << "\nThis is exactly where the Markov functional model"
574	                  << "\ncomes into play, because it can calibrate to any"
575	                  << "\ngiven underlying smile (as long as it is arbitrage"
576	                  << "\nfree). We try this now. Of course the usual use case"
577	                  << "\nis not to calibrate to a flat smile as in our simple"
578	                  << "\nexample, still it should be possible, of course..."
579	                  << std::endl;
580	
581	        std::vector<Date> markovStepDates(exerciseDates.begin(),
582	                                          exerciseDates.end());
583	        const std::vector<Date>& cmsFixingDates(markovStepDates);
584	        std::vector<Real> markovSigmas(markovStepDates.size() + 1, 0.01);
585	        std::vector<Period> tenors(cmsFixingDates.size(), 10 * Years);
586	        ext::shared_ptr<MarkovFunctional> markov =
587	            ext::make_shared<MarkovFunctional>(
588	                yts6m, reversion, markovStepDates, markovSigmas, swaptionVol,
589	                cmsFixingDates, tenors, swapBase,
590	                MarkovFunctional::ModelSettings().withYGridPoints(16));
591	
592	        ext::shared_ptr<Gaussian1dSwaptionEngine> swaptionEngineMarkov =
593	            ext::make_shared<Gaussian1dSwaptionEngine>(markov, 8, 5.0, true,
594	                                                         false, ytsOis);
595	        ext::shared_ptr<Gaussian1dFloatFloatSwaptionEngine>
596	            floatEngineMarkov =
597	                ext::make_shared<Gaussian1dFloatFloatSwaptionEngine>(
598	                    markov, 16, 7.0, true, false, Handle<Quote>(), ytsOis,
599	                    true);
600	
601	        swaption4->setPricingEngine(floatEngineMarkov);
602	
603	        
604	        Real npv7 = swaption4->NPV();
605	        
606	
607	        std::cout << "\nThe option npv is the markov model is:" << std::endl;
608	
609	        std::cout << "\nFloat swaption NPV (Markov) = " << std::setprecision(6)
610	                  << npv7 << std::endl;
611	        
612	
613	        std::cout << "\nThis is not too far from the GSR price." << std::endl;
614	
615	        std::cout << "\nMore interesting is the question how well the Markov"
616	                  << "\nmodel did its job to match our input smile. For this"
617	                  << "\nwe look at the underlying npv under the Markov model"
618	                  << std::endl;
619	
620	        std::cout << "\nFloat swap NPV (Markov) = " << std::setprecision(6)
621	                  << swaption4->result<Real>("underlyingValue") << std::endl;
622	
623	        std::cout << "\nThis is closer to our terminal swap rate model price."
624	                     "\nA perfect match is not expected anyway, because the"
625	                     "\ndynamics of the underlying rate in the linear"
626	                     "\nmodel is different from the Markov model, of"
627	                     "\ncourse." << std::endl;
628	
629	        std::cout << "\nThe Markov model can not only calibrate to the"
630	                     "\nunderlying smile, but has at the same time a"
631	                     "\nsigma function (similar to the GSR model) which"
632	                     "\ncan be used to calibrate to a second instrument"
633	                     "\nset. We do this here to calibrate to our coterminal"
634	                     "\nATM swaptions from above." << std::endl;
635	
636	        std::cout << "\nThis is a computationally demanding task, so"
637	                     "\ndepending on your machine, this may take a"
638	                     "\nwhile now..." << std::endl;
639	
640	        for (Size i = 0; i < basket.size(); ++i)
641	            basket[i]->setPricingEngine(swaptionEngineMarkov);
642	
643	        
644	        markov->calibrate(basket, method, ec);
645	        
646	
647	        printModelCalibration(basket, markov->volatility());
648	        
649	
650	        std::cout << "\nNow let's have a look again at the underlying pricing."
651	                     "\nIt shouldn't have changed much, because the underlying"
652	                     "\nsmile is still matched." << std::endl;
653	
654	        
655	        Real npv8 = swaption4->result<Real>("underlyingValue");
656	        
657	        std::cout << "\nFloat swap NPV (Markov) = " << std::setprecision(6)
658	                  << npv8 << std::endl;
659	        
660	
661	        std::cout << "\nThis is close to the previous value as expected."
662	                  << std::endl;
663	
664	        std::cout << "\nAs a final remark we note that the calibration to"
665	                  << "\ncoterminal swaptions is not particularly reasonable"
666	                  << "\nhere, because the european call rights are not"
667	                  << "\nwell represented by these swaptions."
668	                  << "\nSecondly, our CMS swaption is sensitive to the"
669	                  << "\ncorrelation between the 10y swap rate and the"
670	                  << "\nEuribor 6M rate. Since the Markov model is one factor"
671	                  << "\nit will most probably underestimate the market value"
672	                  << "\nby construction." << std::endl;
673	
674	        std::cout << "\nThat was it. Thank you for running this demo. Bye."
675	                  << std::endl;
676	
677	    } catch (const QuantLib::Error& e) {
678	        std::cout << "terminated with a ql exception: " << e.what()
679	                  << std::endl;
680	        return 1;
681	    } catch (const std::exception& e) {
682	        std::cout << "terminated with a general exception: " << e.what()
683	                  << std::endl;
684	        return 1;
685	    }
686	}
687