1	/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2	
3	/*
4	 Copyright (C) 2008 Jose Aparicio
5	 Copyright (C) 2014 Peter Caspers
6	
7	 This file is part of QuantLib, a free-software/open-source library
8	 for financial quantitative analysts and developers - http://quantlib.org/
9	
10	 QuantLib is free software: you can redistribute it and/or modify it
11	 under the terms of the QuantLib license.  You should have received a
12	 copy of the license along with this program; if not, please email
13	 <quantlib-dev@lists.sf.net>. The license is also available online at
14	 <http://quantlib.org/license.shtml>.
15	
16	 This program is distributed in the hope that it will be useful, but WITHOUT
17	 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18	 FOR A PARTICULAR PURPOSE.  See the license for more details.
19	*/
20	
21	#include <ql/qldefines.hpp>
22	#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
23	#  include <ql/auto_link.hpp>
24	#endif
25	#include <ql/cashflows/fixedratecoupon.hpp>
26	#include <ql/cashflows/iborcoupon.hpp>
27	#include <ql/instruments/creditdefaultswap.hpp>
28	#include <ql/indexes/ibor/euribor.hpp>
29	#include <ql/pricingengines/credit/midpointcdsengine.hpp>
30	#include <ql/pricingengines/credit/isdacdsengine.hpp>
31	#include <ql/termstructures/credit/piecewisedefaultcurve.hpp>
32	#include <ql/termstructures/credit/defaultprobabilityhelpers.hpp>
33	#include <ql/termstructures/credit/flathazardrate.hpp>
34	#include <ql/termstructures/yield/flatforward.hpp>
35	#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
36	#include <ql/termstructures/yield/ratehelpers.hpp>
37	#include <ql/math/interpolations/backwardflatinterpolation.hpp>
38	#include <ql/time/calendars/target.hpp>
39	#include <ql/time/calendars/weekendsonly.hpp>
40	#include <ql/time/daycounters/thirty360.hpp>
41	#include <ql/time/daycounters/actual365fixed.hpp>
42	#include <ql/time/daycounters/actual360.hpp>
43	#include <ql/currencies/europe.hpp>
44	#include <ql/quotes/simplequote.hpp>
45	
46	#include <iostream>
47	#include <iomanip>
48	
49	using namespace std;
50	using namespace QuantLib;
51	
52	void example01() {
53	
54	    std::cout << std::endl;
55	
56	    /*********************
57	     ***  MARKET DATA  ***
58	     *********************/
59	
60	    Calendar calendar = TARGET();
61	    Date todaysDate(15, May, 2007);
62	    // must be a business day
63	    todaysDate = calendar.adjust(todaysDate);
64	
65	    Settings::instance().evaluationDate() = todaysDate;
66	
67	    // dummy curve
68	    auto flatRate = ext::make_shared<SimpleQuote>(0.01);
69	    Handle<YieldTermStructure> tsCurve(
70	        ext::make_shared<FlatForward>(
71	            todaysDate, Handle<Quote>(flatRate), Actual365Fixed()));
72	
73	    /*
74	      In Lehmans Brothers "guide to exotic credit derivatives"
75	      p. 32 there's a simple case, zero flat curve with a flat CDS
76	      curve with constant market spreads of 150 bp and RR = 50%
77	      corresponds to a flat 3% hazard rate. The implied 1-year
78	      survival probability is 97.04% and the 2-years is 94.18%
79	    */
80	
81	    // market
82	    Natural settlementDays = 1;
83	    Real recovery_rate = 0.5;
84	    Real quoted_spreads[] = { 0.0150, 0.0150, 0.0150, 0.0150 };
85	    vector<Period> tenors;
86	    tenors.push_back(3 * Months);
87	    tenors.push_back(6 * Months);
88	    tenors.push_back(1 * Years);
89	    tenors.push_back(2 * Years);
90	
91	    Date settlementDate = calendar.advance(todaysDate, settlementDays, Days);
92	    vector<Date> maturities;
93	    for (Size i = 0; i < 4; i++) {
94	        maturities.push_back(
95	            calendar.adjust(settlementDate + tenors[i], Following));
96	    }
97	
98	    std::vector<ext::shared_ptr<DefaultProbabilityHelper>> instruments;
99	    for (Size i = 0; i < 4; i++) {
100	        instruments.push_back(ext::make_shared<SpreadCdsHelper>(
101	                                Handle<Quote>(ext::make_shared<SimpleQuote>(quoted_spreads[i])),
102	                                tenors[i], settlementDays, calendar, Quarterly, Following,
103	                                DateGeneration::TwentiethIMM, Actual365Fixed(),
104	                                recovery_rate, tsCurve));
105	    }
106	
107	    // Bootstrap hazard rates
108	    auto hazardRateStructure = ext::make_shared<PiecewiseDefaultCurve<HazardRate, BackwardFlat>>(
109	        todaysDate, instruments, Actual365Fixed());
110	    vector<pair<Date, Real>> hr_curve_data = hazardRateStructure->nodes();
111	
112	    cout << "Calibrated hazard rate values: " << endl;
113	    for (auto& i : hr_curve_data) {
114	        cout << "hazard rate on " << i.first << " is " << i.second << endl;
115	    }
116	    cout << endl;
117	
118	    cout << "Some survival probability values: " << endl;
119	    cout << "1Y survival probability: "
120	         << io::percent(hazardRateStructure->survivalProbability(todaysDate +
121	                                                                 1 * Years))
122	         << endl << "               expected: " << io::percent(0.9704) << endl;
123	    cout << "2Y survival probability: "
124	         << io::percent(hazardRateStructure->survivalProbability(todaysDate +
125	                                                                 2 * Years))
126	         << endl << "               expected: " << io::percent(0.9418) << endl;
127	
128	    cout << endl << endl;
129	
130	    // reprice instruments
131	    Real nominal = 1000000.0;
132	    Handle<DefaultProbabilityTermStructure> probability(hazardRateStructure);
133	    auto engine = ext::make_shared<MidPointCdsEngine>(probability, recovery_rate, tsCurve);
134	
135	    Schedule cdsSchedule = MakeSchedule()
136	                               .from(settlementDate)
137	                               .to(maturities[0])
138	                               .withFrequency(Quarterly)
139	                               .withCalendar(calendar)
140	                               .withTerminationDateConvention(Unadjusted)
141	                               .withRule(DateGeneration::TwentiethIMM);
142	    CreditDefaultSwap cds_3m(Protection::Seller, nominal, quoted_spreads[0],
143	                             cdsSchedule, Following, Actual365Fixed());
144	
145	    cdsSchedule = MakeSchedule()
146	                      .from(settlementDate)
147	                      .to(maturities[1])
148	                      .withFrequency(Quarterly)
149	                      .withCalendar(calendar)
150	                      .withTerminationDateConvention(Unadjusted)
151	                      .withRule(DateGeneration::TwentiethIMM);
152	    CreditDefaultSwap cds_6m(Protection::Seller, nominal, quoted_spreads[1],
153	                             cdsSchedule, Following, Actual365Fixed());
154	
155	    cdsSchedule = MakeSchedule()
156	                      .from(settlementDate)
157	                      .to(maturities[2])
158	                      .withFrequency(Quarterly)
159	                      .withCalendar(calendar)
160	                      .withTerminationDateConvention(Unadjusted)
161	                      .withRule(DateGeneration::TwentiethIMM);
162	    CreditDefaultSwap cds_1y(Protection::Seller, nominal, quoted_spreads[2],
163	                             cdsSchedule, Following, Actual365Fixed());
164	
165	    cdsSchedule = MakeSchedule()
166	                      .from(settlementDate)
167	                      .to(maturities[3])
168	                      .withFrequency(Quarterly)
169	                      .withCalendar(calendar)
170	                      .withTerminationDateConvention(Unadjusted)
171	                      .withRule(DateGeneration::TwentiethIMM);
172	    CreditDefaultSwap cds_2y(Protection::Seller, nominal, quoted_spreads[3],
173	                             cdsSchedule, Following, Actual365Fixed());
174	
175	    cds_3m.setPricingEngine(engine);
176	    cds_6m.setPricingEngine(engine);
177	    cds_1y.setPricingEngine(engine);
178	    cds_2y.setPricingEngine(engine);
179	
180	    cout << "Repricing of quoted CDSs employed for calibration: " << endl;
181	    cout << "3M fair spread: " << io::rate(cds_3m.fairSpread()) << endl
182	         << "   NPV:         " << cds_3m.NPV() << endl
183	         << "   default leg: " << cds_3m.defaultLegNPV() << endl
184	         << "   coupon leg:  " << cds_3m.couponLegNPV() << endl << endl;
185	
186	    cout << "6M fair spread: " << io::rate(cds_6m.fairSpread()) << endl
187	         << "   NPV:         " << cds_6m.NPV() << endl
188	         << "   default leg: " << cds_6m.defaultLegNPV() << endl
189	         << "   coupon leg:  " << cds_6m.couponLegNPV() << endl << endl;
190	
191	    cout << "1Y fair spread: " << io::rate(cds_1y.fairSpread()) << endl
192	         << "   NPV:         " << cds_1y.NPV() << endl
193	         << "   default leg: " << cds_1y.defaultLegNPV() << endl
194	         << "   coupon leg:  " << cds_1y.couponLegNPV() << endl << endl;
195	
196	    cout << "2Y fair spread: " << io::rate(cds_2y.fairSpread()) << endl
197	         << "   NPV:         " << cds_2y.NPV() << endl
198	         << "   default leg: " << cds_2y.defaultLegNPV() << endl
199	         << "   coupon leg:  " << cds_2y.couponLegNPV() << endl << endl;
200	
201	    cout << endl << endl;
202	
203	}
204	
205	void example02() {
206	
207	Date todaysDate(25, September, 2014);
208	Settings::instance().evaluationDate() = todaysDate;
209	
210	Date termDate = TARGET().adjust(todaysDate+Period(2*Years), Following);
211	
212	Schedule cdsSchedule =
213	    MakeSchedule().from(todaysDate).to(termDate)
214	                  .withFrequency(Quarterly)
215	                  .withCalendar(WeekendsOnly())
216	                  .withConvention(ModifiedFollowing)
217	                  .withTerminationDateConvention(ModifiedFollowing)
218	                  .withRule(DateGeneration::CDS);
219	
220	std::copy(cdsSchedule.begin(), cdsSchedule.end(),
221	    std::ostream_iterator<Date>(cout, "\n"));
222	
223	    Date evaluationDate = Date(21, October, 2014);
224	
225	    Settings::instance().evaluationDate() = evaluationDate;
226	
227	    IborCoupon::Settings::instance().createAtParCoupons();
228	
229	    // set up ISDA IR curve helpers
230	
231	    auto dp1m = ext::make_shared<DepositRateHelper>(0.000060, 1 * Months, 2,
232	                                              TARGET(), ModifiedFollowing,
233	                                              false, Actual360());
234	    auto dp2m = ext::make_shared<DepositRateHelper>(0.000450, 2 * Months, 2,
235	                                              TARGET(), ModifiedFollowing,
236	                                              false, Actual360());
237	    auto dp3m = ext::make_shared<DepositRateHelper>(0.000810, 3 * Months, 2,
238	                                              TARGET(), ModifiedFollowing,
239	                                              false, Actual360());
240	    auto dp6m = ext::make_shared<DepositRateHelper>(0.001840, 6 * Months, 2,
241	                                              TARGET(), ModifiedFollowing,
242	                                              false, Actual360());
243	    auto dp9m = ext::make_shared<DepositRateHelper>(0.002560, 9 * Months, 2,
244	                                              TARGET(), ModifiedFollowing,
245	                                              false, Actual360());
246	    auto dp12m = ext::make_shared<DepositRateHelper>(0.003370, 12 * Months, 2,
247	                                              TARGET(), ModifiedFollowing,
248	                                              false, Actual360());
249	
250	    // intentionally we do not provide a fixing for the euribor index used for
251	    // bootstrapping in order to be compliant with the ISDA specification
252	
253	    auto euribor6m = ext::make_shared<Euribor>(Euribor(6 * Months));
254	
255	    DayCounter thirty360 = Thirty360(Thirty360::BondBasis);
256	
257	    auto sw2y = ext::make_shared<SwapRateHelper>(
258	        0.002230, 2 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
259	        euribor6m);
260	    auto sw3y = ext::make_shared<SwapRateHelper>(
261	        0.002760, 3 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
262	        euribor6m);
263	    auto sw4y = ext::make_shared<SwapRateHelper>(
264	        0.003530, 4 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
265	        euribor6m);
266	    auto sw5y = ext::make_shared<SwapRateHelper>(
267	        0.004520, 5 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
268	        euribor6m);
269	    auto sw6y = ext::make_shared<SwapRateHelper>(
270	        0.005720, 6 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
271	        euribor6m);
272	    auto sw7y = ext::make_shared<SwapRateHelper>(
273	        0.007050, 7 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
274	        euribor6m);
275	    auto sw8y = ext::make_shared<SwapRateHelper>(
276	        0.008420, 8 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
277	        euribor6m);
278	    auto sw9y = ext::make_shared<SwapRateHelper>(
279	        0.009720, 9 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
280	        euribor6m);
281	    auto sw10y = ext::make_shared<SwapRateHelper>(
282	        0.010900, 10 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
283	        euribor6m);
284	    auto sw12y = ext::make_shared<SwapRateHelper>(
285	        0.012870, 12 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
286	        euribor6m);
287	    auto sw15y = ext::make_shared<SwapRateHelper>(
288	        0.014970, 15 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
289	        euribor6m);
290	    auto sw20y = ext::make_shared<SwapRateHelper>(
291	        0.017000, 20 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
292	        euribor6m);
293	    auto sw30y = ext::make_shared<SwapRateHelper>(
294	        0.018210, 30 * Years, TARGET(), Annual, ModifiedFollowing, thirty360,
295	        euribor6m);
296	
297	    std::vector<ext::shared_ptr<RateHelper>> isdaRateHelper;
298	
299	    isdaRateHelper.push_back(dp1m);
300	    isdaRateHelper.push_back(dp2m);
301	    isdaRateHelper.push_back(dp3m);
302	    isdaRateHelper.push_back(dp6m);
303	    isdaRateHelper.push_back(dp9m);
304	    isdaRateHelper.push_back(dp12m);
305	    isdaRateHelper.push_back(sw2y);
306	    isdaRateHelper.push_back(sw3y);
307	    isdaRateHelper.push_back(sw4y);
308	    isdaRateHelper.push_back(sw5y);
309	    isdaRateHelper.push_back(sw6y);
310	    isdaRateHelper.push_back(sw7y);
311	    isdaRateHelper.push_back(sw8y);
312	    isdaRateHelper.push_back(sw9y);
313	    isdaRateHelper.push_back(sw10y);
314	    isdaRateHelper.push_back(sw12y);
315	    isdaRateHelper.push_back(sw15y);
316	    isdaRateHelper.push_back(sw20y);
317	    isdaRateHelper.push_back(sw30y);
318	
319	    Handle<YieldTermStructure> rateTs(
320	        ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear>>(
321	            0, WeekendsOnly(), isdaRateHelper, Actual365Fixed()));
322	    rateTs->enableExtrapolation();
323	
324	    // output rate curve
325	    std::cout << "ISDA rate curve: " << std::endl;
326	    for (auto& i : isdaRateHelper) {
327	        Date d = i->latestDate();
328	        std::cout << d << "\t" << setprecision(6) <<
329	            rateTs->zeroRate(d,Actual365Fixed(),Continuous).rate() << "\t" <<
330	            rateTs->discount(d) << std::endl;
331	    }
332	
333	    // build reference credit curve (flat)
334	    auto defaultTs0 = ext::make_shared<FlatHazardRate>(0, WeekendsOnly(), 0.016739207493630, Actual365Fixed());
335	
336	    // reference CDS
337	    Schedule sched( Date(22,September,2014), Date(20,December,2019), 3*Months,
338	            WeekendsOnly(), Following, Unadjusted, DateGeneration::CDS, false, Date(), Date() );
339	    auto trade = ext::make_shared<CreditDefaultSwap>(
340	            Protection::Buyer, 100000000.0, 0.01, sched,
341	                                  Following, Actual360(), true, true,
342	                                  Date(22,October,2014), ext::shared_ptr<Claim>(),
343	                                  Actual360(true), true);
344	
345	    auto cp = ext::dynamic_pointer_cast<FixedRateCoupon>(trade->coupons()[0]);
346	    std::cout << "first period = " << cp->accrualStartDate() << " to " << cp->accrualEndDate() <<
347	        " accrued amount = " << cp->accruedAmount(Date(24,October,2014)) << std::endl;
348	
349	    // price with isda engine
350	    auto engine = ext::make_shared<IsdaCdsEngine>(
351	            Handle<DefaultProbabilityTermStructure>(defaultTs0), 0.4, rateTs,
352	            false, IsdaCdsEngine::Taylor, IsdaCdsEngine::NoBias, IsdaCdsEngine::Piecewise);
353	
354	    trade->setPricingEngine(engine);
355	
356	    std::cout << "reference trade NPV = " << trade->NPV() << std::endl;
357	
358	
359	    // build credit curve with one cds
360	    std::vector<ext::shared_ptr<DefaultProbabilityHelper>> isdaCdsHelper;
361	
362	    auto cds5y = ext::make_shared<SpreadCdsHelper>(
363	        0.00672658551, 4 * Years + 6 * Months, 1, WeekendsOnly(), Quarterly,
364	        Following, DateGeneration::CDS, Actual360(), 0.4, rateTs, true, true,
365	        Date(), Actual360(true), true, CreditDefaultSwap::ISDA);
366	
367	    isdaCdsHelper.push_back(cds5y);
368	
369	    Handle<DefaultProbabilityTermStructure> defaultTs(ext::make_shared<
370	        PiecewiseDefaultCurve<SurvivalProbability, LogLinear>>(
371	        0, WeekendsOnly(), isdaCdsHelper, Actual365Fixed()));
372	
373	    std::cout << "ISDA credit curve: " << std::endl;
374	    for (auto& i : isdaCdsHelper) {
375	        Date d = i->latestDate();
376	        Real pd = defaultTs->defaultProbability(d);
377	        Real t = defaultTs->timeFromReference(d);
378	        std::cout << d << ";" << pd << ";" << 1.0 - pd << ";" <<
379	            -std::log(1.0-pd)/t << std::endl;
380	    }
381	
382	
383	    // // set up sample CDS trade
384	
385	    // auto trade =
386	    //     MakeCreditDefaultSwap(5 * Years, 0.03);
387	
388	    // // set up isda engine
389	
390	    // // auto isdaPricer =
391	    // //     ext::make_shared<IsdaCdsEngine>(
392	    // //         isdaCdsHelper, 0.4, isdaRateHelper);
393	    // auto isdaPricer =
394	    //     ext::make_shared<IsdaCdsEngine>(defaultTs,0.40,rateTs);
395	
396	    // // check the curves built by the engine
397	
398	    // Handle<YieldTermStructure> isdaYts = isdaPricer->isdaRateCurve();
399	    // Handle<DefaultProbabilityTermStructure> isdaCts = isdaPricer->isdaCreditCurve();
400	
401	    // std::cout << "isda rate 1m " << dp1m->latestDate() << " "
402	    //           << isdaYts->zeroRate(dp1m->latestDate(), Actual365Fixed(),
403	    //                                   Continuous) << std::endl;
404	    // std::cout << "isda rate 3m " << dp3m->latestDate() << " "
405	    //           << isdaYts->zeroRate(dp3m->latestDate(), Actual365Fixed(),
406	    //                                   Continuous) << std::endl;
407	    // std::cout << "isda rate 6m " << dp6m->latestDate() << " "
408	    //           << isdaYts->zeroRate(dp6m->latestDate(), Actual365Fixed(),
409	    //                                   Continuous) << std::endl;
410	
411	    // std::cout << "isda hazard 5y " << cds5y->latestDate() << " "
412	    //           << isdaCts->hazardRate(cds5y->latestDate()) << std::endl;
413	
414	    // // price the trade
415	
416	    // trade->setPricingEngine(isdaPricer);
417	
418	    // Real npv = trade->NPV();
419	
420	    // std::cout << "Pricing of example trade with ISDA engine:" << std::endl;
421	    // std::cout << "NPV = " << npv << std::endl;
422	
423	}
424	
425	void example03() {
426	
427	    // this is the example from Apdx E in pricing and risk management of CDS, OpenGamma
428	
429	    Date tradeDate(13,June,2011);
430	
431	    Settings::instance().evaluationDate() = tradeDate;
432	
433	    IborCoupon::Settings::instance().createAtParCoupons();
434	
435	    DayCounter actual360 = Actual360();
436	    DayCounter thirty360 = Thirty360(Thirty360::BondBasis);
437	
438	    auto dp1m = ext::make_shared<DepositRateHelper>(0.00445, 1 * Months, 2,
439	                                              WeekendsOnly(), ModifiedFollowing,
440	                                              false, actual360);
441	    auto dp2m = ext::make_shared<DepositRateHelper>(0.00949, 2 * Months, 2,
442	                                              WeekendsOnly(), ModifiedFollowing,
443	                                              false, actual360);
444	    auto dp3m = ext::make_shared<DepositRateHelper>(0.01234, 3 * Months, 2,
445	                                              WeekendsOnly(), ModifiedFollowing,
446	                                              false, actual360);
447	    auto dp6m = ext::make_shared<DepositRateHelper>(0.01776, 6 * Months, 2,
448	                                              WeekendsOnly(), ModifiedFollowing,
449	                                              false, actual360);
450	    auto dp9m = ext::make_shared<DepositRateHelper>(0.01935, 9 * Months, 2,
451	                                              WeekendsOnly(), ModifiedFollowing,
452	                                              false, actual360);
453	    auto dp1y = ext::make_shared<DepositRateHelper>(0.02084, 12 * Months, 2,
454	                                              WeekendsOnly(), ModifiedFollowing,
455	                                              false, actual360);
456	
457	    // this index is probably not important since we are not using
458	    // IborCoupon::Settings::instance().usingAtParCoupons() == false
459	    // - define it "isda compliant" anyway
460	    auto euribor6m = ext::make_shared<IborIndex>(
461	        "IsdaIbor", 6 * Months, 2, EURCurrency(), WeekendsOnly(),
462	        ModifiedFollowing, false, actual360);
463	
464	    auto sw2y = ext::make_shared<SwapRateHelper>(
465	        0.01652, 2 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
466	        euribor6m);
467	    auto sw3y = ext::make_shared<SwapRateHelper>(
468	        0.02018, 3 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
469	        euribor6m);
470	    auto sw4y = ext::make_shared<SwapRateHelper>(
471	        0.02303, 4 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
472	        euribor6m);
473	    auto sw5y = ext::make_shared<SwapRateHelper>(
474	        0.02525, 5 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
475	        euribor6m);
476	    auto sw6y = ext::make_shared<SwapRateHelper>(
477	        0.02696, 6 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
478	        euribor6m);
479	    auto sw7y = ext::make_shared<SwapRateHelper>(
480	        0.02825, 7 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
481	        euribor6m);
482	    auto sw8y = ext::make_shared<SwapRateHelper>(
483	        0.02931, 8 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
484	        euribor6m);
485	    auto sw9y = ext::make_shared<SwapRateHelper>(
486	        0.03017, 9 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
487	        euribor6m);
488	    auto sw10y = ext::make_shared<SwapRateHelper>(
489	        0.03092, 10 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
490	        euribor6m);
491	    auto sw11y = ext::make_shared<SwapRateHelper>(
492	        0.03160, 11 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
493	        euribor6m);
494	    auto sw12y = ext::make_shared<SwapRateHelper>(
495	        0.03231, 12 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
496	        euribor6m);
497	    auto sw15y = ext::make_shared<SwapRateHelper>(
498	        0.03367, 15 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
499	        euribor6m);
500	    auto sw20y = ext::make_shared<SwapRateHelper>(
501	        0.03419, 20 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
502	        euribor6m);
503	    auto sw25y = ext::make_shared<SwapRateHelper>(
504	        0.03411, 25 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
505	        euribor6m);
506	    auto sw30y = ext::make_shared<SwapRateHelper>(
507	        0.03412, 30 * Years, WeekendsOnly(), Annual, ModifiedFollowing, thirty360,
508	        euribor6m);
509	
510	    std::vector<ext::shared_ptr<RateHelper>> isdaYieldHelpers;
511	
512	    isdaYieldHelpers.push_back(dp1m);
513	    isdaYieldHelpers.push_back(dp2m);
514	    isdaYieldHelpers.push_back(dp3m);
515	    isdaYieldHelpers.push_back(dp6m);
516	    isdaYieldHelpers.push_back(dp9m);
517	    isdaYieldHelpers.push_back(dp1y);
518	    isdaYieldHelpers.push_back(sw2y);
519	    isdaYieldHelpers.push_back(sw3y);
520	    isdaYieldHelpers.push_back(sw4y);
521	    isdaYieldHelpers.push_back(sw5y);
522	    isdaYieldHelpers.push_back(sw6y);
523	    isdaYieldHelpers.push_back(sw7y);
524	    isdaYieldHelpers.push_back(sw8y);
525	    isdaYieldHelpers.push_back(sw9y);
526	    isdaYieldHelpers.push_back(sw10y);
527	    isdaYieldHelpers.push_back(sw11y);
528	    isdaYieldHelpers.push_back(sw12y);
529	    isdaYieldHelpers.push_back(sw15y);
530	    isdaYieldHelpers.push_back(sw20y);
531	    isdaYieldHelpers.push_back(sw25y);
532	    isdaYieldHelpers.push_back(sw30y);
533	
534	    // build yield curve
535	    Handle<YieldTermStructure> isdaYts = Handle<YieldTermStructure>(
536	            ext::make_shared<PiecewiseYieldCurve<Discount, LogLinear>>(
537	                0, WeekendsOnly(), isdaYieldHelpers, Actual365Fixed()));
538	    isdaYts->enableExtrapolation();
539	
540	
541	    CreditDefaultSwap::PricingModel model = CreditDefaultSwap::ISDA;
542	    auto cds6m = ext::make_shared<SpreadCdsHelper>(
543	        0.007927, 6 * Months, 1, WeekendsOnly(), Quarterly, Following,
544	        DateGeneration::CDS, Actual360(), 0.4, isdaYts, true, true, Date(),
545	        Actual360(true), true, model);
546	    auto cds1y = ext::make_shared<SpreadCdsHelper>(
547	        0.007927, 1 * Years, 1, WeekendsOnly(), Quarterly, Following,
548	        DateGeneration::CDS, Actual360(), 0.4, isdaYts, true, true, Date(),
549	        Actual360(true), true, model);
550	    auto cds3y = ext::make_shared<SpreadCdsHelper>(
551	        0.012239, 3 * Years, 1, WeekendsOnly(), Quarterly, Following,
552	        DateGeneration::CDS, Actual360(), 0.4, isdaYts, true, true, Date(),
553	        Actual360(true), true, model);
554	    auto cds5y = ext::make_shared<SpreadCdsHelper>(
555	        0.016979, 5 * Years, 1, WeekendsOnly(), Quarterly, Following,
556	        DateGeneration::CDS, Actual360(), 0.4, isdaYts, true, true, Date(),
557	        Actual360(true), true, model);
558	    auto cds7y = ext::make_shared<SpreadCdsHelper>(
559	        0.019271, 7 * Years, 1, WeekendsOnly(), Quarterly, Following,
560	        DateGeneration::CDS, Actual360(), 0.4, isdaYts, true, true, Date(),
561	        Actual360(true), true, model);
562	    auto cds10y = ext::make_shared<SpreadCdsHelper>(
563	        0.020860, 10 * Years, 1, WeekendsOnly(), Quarterly, Following,
564	        DateGeneration::CDS, Actual360(), 0.4, isdaYts, true, true, Date(),
565	        Actual360(true), true, model);
566	
567	    std::vector<ext::shared_ptr<DefaultProbabilityHelper>> isdaCdsHelpers;
568	
569	    isdaCdsHelpers.push_back(cds6m);
570	    isdaCdsHelpers.push_back(cds1y);
571	    isdaCdsHelpers.push_back(cds3y);
572	    isdaCdsHelpers.push_back(cds5y);
573	    isdaCdsHelpers.push_back(cds7y);
574	    isdaCdsHelpers.push_back(cds10y);
575	
576	    // build credit curve
577	    auto isdaCts =
578	    Handle<DefaultProbabilityTermStructure>(ext::make_shared<
579	        PiecewiseDefaultCurve<SurvivalProbability, LogLinear>>(
580	            0, WeekendsOnly(), isdaCdsHelpers, Actual365Fixed()));
581	
582	    // set up isda engine
583	    auto isdaPricer = ext::make_shared<IsdaCdsEngine>(isdaCts, 0.4, isdaYts);
584	
585	    // check the curves
586	    std::cout << "ISDA yield curve:" << std::endl;
587	    std::cout << "date;time;zeroyield" << std::endl;
588	    for (auto& isdaYieldHelper : isdaYieldHelpers) {
589	        Date d = isdaYieldHelper->latestDate();
590	        Real t = isdaYts->timeFromReference(d);
591	        std::cout << d << ";" << t << ";"
592	                  << isdaYts->zeroRate(d, Actual365Fixed(), Continuous).rate()
593	                  << std::endl;
594	    }
595	
596	    std::cout << "ISDA credit curve:" << std::endl;
597	    std::cout << "date;time;survivalprob" << std::endl;
598	    for (auto& isdaCdsHelper : isdaCdsHelpers) {
599	        Date d = isdaCdsHelper->latestDate();
600	        Real t = isdaCts->timeFromReference(d);
601	        std::cout << d << ";" << t << ";" << isdaCts->survivalProbability(d)
602	                  << std::endl;
603	    }
604	}
605	
606	
607	int main(int argc, char *argv[]) {
608	
609	    try {
610	        Size example = 0;
611	        if (argc == 2)
612	            example = std::atoi(argv[1]);
613	
614	        if (example == 0 || example == 1) {
615	            std::cout << "***** Running example #1 *****" << std::endl;
616	            example01();
617	        }
618	
619	        if (example == 0 || example == 2) {
620	            std::cout << "***** Running example #2 *****" << std::endl;
621	            example02();
622	        }
623	
624	        if (example == 0 || example == 3) {
625	            std::cout << "***** Running example #3 *****" << std::endl;
626	            example03();
627	        }
628	
629	        return 0;
630	    }
631	    catch (exception &e) {
632	        cerr << e.what() << endl;
633	        return 1;
634	    }
635	    catch (...) {
636	        cerr << "unknown error" << endl;
637	        return 1;
638	    }
639	}