CDS.cpp
This example bootstraps a default-probability curve over a number of CDS and reprices them.
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2008 Jose Aparicio This file is part of QuantLib, a free-software/open-source library for financial quantitative analysts and developers - http://quantlib.org/ QuantLib is free software: you can redistribute it and/or modify it under the terms of the QuantLib license. You should have received a copy of the license along with this program; if not, please email <quantlib-dev@lists.sf.net>. The license is also available online at <http://quantlib.org/license.shtml>. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ #include <ql/quantlib.hpp> #include <boost/timer.hpp> #include <iostream> #include <iomanip> using namespace std; using namespace QuantLib; #if defined(QL_ENABLE_SESSIONS) namespace QuantLib { Integer sessionId() { return 0; } } #endif int main(int, char* []) { try { boost::timer timer; std::cout << std::endl; /********************* *** MARKET DATA *** *********************/ Calendar calendar = TARGET(); Date todaysDate(15, May, 2007); // must be a business day todaysDate = calendar.adjust(todaysDate); Settings::instance().evaluationDate() = todaysDate; // dummy curve boost::shared_ptr<Quote> flatRate(new SimpleQuote(0.01)); Handle<YieldTermStructure> tsCurve( boost::shared_ptr<FlatForward>( new FlatForward(todaysDate, Handle<Quote>(flatRate), Actual365Fixed()))); /* In Lehmans Brothers "guide to exotic credit derivatives" p. 32 there's a simple case, zero flat curve with a flat CDS curve with constant market spreads of 150 bp and RR = 50% corresponds to a flat 3% hazard rate. The implied 1-year survival probability is 97.04% and the 2-years is 94.18% */ // market Real recovery_rate = 0.5; Real quoted_spreads[] = { 0.0150, 0.0150, 0.0150, 0.0150 }; vector<Period> tenors; tenors.push_back(3*Months); tenors.push_back(6*Months); tenors.push_back(1*Years); tenors.push_back(2*Years); vector<Date> maturities; for (Size i=0; i<4; i++) { maturities.push_back(calendar.adjust(todaysDate + tenors[i], Following)); } std::vector<boost::shared_ptr<DefaultProbabilityHelper> > instruments; for (Size i=0; i<4; i++) { instruments.push_back(boost::shared_ptr<DefaultProbabilityHelper>( new CdsHelper(Handle<Quote>(boost::shared_ptr<Quote>( new SimpleQuote(quoted_spreads[i]))), tenors[i], 0, calendar, Quarterly, Following, DateGeneration::TwentiethIMM, Actual365Fixed(), recovery_rate, tsCurve))); } // Bootstrap hazard rates boost::shared_ptr<PiecewiseDefaultCurve<HazardRate, BackwardFlat> > hazardRateStructure( new PiecewiseDefaultCurve<HazardRate, BackwardFlat>( todaysDate, instruments, Actual365Fixed())); vector<pair<Date, Real> > hr_curve_data = hazardRateStructure->nodes(); cout << "Calibrated hazard rate values: " << endl ; for (Size i=0; i<hr_curve_data.size(); i++) { cout << "hazard rate on " << hr_curve_data[i].first << " is " << hr_curve_data[i].second << endl; } cout << endl; cout << "Some survival probability values: " << endl ; cout << "1Y survival probability: " << io::percent(hazardRateStructure->survivalProbability( todaysDate + 1*Years)) << endl << " expected: " << io::percent(0.9704) << endl; cout << "2Y survival probability: " << io::percent(hazardRateStructure->survivalProbability( todaysDate + 2*Years)) << endl << " expected: " << io::percent(0.9418) << endl; cout << endl << endl; // reprice instruments Real nominal = 1000000.0; Issuer issuer(Handle<DefaultProbabilityTermStructure>( hazardRateStructure), recovery_rate); boost::shared_ptr<PricingEngine> engine( new MidPointCdsEngine(issuer, tsCurve)); Schedule cdsSchedule = MakeSchedule(todaysDate, maturities[0], Period(Quarterly), calendar, Following) .withRule(DateGeneration::TwentiethIMM); CreditDefaultSwap cds_3m(Protection::Seller, nominal, quoted_spreads[0], cdsSchedule, Following, Actual365Fixed()); cdsSchedule = MakeSchedule(todaysDate, maturities[1], Period(Quarterly), calendar, Following) .withRule(DateGeneration::TwentiethIMM); CreditDefaultSwap cds_6m(Protection::Seller, nominal, quoted_spreads[1], cdsSchedule, Following, Actual365Fixed()); cdsSchedule = MakeSchedule(todaysDate, maturities[2], Period(Quarterly), calendar, Following) .withRule(DateGeneration::TwentiethIMM); CreditDefaultSwap cds_1y(Protection::Seller, nominal, quoted_spreads[2], cdsSchedule, Following, Actual365Fixed()); cdsSchedule = MakeSchedule(todaysDate, maturities[3], Period(Quarterly), calendar, Following) .withRule(DateGeneration::TwentiethIMM); CreditDefaultSwap cds_2y(Protection::Seller, nominal, quoted_spreads[3], cdsSchedule, Following, Actual365Fixed()); cds_3m.setPricingEngine(engine); cds_6m.setPricingEngine(engine); cds_1y.setPricingEngine(engine); cds_2y.setPricingEngine(engine); cout << "Repricing of quoted CDSs employed for calibration: " << endl; cout << "3M fair spread: " << io::rate(cds_3m.fairSpread()) << endl << " NPV: " << cds_3m.NPV() << endl << " default leg: " << cds_3m.defaultLegNPV() << endl << " coupon leg: " << cds_3m.couponLegNPV() << endl << endl; cout << "6M fair spread: " << io::rate(cds_6m.fairSpread()) << endl << " NPV: " << cds_6m.NPV() << endl << " default leg: " << cds_6m.defaultLegNPV() << endl << " coupon leg: " << cds_6m.couponLegNPV() << endl << endl; cout << "1Y fair spread: " << io::rate(cds_1y.fairSpread()) << endl << " NPV: " << cds_1y.NPV() << endl << " default leg: " << cds_1y.defaultLegNPV() << endl << " coupon leg: " << cds_1y.couponLegNPV() << endl << endl; cout << "2Y fair spread: " << io::rate(cds_2y.fairSpread()) << endl << " NPV: " << cds_2y.NPV() << endl << " default leg: " << cds_2y.defaultLegNPV() << endl << " coupon leg: " << cds_2y.couponLegNPV() << endl << endl; cout << endl << endl; Real seconds = timer.elapsed(); Integer hours = Integer(seconds/3600); seconds -= hours * 3600; Integer minutes = Integer(seconds/60); seconds -= minutes * 60; cout << "Run completed in "; if (hours > 0) cout << hours << " h "; if (hours > 0 || minutes > 0) cout << minutes << " m "; cout << fixed << setprecision(0) << seconds << " s" << endl; return 0; } catch (exception& e) { cout << e.what() << endl; return 1; } catch (...) { cout << "unknown error" << endl; return 1; } }