C++ code taken from Bonds.cpp
and slightly amended:
#include <ql/quantlib.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <iomanip>
using namespace QuantLib;
int main(int, char* []) {
try {
// Just a couple of parameters
Calendar calendar = TARGET();
Date settlementDate(18, September, 2008);
settlementDate = calendar.adjust(settlementDate);
Integer fixingDays = 3;
Natural settlementDays = 3;
Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);
Settings::instance().evaluationDate() = todaysDate;
/* Now let's introduce two curves: the first one is a swap curve built from
deposits and IRS, the second one is a credit spread curve which should be
added to the former one to get a proper yield curve */
// Swap curve
DayCounter termStructureDayCounter = ActualActual(ActualActual::ISDA);
double tolerance = 1.0e-5;
// Deposits
Rate d1wQuote = 0.043375;
Rate d1mQuote = 0.031875;
Rate d3mQuote = 0.0320375;
Rate d6mQuote = 0.03385;
Rate d9mQuote = 0.0338125;
Rate d1yQuote = 0.0335125;
boost::shared_ptr<Quote> d1wRate(new SimpleQuote(d1wQuote));
boost::shared_ptr<Quote> d1mRate(new SimpleQuote(d1mQuote));
boost::shared_ptr<Quote> d3mRate(new SimpleQuote(d3mQuote));
boost::shared_ptr<Quote> d6mRate(new SimpleQuote(d6mQuote));
boost::shared_ptr<Quote> d9mRate(new SimpleQuote(d9mQuote));
boost::shared_ptr<Quote> d1yRate(new SimpleQuote(d1yQuote));
// IRS
Rate s2yQuote = 0.0295;
Rate s3yQuote = 0.0323;
Rate s5yQuote = 0.0359;
Rate s10yQuote = 0.0412;
Rate s15yQuote = 0.0433;
boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote));
boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote));
boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote));
boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote));
boost::shared_ptr<Quote> s15yRate(new SimpleQuote(s15yQuote));
// Rate Helper
// Deposits
DayCounter depositDayCounter = Actual360();
boost::shared_ptr<RateHelper> d1w(new DepositRateHelper(
Handle<Quote>(d1wRate),
1*Weeks, fixingDays,
calendar, ModifiedFollowing,
true, depositDayCounter));
boost::shared_ptr<RateHelper> d1m(new DepositRateHelper(
Handle<Quote>(d1mRate),
1*Months, fixingDays,
calendar, ModifiedFollowing,
true, depositDayCounter));
boost::shared_ptr<RateHelper> d3m(new DepositRateHelper(
Handle<Quote>(d3mRate),
3*Months, fixingDays,
calendar, ModifiedFollowing,
true, depositDayCounter));
boost::shared_ptr<RateHelper> d6m(new DepositRateHelper(
Handle<Quote>(d6mRate),
6*Months, fixingDays,
calendar, ModifiedFollowing,
true, depositDayCounter));
boost::shared_ptr<RateHelper> d9m(new DepositRateHelper(
Handle<Quote>(d9mRate),
9*Months, fixingDays,
calendar, ModifiedFollowing,
true, depositDayCounter));
boost::shared_ptr<RateHelper> d1y(new DepositRateHelper(
Handle<Quote>(d1yRate),
1*Years, fixingDays,
calendar, ModifiedFollowing,
true, depositDayCounter));
// Setup IRS
Frequency swFixedLegFrequency = Annual;
BusinessDayConvention swFixedLegConvention = Unadjusted;
DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European);
boost::shared_ptr<IborIndex> swFloatingLegIndex(new Euribor6M);
const Period forwardStart(1*Days);
boost::shared_ptr<RateHelper> s2y(new SwapRateHelper(
Handle<Quote>(s2yRate), 2*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> s3y(new SwapRateHelper(
Handle<Quote>(s3yRate), 3*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> s5y(new SwapRateHelper(
Handle<Quote>(s5yRate), 5*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> s10y(new SwapRateHelper(
Handle<Quote>(s10yRate), 10*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> s15y(new SwapRateHelper(
Handle<Quote>(s15yRate), 15*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
// A depo-swap curve
std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments;
depoSwapInstruments.push_back(d1w);
depoSwapInstruments.push_back(d1m);
depoSwapInstruments.push_back(d3m);
depoSwapInstruments.push_back(d6m);
depoSwapInstruments.push_back(d9m);
depoSwapInstruments.push_back(d1y);
depoSwapInstruments.push_back(s2y);
depoSwapInstruments.push_back(s3y);
depoSwapInstruments.push_back(s5y);
depoSwapInstruments.push_back(s10y);
depoSwapInstruments.push_back(s15y);
boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(
new PiecewiseYieldCurve<Discount,LogLinear>(
settlementDate, depoSwapInstruments,
termStructureDayCounter,
tolerance));
return 0;
} catch (std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "unknown error" << std::endl;
return 1;
}
}
If I'm not wrong, so far we've been obtaining a kind of risk free discount curve.
Now let me to introduce an additional credit spread curve in the form of an object handled by RateHelper
(kinda snippet to be inserted after the depo-swap curve of the code above):
...
Rate d1ySpread = 0.013;
Rate d2ySpread = 0.011;
Rate d3ySpread = 0.022;
Rate d6ySpread = 0.0238;
Rate d9ySpread = 0.0238;
Rate d10ySpread = 0.0239;
boost::shared_ptr<Quote> d1ySpreadRate(new SimpleQuote(d1ySpread));
boost::shared_ptr<Quote> d2ySpreadRate(new SimpleQuote(d2ySpread));
boost::shared_ptr<Quote> d3ySpreadRate(new SimpleQuote(d3ySpread));
boost::shared_ptr<Quote> d6ySpreadRate(new SimpleQuote(d6ySpread));
boost::shared_ptr<Quote> d9ySpreadRate(new SimpleQuote(d9ySpread));
boost::shared_ptr<Quote> d10ySpreadRate(new SimpleQuote(d10ySpread));
boost::shared_ptr<RateHelper> credit1y(new SwapRateHelper(
Handle<Quote>(d1ySpreadRate), 1*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> credit2y(new SwapRateHelper(
Handle<Quote>(d2ySpreadRate), 2*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> credit3y(new SwapRateHelper(
Handle<Quote>(d3ySpreadRate), 3*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> credit6y(new SwapRateHelper(
Handle<Quote>(d6ySpreadRate), 6*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> credit9y(new SwapRateHelper(
Handle<Quote>(d9ySpreadRate), 9*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
boost::shared_ptr<RateHelper> credit10y(new SwapRateHelper(
Handle<Quote>(d10ySpreadRate), 10*Years,
calendar, swFixedLegFrequency,
swFixedLegConvention, swFixedLegDayCounter,
swFloatingLegIndex, Handle<Quote>(),forwardStart));
std::vector<boost::shared_ptr<RateHelper> > creditInstruments;
creditInstruments.push_back(credit1y);
creditInstruments.push_back(credit2y);
creditInstruments.push_back(credit3y);
creditInstruments.push_back(credit6y);
creditInstruments.push_back(credit9y);
creditInstruments.push_back(credit10y);
boost::shared_ptr<YieldTermStructure> creditTermStructure(
new PiecewiseYieldCurve<Discount,LogLinear>(
settlementDate, creditInstruments,
termStructureDayCounter,
tolerance));
...
The object creditTermStructure
could represent, as instance, a CDS spread curve, or such a term structure.
Having both the depoSwapTermStructure
and the creditTermStructure
built by the code above, I would like to produce a new object of class YieldTermStructure
by summing depoSwapTermStructure
and creditTermStructure
taking into account the misaligned time knots, that is, the code must sum the rates by the appropriate tenors (1Y depo-swap + 1Y credit spread, 2Y depo-swap + 2Y credit spread... and so on. As of the lacking credit spread maturities, such as 18Y, it should be interpolate known knots).
How is it possible to do such a thing using QuantLib?