#include <ql/quantlib.hpp>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <ql/termstructures/yield/ratehelpers.hpp>
using namespace std;
using namespace QuantLib;
using namespace boost;
void testPiecewiseCurve(int yyyymmdd);
int main(int argc, char* argv[])
{
int yyyymmdd = 20140117;
try {
testPiecewiseCurve(yyyymmdd);
}
catch (std::exception& e) {
cout << "Couldn't build yield curve: " << e.what() << endl;
}
return 0;
}
struct Datum {
int n;
TimeUnit units;
Rate rate;
};
struct EDFDatum {
Date expiry;
Real price;
Rate convexityAdj;
};
Datum depositData[] = {
{ 1, Months, 0.157 },
{ 3, Months, 0.2366 }
};
EDFDatum edfData[] = {
{ Date(41715), 99.75, 0.00 },
{ Date(41806), 99.71, 0.00 },
{ Date(41897), 99.66, 0.00 },
{ Date(41988), 99.575, 0.00 },
{ Date(42079), 99.445, 0.00 },
{ Date(42170), 99.28, 0.00 },
{ Date(42261), 99.08, 0.00 },
{ Date(42352), 98.84, 0.00 },
{ Date(42443), 98.56, 0.00 },
{ Date(42534), 98.275, 0.00 },
{ Date(42632), 98.00, 0.00 },
{ Date(42723), 97.735, 0.00 }
};
Datum swapData[] = {
{ 5, Years, 1.73377 },
{ 6, Years, 2.074532 },
{ 7, Years, 2.36113 },
{ 8, Years, 2.592213 },
{ 9, Years, 2.781181 },
{ 10, Years, 2.937271 },
{ 15, Years, 3.418712 },
{ 30, Years, 3.742963 },
{ 35, Years, 3.742963 },
{ 40, Years, 3.742963 },
{ 45, Years, 3.742963 },
{ 50, Years, 3.742963 }
};
void testPiecewiseCurve(int yyyymmdd){
Calendar calendar = JointCalendar(UnitedStates(UnitedStates::Settlement), UnitedKingdom(UnitedKingdom::Exchange), JoinHolidays);
int dd = yyyymmdd%100;
int mm = (yyyymmdd/100)%100;
int yyyy = yyyymmdd/10000;
Date pricingDate = calendar.adjust(Date(dd , Month(mm), yyyy));
Date zeroDate = calendar.advance (pricingDate , 2 , Days );
vector<boost::shared_ptr<SimpleQuote> > rates, prices;
vector <boost::shared_ptr < RateHelper >> instruments;
Size libors = 2;
Size edfs = 12 ;
Size swaps = 12;
instruments = std::vector<boost::shared_ptr<RateHelper> >(libors + edfs + swaps);
rates = vector<boost::shared_ptr<SimpleQuote> >(libors + swaps);
prices = vector<boost::shared_ptr<SimpleQuote> >(edfs);
for (Size i=0; i<libors; i++) {
rates[i] = boost::shared_ptr<SimpleQuote>(new SimpleQuote(depositData[i].rate/100));
}
for (Size i=0; i<edfs; i++) {
prices[i] = boost::shared_ptr<SimpleQuote>(new SimpleQuote(edfData[i].price));
}
for (Size i=0; i<swaps; i++) {
rates[i+libors] = boost::shared_ptr<SimpleQuote>(new SimpleQuote(swapData[i].rate/100));
}
Settings::instance().evaluationDate() = pricingDate;
//For USD Libor Swap, the fixed leg frequency is semiannual
Frequency fixedLegFrequency = Semiannual;
//For USD Libor Swap, the fixed leg convention is modified following
//Modified Following: Choose the first business day after the given holiday unless it belongs to a different month,
//in which case choose the first business day before the holiday.
BusinessDayConvention fixedLegConvention = ModifiedFollowing;
//For USD Libor Swap, the fixed leg day counter is 30/360
DayCounter fixedLegDayCounter = Thirty360();
boost::shared_ptr<IborIndex> libor1m(new USDLibor(1*Months));
boost::shared_ptr<IborIndex> libor3m(new USDLibor(3*Months));
boost::shared_ptr<IborIndex> libor6m(new USDLibor(6*Months));
Handle<Quote> r0(rates[0]);
instruments[0] = boost::shared_ptr<RateHelper>(new DepositRateHelper(r0, 1*Months, libor1m->fixingDays(), calendar,
libor1m->businessDayConvention(),
libor1m->endOfMonth(),
libor1m->dayCounter()));
Handle<Quote> r1(rates[1]);
instruments[1] = boost::shared_ptr<RateHelper>(new DepositRateHelper(r1, 3*Months, libor3m->fixingDays(), calendar,
libor3m->businessDayConvention(),
libor3m->endOfMonth(),
libor3m->dayCounter()));
for (Size i=0; i<edfs; i++) {
Handle<Quote> p(prices[i]);
Date immDate = IMM::nextDate(edfData[i].expiry);
//EDF prices should be convexity adjusted
boost::shared_ptr<Quote> convexity(new SimpleQuote(edfData[i].convexityAdj/10000.0));
instruments[i+libors] = boost::shared_ptr<RateHelper>(new FuturesRateHelper(p, immDate, 3, calendar,
libor3m->businessDayConvention(),
libor3m->endOfMonth(),
libor3m->dayCounter(),
Handle<Quote>(convexity)));
}
for (Size i=0; i<swaps; i++) {
Handle<Quote> r(rates[i+libors]);
instruments[i+libors+edfs] = boost::shared_ptr<RateHelper>(new SwapRateHelper(r, swapData[i].n*swapData[i].units, calendar,
fixedLegFrequency, fixedLegConvention, fixedLegDayCounter, libor3m));
}
Cubic myCubic(CubicInterpolation::Spline, true,
CubicInterpolation::SecondDerivative, 0.0,
CubicInterpolation::SecondDerivative, 0.0);
DayCounter dc= Actual360 ();
cout << "zero date is " << zeroDate << endl;
boost::shared_ptr <QuantLib::YieldTermStructure> yieldCurve = boost::shared_ptr < YieldTermStructure >( new PiecewiseYieldCurve < ZeroYield , Cubic, IterativeBootstrap >( zeroDate , instruments , dc, myCubic));
yieldCurve -> enableExtrapolation();
Handle < YieldTermStructure > ycHandle ( yieldCurve );
boost::shared_ptr < IborIndex > libor3m_new ( new USDLibor ( Period (3, Months ), ycHandle ));
cout << "Checking estimated rates against input..." << endl;
Real tolerance = 1.0e-7;
// Check Results
// Check deposits
for (Size i=0; i<libors; i++) {
//USDLibor index(depositData[i].n*depositData[i].units, ycHandle);
Libor index("USDLibor", depositData[i].n*depositData[i].units, 2,
USDCurrency(),
calendar,
Actual360(), ycHandle);
Rate inputRate = depositData[i].rate/100,
estimatedRate = index.fixing(pricingDate);
if (std::fabs(estimatedRate - inputRate) > tolerance)
cout << depositData[i].n*depositData[i].units
<< " Deposit:"
<< setprecision(8)
<< "\n\t estimated rate: " << estimatedRate
<< "\n\t input rate: " << inputRate
<< endl;
}
// Check swap rate
for (Size i=0; i<swaps; i++) {
Period tenor = swapData[i].n*swapData[i].units;
// construct a vanilla swap
VanillaSwap swap = MakeVanillaSwap (tenor, libor3m_new)
. withEffectiveDate (zeroDate)
. withFixedLegConvention (ModifiedFollowing)
. withFixedLegTenor (6*Months);
Rate inputRate = swapData[i].rate/100,
estimatedRate = swap.fairRate();
if (std::fabs(estimatedRate - inputRate) > tolerance)
cout << tenor <<" Swap :" << setprecision(8)
<< "\n\t estimated rate: "<< estimatedRate
<< "\n\t input rate: "<< inputRate
<< endl ;
}
cout << "Zero-yield Rates..."<< endl;
for (int i=0; i<=120; i++){
Rate zeroRate = yieldCurve -> zeroRate ( zeroDate + 3*i* Months ,dc , Continuous );
DiscountFactor discountFactor = yieldCurve -> discount( zeroDate + 3*i* Months );
cout << " Zero " << 3*i << "M: " << zeroDate +3*i* Months<< " " << zeroRate << " discount factor " << discountFactor << endl ;
}
cout << "\n3m Forward Rates..."<< endl;
for (int i=0; i<=120; i++){
Date d1= zeroDate +3*i* Months, d2=d1 +3* Months ;
Rate forwardRate = yieldCurve -> forwardRate (d1 ,d2 ,dc , Continuous );
cout << 3*i << " x " << 3*i + 3 << " Fwd : " << forwardRate<< endl ;
}
}
Free forum by Nabble | Edit this page |