C++

CDS

/*
 CDS
*/

/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */


#include <ql/quantlib.hpp>

#include <boost/timer.hpp>
#include <iostream>
#include <iomanip>

using namespace std;
using namespace QuantLib;

#ifdef BOOST_MSVC
#  ifdef QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERN
#    include <ql/auto_link.hpp>
#    define BOOST_LIB_NAME boost_system
#    include <boost/config/auto_link.hpp>
#    undef BOOST_LIB_NAME
#    define BOOST_LIB_NAME boost_thread
#    include <boost/config/auto_link.hpp>
#    undef BOOST_LIB_NAME
#  endif
#endif


#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 SpreadCdsHelper(
                              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;
        Handle<DefaultProbabilityTermStructure> probability(hazardRateStructure);
        boost::shared_ptr<PricingEngine> engine(
                  new MidPointCdsEngine(probability, recovery_rate, tsCurve));

        Schedule cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[0])
                          .withFrequency(Quarterly)
                          .withCalendar(calendar)
                          .withTerminationDateConvention(Unadjusted)
                          .withRule(DateGeneration::TwentiethIMM);
        CreditDefaultSwap cds_3m(Protection::Seller,
                                 nominal,
                                 quoted_spreads[0],
                                 cdsSchedule,
                                 Following,
                                 Actual365Fixed());

        cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[1])
                          .withFrequency(Quarterly)
                          .withCalendar(calendar)
                          .withTerminationDateConvention(Unadjusted)
                          .withRule(DateGeneration::TwentiethIMM);
        CreditDefaultSwap cds_6m(Protection::Seller,
                                 nominal,
                                 quoted_spreads[1],
                                 cdsSchedule,
                                 Following,
                                 Actual365Fixed());

        cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[2])
                          .withFrequency(Quarterly)
                          .withCalendar(calendar)
                          .withTerminationDateConvention(Unadjusted)
                          .withRule(DateGeneration::TwentiethIMM);
        CreditDefaultSwap cds_1y(Protection::Seller,
                                 nominal,
                                 quoted_spreads[2],
                                 cdsSchedule,
                                 Following,
                                 Actual365Fixed());

        cdsSchedule =
            MakeSchedule().from(todaysDate).to(maturities[3])
                          .withFrequency(Quarterly)
                          .withCalendar(calendar)
                          .withTerminationDateConvention(Unadjusted)
                          .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) {
        cerr << e.what() << endl;
        return 1;
    } catch (...) {
        cerr << "unknown error" << endl;
        return 1;
    }
}