Código C++ extraído de Bonds.cpp
y ligeramente modificado:
#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;
}
}
Si no me equivoco, hasta ahora hemos obtenido una especie de curva de descuento sin riesgo.
Ahora permítanme introducir una curva adicional de diferencial de crédito en forma de un objeto manejado por RateHelper
(un fragmento que se inserta después de la curva depo-swap del código anterior):
...
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));
...
El objeto creditTermStructure
podría representar, por ejemplo, una curva de diferencial de CDS, o una estructura de plazos de este tipo.
Teniendo tanto el depoSwapTermStructure
y el creditTermStructure
construido por el código anterior, me gustaría producir un nuevo objeto de clase YieldTermStructure
mediante la suma depoSwapTermStructure
y creditTermStructure
teniendo en cuenta los nudos temporales desalineados, es decir, el código debe sumar los tipos por los tenores adecuados (1Y depo-swap + 1Y credit spread, 2Y depo-swap + 2Y credit spread... y así sucesivamente. A partir de los vencimientos que carecen de diferencial de crédito, como el de 18Y, se debe interpolar nudos conocidos).
¿Cómo es posible hacer algo así utilizando QuantLib ?