Piecewise Yield Curve Errors

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Piecewise Yield Curve Errors

Neo G.W.
Hi,

I am trying to build a yield curve using the following inputs:

USD Libor 1m, 3m
EDF prices (12 of them, 3m apart, let's suppose convexity adjustment is zero)
Swap rates (5yr to 50yr)

To be able to interpolate with swap rates, I have to set my calendar to be the joint calendar of US and UK. Theses are the errors I am getting:

For pricing date 1/17/2014:
negative time (-0.00277778) given

For pricing date 2/13/2014:
interpolation range is [0.0777778, 7.10278]: extrapolation at 0.075 not allowed

To avoid out of range errors, I also have to enable extrapolation for the yield curve builder.

Can anybody help me with this? The stand alone code is as follows:

#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 ;

}

 

}



------------------------------------------------------------------------------

_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Piecewise Yield Curve Errors

Marianne James

Hi Guan,

The deposit check is requesting a rate for the zerodate and hence getting a negative time of 1 day in years (for 360 days). Change the deposit check to this so you are actually asking for a rate on the deposit data point.

 

       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;

              Date l_DateToUse = pricingDate + (depositData[i].n*depositData[i].units);

              Rate estimatedRate = index.fixing(l_DateToUse);

              //if (std::fabs(estimatedRate - inputRate) > tolerance)

              cout << depositData[i].n*depositData[i].units << " (" << l_DateToUse << ") "

                     << " Deposit:"

                     << setprecision(8)

                     << "\n\t estimated rate: " << estimatedRate

                     << "\n\t input rate: " << inputRate

                     << endl;

       }

 

I get the following output – the deposit rates for 1M and 3M are off although the zero yield rates for 0M and 3M look better – I’m not sure why at the moment.

 

Thanks

Ed

 

 

zero date is January 22nd, 2014

Checking estimated rates against input...

1M (February 17th, 2014)  Deposit:

                estimated rate: 0.0020672531

                input rate: 0.00157

3M (April 17th, 2014)  Deposit:

                estimated rate: 0.0021845006

                input rate: 0.002366

5Y Swap :

                estimated rate: 0.0173377

                input rate: 0.0173377

6Y Swap :

                estimated rate: 0.02074532

                input rate: 0.02074532

7Y Swap :

                estimated rate: 0.0236113

                input rate: 0.0236113

8Y Swap :

                estimated rate: 0.02592213

                input rate: 0.02592213

9Y Swap :

                estimated rate: 0.02781181

                input rate: 0.02781181

10Y Swap :

                estimated rate: 0.02937271

                input rate: 0.02937271

15Y Swap :

                estimated rate: 0.03418712

                input rate: 0.03418712

30Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

35Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

40Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

45Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

50Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

Zero-yield Rates...

Zero 0M: January 22nd, 2014 0.001569887 discount factor 1

Zero 3M: April 22nd, 2014 0.0023653005 discount factor 0.99940885

Zero 6M: July 22nd, 2014 0.0022751584 discount factor 0.99885675

Zero 9M: October 22nd, 2014 0.0026115489 discount factor 0.99802154

Zero 12M: January 22nd, 2015 0.002851819 discount factor 0.99711275

Zero 15M: April 22nd, 2015 0.003226952 discount factor 0.9959298

Zero 18M: July 22nd, 2015 0.003708467 discount factor 0.99439128

Zero 21M: October 22nd, 2015 0.0043166678 discount factor 0.99237909

Zero 24M: January 22nd, 2016 0.0050454544 discount factor 0.9898211

Zero 27M: April 22nd, 2016 0.0058911916 discount factor 0.98665466

Zero 30M: July 22nd, 2016 0.006853368 discount factor 0.98278798

Zero 33M: October 22nd, 2016 0.0078990854 discount factor 0.97821121

Zero 36M: January 22nd, 2017 0.0089884804 discount factor 0.9730061

Zero 39M: April 22nd, 2017 0.010082293 discount factor 0.96733002

Zero 42M: July 22nd, 2017 0.011174645 discount factor 0.9611364

Zero 45M: October 22nd, 2017 0.012259943 discount factor 0.95444826

Zero 48M: January 22nd, 2018 0.013324237 discount factor 0.94736181

Zero 51M: April 22nd, 2018 0.014343294 discount factor 0.94007493

Zero 54M: July 22nd, 2018 0.015349671 discount factor 0.93238305

Zero 57M: October 22nd, 2018 0.016340753 discount factor 0.92430982

Zero 60M: January 22nd, 2019 0.017303495 discount factor 0.91597412

Zero 63M: April 22nd, 2019 0.018216268 discount factor 0.90760046

Zero 66M: July 22nd, 2019 0.019109012 discount factor 0.89894562

Zero 69M: October 22nd, 2019 0.019979907 discount factor 0.89003548

Zero 72M: January 22nd, 2020 0.02081814 discount factor 0.8809966

Zero 75M: April 22nd, 2020 0.02161429 discount factor 0.871961

Zero 78M: July 22nd, 2020 0.02237673 discount factor 0.86286249

Zero 81M: October 22nd, 2020 0.02311232 discount factor 0.85363191

Zero 84M: January 22nd, 2021 0.023811523 discount factor 0.84440085

Zero 87M: April 22nd, 2021 0.02446009 discount factor 0.83539584

Zero 90M: July 22nd, 2021 0.025082903 discount factor 0.82632311

Zero 93M: October 22nd, 2021 0.025682361 discount factor 0.81718326

Zero 96M: January 22nd, 2022 0.026254993 discount factor 0.80807288

Zero 99M: April 22nd, 2022 0.026792146 discount factor 0.79918649

Zero 102M: July 22nd, 2022 0.027312938 discount factor 0.79023702

Zero 105M: October 22nd, 2022 0.027816886 discount factor 0.78123845

Zero 108M: January 22nd, 2023 0.028298407 discount factor 0.77230157

Zero 111M: April 22nd, 2023 0.028748215 discount factor 0.76362822

Zero 114M: July 22nd, 2023 0.029182995 discount factor 0.75493055

Zero 117M: October 22nd, 2023 0.029603684 discount factor 0.7462105

Zero 120M: January 22nd, 2024 0.030007023 discount factor 0.73756241

Zero 123M: April 22nd, 2024 0.030390789 discount factor 0.72907418

Zero 126M: July 22nd, 2024 0.030760488 discount factor 0.7206518

Zero 129M: October 22nd, 2024 0.031120285 discount factor 0.71220891

Zero 132M: January 22nd, 2025 0.031466383 discount factor 0.70384311

Zero 135M: April 22nd, 2025 0.03179203 discount factor 0.69573782

Zero 138M: July 22nd, 2025 0.032108624 discount factor 0.68762516

Zero 141M: October 22nd, 2025 0.032416082 discount factor 0.67951111

Zero 144M: January 22nd, 2026 0.032711196 discount factor 0.67148821

Zero 147M: April 22nd, 2026 0.03298828 discount factor 0.66373031

Zero 150M: July 22nd, 2026 0.03325709 discount factor 0.65597933

Zero 153M: October 22nd, 2026 0.033517587 discount factor 0.6482401

Zero 156M: January 22nd, 2027 0.033767097 discount factor 0.64059972

Zero 159M: April 22nd, 2027 0.034000878 discount factor 0.63322212

Zero 162M: July 22nd, 2027 0.034227224 discount factor 0.62586052

Zero 165M: October 22nd, 2027 0.034446139 discount factor 0.61851863

Zero 168M: January 22nd, 2028 0.034655422 discount factor 0.6112781

Zero 171M: April 22nd, 2028 0.034853289 discount factor 0.60421592

Zero 174M: July 22nd, 2028 0.035042398 discount factor 0.59725252

Zero 177M: October 22nd, 2028 0.035225017 discount factor 0.59031249

Zero 180M: January 22nd, 2029 0.035399364 discount factor 0.58347209

Zero 183M: April 22nd, 2029 0.035563263 discount factor 0.57686678

Zero 186M: July 22nd, 2029 0.035723509 discount factor 0.57026567

Zero 189M: October 22nd, 2029 0.035880014 discount factor 0.56367193

Zero 192M: January 22nd, 2030 0.036031083 discount factor 0.55715903

Zero 195M: April 22nd, 2030 0.0361737 discount factor 0.5508663

Zero 198M: July 22nd, 2030 0.036312798 discount factor 0.54458294

Zero 201M: October 22nd, 2030 0.036448302 discount factor 0.53831177

Zero 204M: January 22nd, 2031 0.036578751 discount factor 0.53212234

Zero 207M: April 22nd, 2031 0.036701566 discount factor 0.52614657

Zero 210M: July 22nd, 2031 0.036821012 discount factor 0.52018385

Zero 213M: October 22nd, 2031 0.036937028 discount factor 0.51423665

Zero 216M: January 22nd, 2032 0.03704837 discount factor 0.50837069

Zero 219M: April 22nd, 2032 0.037153998 discount factor 0.50264808

Zero 222M: July 22nd, 2032 0.037255241 discount factor 0.49700425

Zero 225M: October 22nd, 2032 0.037353234 discount factor 0.49137804

Zero 228M: January 22nd, 2033 0.037446935 discount factor 0.48583137

Zero 231M: April 22nd, 2033 0.037534539 discount factor 0.4804817

Zero 234M: July 22nd, 2033 0.037619126 discount factor 0.47514882

Zero 237M: October 22nd, 2033 0.037700659 discount factor 0.46983458

Zero 240M: January 22nd, 2034 0.037778282 discount factor 0.46459728

Zero 243M: April 22nd, 2034 0.037850526 discount factor 0.45954754

Zero 246M: July 22nd, 2034 0.037919953 discount factor 0.454515

Zero 249M: October 22nd, 2034 0.037986539 discount factor 0.44950125

Zero 252M: January 22nd, 2035 0.038049596 discount factor 0.4445611

Zero 255M: April 22nd, 2035 0.038107959 discount factor 0.43979867

Zero 258M: July 22nd, 2035 0.038163723 discount factor 0.4350531

Zero 261M: October 22nd, 2035 0.038216873 discount factor 0.43032573

Zero 264M: January 22nd, 2036 0.038266876 discount factor 0.42566807

Zero 267M: April 22nd, 2036 0.038313333 discount factor 0.42112858

Zero 270M: July 22nd, 2036 0.038356897 discount factor 0.41665523

Zero 273M: October 22nd, 2036 0.038398095 discount factor 0.41219887

Zero 276M: January 22nd, 2037 0.038436527 discount factor 0.4078079

Zero 279M: April 22nd, 2037 0.03847154 discount factor 0.40357457

Zero 282M: July 22nd, 2037 0.038504436 discount factor 0.39935562

Zero 285M: October 22nd, 2037 0.038535227 discount factor 0.39515195

Zero 288M: January 22nd, 2038 0.038563634 discount factor 0.39100908

Zero 291M: April 22nd, 2038 0.038589209 discount factor 0.38701395

Zero 294M: July 22nd, 2038 0.038612933 discount factor 0.38303127

Zero 297M: October 22nd, 2038 0.038634831 discount factor 0.37906173

Zero 300M: January 22nd, 2039 0.038654725 discount factor 0.37514819

Zero 303M: April 22nd, 2039 0.038672341 discount factor 0.37137273

Zero 306M: July 22nd, 2039 0.038688389 discount factor 0.36760743

Zero 309M: October 22nd, 2039 0.038702905 discount factor 0.3638528

Zero 312M: January 22nd, 2040 0.038715799 discount factor 0.36014925

Zero 315M: April 22nd, 2040 0.038727052 discount factor 0.35653498

Zero 318M: July 22nd, 2040 0.038736905 discount factor 0.35296826

Zero 321M: October 22nd, 2040 0.038745538 discount factor 0.34940945

Zero 324M: January 22nd, 2041 0.038752931 discount factor 0.34589673

Zero 327M: April 22nd, 2041 0.038759057 discount factor 0.34250378

Zero 330M: July 22nd, 2041 0.038764229 discount factor 0.33911557

Zero 333M: October 22nd, 2041 0.038768509 discount factor 0.33573228

Zero 336M: January 22nd, 2042 0.038771931 discount factor 0.33239012

Zero 339M: April 22nd, 2042 0.03877454 discount factor 0.32915922

Zero 342M: July 22nd, 2042 0.038776529 discount factor 0.32593004

Zero 345M: October 22nd, 2042 0.038777969 discount factor 0.32270261

Zero 348M: January 22nd, 2043 0.038778931 discount factor 0.3195114

Zero 351M: April 22nd, 2043 0.038779504 discount factor 0.31642341

Zero 354M: July 22nd, 2043 0.038779803 discount factor 0.31333398

Zero 357M: October 22nd, 2043 0.038779915 discount factor 0.31024301

Zero 360M: January 22nd, 2044 0.038779931 discount factor 0.3071834

 

3m Forward Rates...

0 x 3 Fwd : 0.0023653005

3 x 6 Fwd : 0.0021860069

6 x 9 Fwd : 0.0032733606

9 x 12 Fwd : 0.0035647945

12 x 15 Fwd : 0.0047483244

15 x 18 Fwd : 0.0061160423

18 x 21 Fwd : 0.0079262072

21 x 24 Fwd : 0.010099431

24 x 27 Fwd : 0.012675677

27 x 30 Fwd : 0.015534102

30 x 33 Fwd : 0.018265327

33 x 36 Fwd : 0.020877095

36 x 39 Fwd : 0.023402501

39 x 42 Fwd : 0.025411231

42 x 45 Fwd : 0.027324354

45 x 48 Fwd : 0.029161396

48 x 51 Fwd : 0.030885983

51 x 54 Fwd : 0.032502315

54 x 57 Fwd : 0.034029417

57 x 60 Fwd : 0.035449091

60 x 63 Fwd : 0.036735406

63 x 66 Fwd : 0.037905685

66 x 69 Fwd : 0.038978677

69 x 72 Fwd : 0.039942605

72 x 75 Fwd : 0.04078315

75 x 78 Fwd : 0.041496367

78 x 81 Fwd : 0.042085756

81 x 84 Fwd : 0.042545605

84 x 87 Fwd : 0.042886573

87 x 90 Fwd : 0.043199236

90 x 93 Fwd : 0.043522775

93 x 96 Fwd : 0.043869627

96 x 99 Fwd : 0.044231727

99 x 102 Fwd : 0.044550577

102 x 105 Fwd : 0.04481419

105 x 108 Fwd : 0.045020768

108 x 111 Fwd : 0.045176223

111 x 114 Fwd : 0.045317632

114 x 117 Fwd : 0.045461827

117 x 120 Fwd : 0.045614485

120 x 123 Fwd : 0.045792055

123 x 126 Fwd : 0.04596687

126 x 129 Fwd : 0.04611445

129 x 132 Fwd : 0.046235741

132 x 135 Fwd : 0.046330338

135 x 138 Fwd : 0.046400593

138 x 141 Fwd : 0.046448871

141 x 144 Fwd : 0.046475719

144 x 147 Fwd : 0.046482225

147 x 150 Fwd : 0.046470149

150 x 153 Fwd : 0.046440521

153 x 156 Fwd : 0.046394441

156 x 159 Fwd : 0.046334137

159 x 162 Fwd : 0.046260894

162 x 165 Fwd : 0.046174758

165 x 168 Fwd : 0.046077263

168 x 171 Fwd : 0.045970816

171 x 174 Fwd : 0.045856891

174 x 177 Fwd : 0.045735577

177 x 180 Fwd : 0.04560813

180 x 183 Fwd : 0.045541077

183 x 186 Fwd : 0.045530178

186 x 189 Fwd : 0.045508462

189 x 192 Fwd : 0.045476174

192 x 195 Fwd : 0.045434309

195 x 198 Fwd : 0.045383208

198 x 201 Fwd : 0.045322345

201 x 204 Fwd : 0.045252216

204 x 207 Fwd : 0.045174418

207 x 210 Fwd : 0.045089064

210 x 213 Fwd : 0.044995071

213 x 216 Fwd : 0.044893149

216 x 219 Fwd : 0.044784786

219 x 222 Fwd : 0.044670457

222 x 225 Fwd : 0.044549284

225 x 228 Fwd : 0.044421557

228 x 231 Fwd : 0.044289787

231 x 234 Fwd : 0.044153728

234 x 237 Fwd : 0.044011474

237 x 240 Fwd : 0.043864071

240 x 243 Fwd : 0.043714334

243 x 246 Fwd : 0.043561893

246 x 249 Fwd : 0.043404574

249 x 252 Fwd : 0.043243543

252 x 255 Fwd : 0.043081824

255 x 258 Fwd : 0.04291895

258 x 261 Fwd : 0.042752583

261 x 264 Fwd : 0.042583974

264 x 267 Fwd : 0.042415333

267 x 270 Fwd : 0.042247049

270 x 273 Fwd : 0.042077651

273 x 276 Fwd : 0.041907517

276 x 279 Fwd : 0.041739792

279 x 282 Fwd : 0.041573917

282 x 285 Fwd : 0.04140752

285 x 288 Fwd : 0.041241923

288 x 291 Fwd : 0.041080184

291 x 294 Fwd : 0.040921743

294 x 297 Fwd : 0.040764365

297 x 300 Fwd : 0.040609354

300 x 303 Fwd : 0.040459583

303 x 306 Fwd : 0.040314529

306 x 309 Fwd : 0.040172185

309 x 312 Fwd : 0.04003381

312 x 315 Fwd : 0.039901286

315 x 318 Fwd : 0.039774917

318 x 321 Fwd : 0.039653689

321 x 324 Fwd : 0.039538069

324 x 327 Fwd : 0.03943026

327 x 330 Fwd : 0.039329909

330 x 333 Fwd : 0.039235765

333 x 336 Fwd : 0.039148896

336 x 339 Fwd : 0.039071023

339 x 342 Fwd : 0.039001926

342 x 345 Fwd : 0.038940882

345 x 348 Fwd : 0.038888814

348 x 351 Fwd : 0.03884686

351 x 354 Fwd : 0.038814969

354 x 357 Fwd : 0.038793041

357 x 360 Fwd : 0.038781823

360 x 363 Fwd : 0.03858163

 

 

From: Guan Wang [mailto:[hidden email]]
Sent: 11 June 2015 21:47
To: [hidden email]
Subject: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi,

 

I am trying to build a yield curve using the following inputs:

 

USD Libor 1m, 3m

EDF prices (12 of them, 3m apart, let's suppose convexity adjustment is zero)

Swap rates (5yr to 50yr)

 

To be able to interpolate with swap rates, I have to set my calendar to be the joint calendar of US and UK. Theses are the errors I am getting:

 

For pricing date 1/17/2014:

negative time (-0.00277778) given

 

For pricing date 2/13/2014:

interpolation range is [0.0777778, 7.10278]: extrapolation at 0.075 not allowed

 

To avoid out of range errors, I also have to enable extrapolation for the yield curve builder.

 

Can anybody help me with this? The stand alone code is as follows:

 

#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 ;

}

 

}

 


------------------------------------------------------------------------------

_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Piecewise Yield Curve Errors

Neo G.W.
Hi Ed,

I am not sure about the change you made in the deposit check. If you take a look at ../quantlib/1.5/test-suite/piecewiseyieldcurve.cpp, in the function testCurveConsistency():

Euribor index(depositData[i].n*depositData[i].units,curveHandle);

Rate expectedRate = depositData[i].rate/100,

estimatedRate = index.fixing(vars.today);


In my code the pricing date is equivalent to "today" here. The sample driver program seems to suggest using pricing date to index fixing. Your change is not exactly in accordance with the sample code, is it? As a result, the 1M and 3M estimated rates are quite off.


Thanks!

Guan


On Fri, Jun 12, 2015 at 3:17 PM, Ed James <[hidden email]> wrote:

Hi Guan,

The deposit check is requesting a rate for the zerodate and hence getting a negative time of 1 day in years (for 360 days). Change the deposit check to this so you are actually asking for a rate on the deposit data point.

 

       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;

              Date l_DateToUse = pricingDate + (depositData[i].n*depositData[i].units);

              Rate estimatedRate = index.fixing(l_DateToUse);

              //if (std::fabs(estimatedRate - inputRate) > tolerance)

              cout << depositData[i].n*depositData[i].units << " (" << l_DateToUse << ") "

                     << " Deposit:"

                     << setprecision(8)

                     << "\n\t estimated rate: " << estimatedRate

                     << "\n\t input rate: " << inputRate

                     << endl;

       }

 

I get the following output – the deposit rates for 1M and 3M are off although the zero yield rates for 0M and 3M look better – I’m not sure why at the moment.

 

Thanks

Ed

 

 

zero date is January 22nd, 2014

Checking estimated rates against input...

1M (February 17th, 2014)  Deposit:

                estimated rate: 0.0020672531

                input rate: 0.00157

3M (April 17th, 2014)  Deposit:

                estimated rate: 0.0021845006

                input rate: 0.002366

5Y Swap :

                estimated rate: 0.0173377

                input rate: 0.0173377

6Y Swap :

                estimated rate: 0.02074532

                input rate: 0.02074532

7Y Swap :

                estimated rate: 0.0236113

                input rate: 0.0236113

8Y Swap :

                estimated rate: 0.02592213

                input rate: 0.02592213

9Y Swap :

                estimated rate: 0.02781181

                input rate: 0.02781181

10Y Swap :

                estimated rate: 0.02937271

                input rate: 0.02937271

15Y Swap :

                estimated rate: 0.03418712

                input rate: 0.03418712

30Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

35Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

40Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

45Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

50Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

Zero-yield Rates...

Zero 0M: January 22nd, 2014 0.001569887 discount factor 1

Zero 3M: April 22nd, 2014 0.0023653005 discount factor 0.99940885

Zero 6M: July 22nd, 2014 0.0022751584 discount factor 0.99885675

Zero 9M: October 22nd, 2014 0.0026115489 discount factor 0.99802154

Zero 12M: January 22nd, 2015 0.002851819 discount factor 0.99711275

Zero 15M: April 22nd, 2015 0.003226952 discount factor 0.9959298

Zero 18M: July 22nd, 2015 0.003708467 discount factor 0.99439128

Zero 21M: October 22nd, 2015 0.0043166678 discount factor 0.99237909

Zero 24M: January 22nd, 2016 0.0050454544 discount factor 0.9898211

Zero 27M: April 22nd, 2016 0.0058911916 discount factor 0.98665466

Zero 30M: July 22nd, 2016 0.006853368 discount factor 0.98278798

Zero 33M: October 22nd, 2016 0.0078990854 discount factor 0.97821121

Zero 36M: January 22nd, 2017 0.0089884804 discount factor 0.9730061

Zero 39M: April 22nd, 2017 0.010082293 discount factor 0.96733002

Zero 42M: July 22nd, 2017 0.011174645 discount factor 0.9611364

Zero 45M: October 22nd, 2017 0.012259943 discount factor 0.95444826

Zero 48M: January 22nd, 2018 0.013324237 discount factor 0.94736181

Zero 51M: April 22nd, 2018 0.014343294 discount factor 0.94007493

Zero 54M: July 22nd, 2018 0.015349671 discount factor 0.93238305

Zero 57M: October 22nd, 2018 0.016340753 discount factor 0.92430982

Zero 60M: January 22nd, 2019 0.017303495 discount factor 0.91597412

Zero 63M: April 22nd, 2019 0.018216268 discount factor 0.90760046

Zero 66M: July 22nd, 2019 0.019109012 discount factor 0.89894562

Zero 69M: October 22nd, 2019 0.019979907 discount factor 0.89003548

Zero 72M: January 22nd, 2020 0.02081814 discount factor 0.8809966

Zero 75M: April 22nd, 2020 0.02161429 discount factor 0.871961

Zero 78M: July 22nd, 2020 0.02237673 discount factor 0.86286249

Zero 81M: October 22nd, 2020 0.02311232 discount factor 0.85363191

Zero 84M: January 22nd, 2021 0.023811523 discount factor 0.84440085

Zero 87M: April 22nd, 2021 0.02446009 discount factor 0.83539584

Zero 90M: July 22nd, 2021 0.025082903 discount factor 0.82632311

Zero 93M: October 22nd, 2021 0.025682361 discount factor 0.81718326

Zero 96M: January 22nd, 2022 0.026254993 discount factor 0.80807288

Zero 99M: April 22nd, 2022 0.026792146 discount factor 0.79918649

Zero 102M: July 22nd, 2022 0.027312938 discount factor 0.79023702

Zero 105M: October 22nd, 2022 0.027816886 discount factor 0.78123845

Zero 108M: January 22nd, 2023 0.028298407 discount factor 0.77230157

Zero 111M: April 22nd, 2023 0.028748215 discount factor 0.76362822

Zero 114M: July 22nd, 2023 0.029182995 discount factor 0.75493055

Zero 117M: October 22nd, 2023 0.029603684 discount factor 0.7462105

Zero 120M: January 22nd, 2024 0.030007023 discount factor 0.73756241

Zero 123M: April 22nd, 2024 0.030390789 discount factor 0.72907418

Zero 126M: July 22nd, 2024 0.030760488 discount factor 0.7206518

Zero 129M: October 22nd, 2024 0.031120285 discount factor 0.71220891

Zero 132M: January 22nd, 2025 0.031466383 discount factor 0.70384311

Zero 135M: April 22nd, 2025 0.03179203 discount factor 0.69573782

Zero 138M: July 22nd, 2025 0.032108624 discount factor 0.68762516

Zero 141M: October 22nd, 2025 0.032416082 discount factor 0.67951111

Zero 144M: January 22nd, 2026 0.032711196 discount factor 0.67148821

Zero 147M: April 22nd, 2026 0.03298828 discount factor 0.66373031

Zero 150M: July 22nd, 2026 0.03325709 discount factor 0.65597933

Zero 153M: October 22nd, 2026 0.033517587 discount factor 0.6482401

Zero 156M: January 22nd, 2027 0.033767097 discount factor 0.64059972

Zero 159M: April 22nd, 2027 0.034000878 discount factor 0.63322212

Zero 162M: July 22nd, 2027 0.034227224 discount factor 0.62586052

Zero 165M: October 22nd, 2027 0.034446139 discount factor 0.61851863

Zero 168M: January 22nd, 2028 0.034655422 discount factor 0.6112781

Zero 171M: April 22nd, 2028 0.034853289 discount factor 0.60421592

Zero 174M: July 22nd, 2028 0.035042398 discount factor 0.59725252

Zero 177M: October 22nd, 2028 0.035225017 discount factor 0.59031249

Zero 180M: January 22nd, 2029 0.035399364 discount factor 0.58347209

Zero 183M: April 22nd, 2029 0.035563263 discount factor 0.57686678

Zero 186M: July 22nd, 2029 0.035723509 discount factor 0.57026567

Zero 189M: October 22nd, 2029 0.035880014 discount factor 0.56367193

Zero 192M: January 22nd, 2030 0.036031083 discount factor 0.55715903

Zero 195M: April 22nd, 2030 0.0361737 discount factor 0.5508663

Zero 198M: July 22nd, 2030 0.036312798 discount factor 0.54458294

Zero 201M: October 22nd, 2030 0.036448302 discount factor 0.53831177

Zero 204M: January 22nd, 2031 0.036578751 discount factor 0.53212234

Zero 207M: April 22nd, 2031 0.036701566 discount factor 0.52614657

Zero 210M: July 22nd, 2031 0.036821012 discount factor 0.52018385

Zero 213M: October 22nd, 2031 0.036937028 discount factor 0.51423665

Zero 216M: January 22nd, 2032 0.03704837 discount factor 0.50837069

Zero 219M: April 22nd, 2032 0.037153998 discount factor 0.50264808

Zero 222M: July 22nd, 2032 0.037255241 discount factor 0.49700425

Zero 225M: October 22nd, 2032 0.037353234 discount factor 0.49137804

Zero 228M: January 22nd, 2033 0.037446935 discount factor 0.48583137

Zero 231M: April 22nd, 2033 0.037534539 discount factor 0.4804817

Zero 234M: July 22nd, 2033 0.037619126 discount factor 0.47514882

Zero 237M: October 22nd, 2033 0.037700659 discount factor 0.46983458

Zero 240M: January 22nd, 2034 0.037778282 discount factor 0.46459728

Zero 243M: April 22nd, 2034 0.037850526 discount factor 0.45954754

Zero 246M: July 22nd, 2034 0.037919953 discount factor 0.454515

Zero 249M: October 22nd, 2034 0.037986539 discount factor 0.44950125

Zero 252M: January 22nd, 2035 0.038049596 discount factor 0.4445611

Zero 255M: April 22nd, 2035 0.038107959 discount factor 0.43979867

Zero 258M: July 22nd, 2035 0.038163723 discount factor 0.4350531

Zero 261M: October 22nd, 2035 0.038216873 discount factor 0.43032573

Zero 264M: January 22nd, 2036 0.038266876 discount factor 0.42566807

Zero 267M: April 22nd, 2036 0.038313333 discount factor 0.42112858

Zero 270M: July 22nd, 2036 0.038356897 discount factor 0.41665523

Zero 273M: October 22nd, 2036 0.038398095 discount factor 0.41219887

Zero 276M: January 22nd, 2037 0.038436527 discount factor 0.4078079

Zero 279M: April 22nd, 2037 0.03847154 discount factor 0.40357457

Zero 282M: July 22nd, 2037 0.038504436 discount factor 0.39935562

Zero 285M: October 22nd, 2037 0.038535227 discount factor 0.39515195

Zero 288M: January 22nd, 2038 0.038563634 discount factor 0.39100908

Zero 291M: April 22nd, 2038 0.038589209 discount factor 0.38701395

Zero 294M: July 22nd, 2038 0.038612933 discount factor 0.38303127

Zero 297M: October 22nd, 2038 0.038634831 discount factor 0.37906173

Zero 300M: January 22nd, 2039 0.038654725 discount factor 0.37514819

Zero 303M: April 22nd, 2039 0.038672341 discount factor 0.37137273

Zero 306M: July 22nd, 2039 0.038688389 discount factor 0.36760743

Zero 309M: October 22nd, 2039 0.038702905 discount factor 0.3638528

Zero 312M: January 22nd, 2040 0.038715799 discount factor 0.36014925

Zero 315M: April 22nd, 2040 0.038727052 discount factor 0.35653498

Zero 318M: July 22nd, 2040 0.038736905 discount factor 0.35296826

Zero 321M: October 22nd, 2040 0.038745538 discount factor 0.34940945

Zero 324M: January 22nd, 2041 0.038752931 discount factor 0.34589673

Zero 327M: April 22nd, 2041 0.038759057 discount factor 0.34250378

Zero 330M: July 22nd, 2041 0.038764229 discount factor 0.33911557

Zero 333M: October 22nd, 2041 0.038768509 discount factor 0.33573228

Zero 336M: January 22nd, 2042 0.038771931 discount factor 0.33239012

Zero 339M: April 22nd, 2042 0.03877454 discount factor 0.32915922

Zero 342M: July 22nd, 2042 0.038776529 discount factor 0.32593004

Zero 345M: October 22nd, 2042 0.038777969 discount factor 0.32270261

Zero 348M: January 22nd, 2043 0.038778931 discount factor 0.3195114

Zero 351M: April 22nd, 2043 0.038779504 discount factor 0.31642341

Zero 354M: July 22nd, 2043 0.038779803 discount factor 0.31333398

Zero 357M: October 22nd, 2043 0.038779915 discount factor 0.31024301

Zero 360M: January 22nd, 2044 0.038779931 discount factor 0.3071834

 

3m Forward Rates...

0 x 3 Fwd : 0.0023653005

3 x 6 Fwd : 0.0021860069

6 x 9 Fwd : 0.0032733606

9 x 12 Fwd : 0.0035647945

12 x 15 Fwd : 0.0047483244

15 x 18 Fwd : 0.0061160423

18 x 21 Fwd : 0.0079262072

21 x 24 Fwd : 0.010099431

24 x 27 Fwd : 0.012675677

27 x 30 Fwd : 0.015534102

30 x 33 Fwd : 0.018265327

33 x 36 Fwd : 0.020877095

36 x 39 Fwd : 0.023402501

39 x 42 Fwd : 0.025411231

42 x 45 Fwd : 0.027324354

45 x 48 Fwd : 0.029161396

48 x 51 Fwd : 0.030885983

51 x 54 Fwd : 0.032502315

54 x 57 Fwd : 0.034029417

57 x 60 Fwd : 0.035449091

60 x 63 Fwd : 0.036735406

63 x 66 Fwd : 0.037905685

66 x 69 Fwd : 0.038978677

69 x 72 Fwd : 0.039942605

72 x 75 Fwd : 0.04078315

75 x 78 Fwd : 0.041496367

78 x 81 Fwd : 0.042085756

81 x 84 Fwd : 0.042545605

84 x 87 Fwd : 0.042886573

87 x 90 Fwd : 0.043199236

90 x 93 Fwd : 0.043522775

93 x 96 Fwd : 0.043869627

96 x 99 Fwd : 0.044231727

99 x 102 Fwd : 0.044550577

102 x 105 Fwd : 0.04481419

105 x 108 Fwd : 0.045020768

108 x 111 Fwd : 0.045176223

111 x 114 Fwd : 0.045317632

114 x 117 Fwd : 0.045461827

117 x 120 Fwd : 0.045614485

120 x 123 Fwd : 0.045792055

123 x 126 Fwd : 0.04596687

126 x 129 Fwd : 0.04611445

129 x 132 Fwd : 0.046235741

132 x 135 Fwd : 0.046330338

135 x 138 Fwd : 0.046400593

138 x 141 Fwd : 0.046448871

141 x 144 Fwd : 0.046475719

144 x 147 Fwd : 0.046482225

147 x 150 Fwd : 0.046470149

150 x 153 Fwd : 0.046440521

153 x 156 Fwd : 0.046394441

156 x 159 Fwd : 0.046334137

159 x 162 Fwd : 0.046260894

162 x 165 Fwd : 0.046174758

165 x 168 Fwd : 0.046077263

168 x 171 Fwd : 0.045970816

171 x 174 Fwd : 0.045856891

174 x 177 Fwd : 0.045735577

177 x 180 Fwd : 0.04560813

180 x 183 Fwd : 0.045541077

183 x 186 Fwd : 0.045530178

186 x 189 Fwd : 0.045508462

189 x 192 Fwd : 0.045476174

192 x 195 Fwd : 0.045434309

195 x 198 Fwd : 0.045383208

198 x 201 Fwd : 0.045322345

201 x 204 Fwd : 0.045252216

204 x 207 Fwd : 0.045174418

207 x 210 Fwd : 0.045089064

210 x 213 Fwd : 0.044995071

213 x 216 Fwd : 0.044893149

216 x 219 Fwd : 0.044784786

219 x 222 Fwd : 0.044670457

222 x 225 Fwd : 0.044549284

225 x 228 Fwd : 0.044421557

228 x 231 Fwd : 0.044289787

231 x 234 Fwd : 0.044153728

234 x 237 Fwd : 0.044011474

237 x 240 Fwd : 0.043864071

240 x 243 Fwd : 0.043714334

243 x 246 Fwd : 0.043561893

246 x 249 Fwd : 0.043404574

249 x 252 Fwd : 0.043243543

252 x 255 Fwd : 0.043081824

255 x 258 Fwd : 0.04291895

258 x 261 Fwd : 0.042752583

261 x 264 Fwd : 0.042583974

264 x 267 Fwd : 0.042415333

267 x 270 Fwd : 0.042247049

270 x 273 Fwd : 0.042077651

273 x 276 Fwd : 0.041907517

276 x 279 Fwd : 0.041739792

279 x 282 Fwd : 0.041573917

282 x 285 Fwd : 0.04140752

285 x 288 Fwd : 0.041241923

288 x 291 Fwd : 0.041080184

291 x 294 Fwd : 0.040921743

294 x 297 Fwd : 0.040764365

297 x 300 Fwd : 0.040609354

300 x 303 Fwd : 0.040459583

303 x 306 Fwd : 0.040314529

306 x 309 Fwd : 0.040172185

309 x 312 Fwd : 0.04003381

312 x 315 Fwd : 0.039901286

315 x 318 Fwd : 0.039774917

318 x 321 Fwd : 0.039653689

321 x 324 Fwd : 0.039538069

324 x 327 Fwd : 0.03943026

327 x 330 Fwd : 0.039329909

330 x 333 Fwd : 0.039235765

333 x 336 Fwd : 0.039148896

336 x 339 Fwd : 0.039071023

339 x 342 Fwd : 0.039001926

342 x 345 Fwd : 0.038940882

345 x 348 Fwd : 0.038888814

348 x 351 Fwd : 0.03884686

351 x 354 Fwd : 0.038814969

354 x 357 Fwd : 0.038793041

357 x 360 Fwd : 0.038781823

360 x 363 Fwd : 0.03858163

 

 

From: Guan Wang [mailto:[hidden email]]
Sent: 11 June 2015 21:47
To: [hidden email]
Subject: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi,

 

I am trying to build a yield curve using the following inputs:

 

USD Libor 1m, 3m

EDF prices (12 of them, 3m apart, let's suppose convexity adjustment is zero)

Swap rates (5yr to 50yr)

 

To be able to interpolate with swap rates, I have to set my calendar to be the joint calendar of US and UK. Theses are the errors I am getting:

 

For pricing date 1/17/2014:

negative time (-0.00277778) given

 

For pricing date 2/13/2014:

interpolation range is [0.0777778, 7.10278]: extrapolation at 0.075 not allowed

 

To avoid out of range errors, I also have to enable extrapolation for the yield curve builder.

 

Can anybody help me with this? The stand alone code is as follows:

 

#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 ;

}

 

}

 



------------------------------------------------------------------------------

_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Piecewise Yield Curve Errors

Marianne James

Hi Guan,

          In your original code you had a pricingDate = 20140117 and a zeroDate = 20140122. The term structure is set up using the zeroDate as its reference date as follows:

 

boost::shared_ptr <QuantLib::YieldTermStructure> yieldCurve = boost::shared_ptr < YieldTermStructure >( new PiecewiseYieldCurve < ZeroYield , Cubic, IterativeBootstrap >( zeroDate , instruments , dc, myCubic));

 

You then have a LiborIndex which takes a handle to the term structure as follows:

 

Libor index("USDLibor", depositData[i].n*depositData[i].units, 2,

USDCurrency(),

calendar,

Actual360(), ycHandle);

 

You then try and calculate a rate for the pricingDate as follows:

 

estimatedRate = index.fixing(pricingDate);

 

So the pricingDate here is before the reference date of the term structure so you get a negative number of days and it throws an exception, that’s what I got when I stepped through the code, it subtracts the reference date from the date you pass in and the result has to be positive. The term structure can’t be used for dates before its reference date. In the function testCurveConsistency() what’s the relationship between the vars.today date and the reference date of the curveHandle term structure ?

 

Can you try stepping through your original code and confirm that you see an exception thrown on this line:

 

estimatedRate = index.fixing(pricingDate);

 

Thanks

Ed

 

From: Guan Wang [mailto:[hidden email]]
Sent: 12 June 2015 20:49
To: Ed James
Cc: [hidden email]
Subject: Re: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi Ed,

 

I am not sure about the change you made in the deposit check. If you take a look at ../quantlib/1.5/test-suite/piecewiseyieldcurve.cpp, in the function testCurveConsistency():

 

Euribor index(depositData[i].n*depositData[i].units,curveHandle);

Rate expectedRate = depositData[i].rate/100,

estimatedRate = index.fixing(vars.today);

 

In my code the pricing date is equivalent to "today" here. The sample driver program seems to suggest using pricing date to index fixing. Your change is not exactly in accordance with the sample code, is it? As a result, the 1M and 3M estimated rates are quite off.

 

Thanks!

Guan

 

On Fri, Jun 12, 2015 at 3:17 PM, Ed James <[hidden email]> wrote:

Hi Guan,

The deposit check is requesting a rate for the zerodate and hence getting a negative time of 1 day in years (for 360 days). Change the deposit check to this so you are actually asking for a rate on the deposit data point.

 

       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;

              Date l_DateToUse = pricingDate + (depositData[i].n*depositData[i].units);

              Rate estimatedRate = index.fixing(l_DateToUse);

              //if (std::fabs(estimatedRate - inputRate) > tolerance)

              cout << depositData[i].n*depositData[i].units << " (" << l_DateToUse << ") "

                     << " Deposit:"

                     << setprecision(8)

                     << "\n\t estimated rate: " << estimatedRate

                     << "\n\t input rate: " << inputRate

                     << endl;

       }

 

I get the following output – the deposit rates for 1M and 3M are off although the zero yield rates for 0M and 3M look better – I’m not sure why at the moment.

 

Thanks

Ed

 

 

zero date is January 22nd, 2014

Checking estimated rates against input...

1M (February 17th, 2014)  Deposit:

                estimated rate: 0.0020672531

                input rate: 0.00157

3M (April 17th, 2014)  Deposit:

                estimated rate: 0.0021845006

                input rate: 0.002366

5Y Swap :

                estimated rate: 0.0173377

                input rate: 0.0173377

6Y Swap :

                estimated rate: 0.02074532

                input rate: 0.02074532

7Y Swap :

                estimated rate: 0.0236113

                input rate: 0.0236113

8Y Swap :

                estimated rate: 0.02592213

                input rate: 0.02592213

9Y Swap :

                estimated rate: 0.02781181

                input rate: 0.02781181

10Y Swap :

                estimated rate: 0.02937271

                input rate: 0.02937271

15Y Swap :

                estimated rate: 0.03418712

                input rate: 0.03418712

30Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

35Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

40Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

45Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

50Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

Zero-yield Rates...

Zero 0M: January 22nd, 2014 0.001569887 discount factor 1

Zero 3M: April 22nd, 2014 0.0023653005 discount factor 0.99940885

Zero 6M: July 22nd, 2014 0.0022751584 discount factor 0.99885675

Zero 9M: October 22nd, 2014 0.0026115489 discount factor 0.99802154

Zero 12M: January 22nd, 2015 0.002851819 discount factor 0.99711275

Zero 15M: April 22nd, 2015 0.003226952 discount factor 0.9959298

Zero 18M: July 22nd, 2015 0.003708467 discount factor 0.99439128

Zero 21M: October 22nd, 2015 0.0043166678 discount factor 0.99237909

Zero 24M: January 22nd, 2016 0.0050454544 discount factor 0.9898211

Zero 27M: April 22nd, 2016 0.0058911916 discount factor 0.98665466

Zero 30M: July 22nd, 2016 0.006853368 discount factor 0.98278798

Zero 33M: October 22nd, 2016 0.0078990854 discount factor 0.97821121

Zero 36M: January 22nd, 2017 0.0089884804 discount factor 0.9730061

Zero 39M: April 22nd, 2017 0.010082293 discount factor 0.96733002

Zero 42M: July 22nd, 2017 0.011174645 discount factor 0.9611364

Zero 45M: October 22nd, 2017 0.012259943 discount factor 0.95444826

Zero 48M: January 22nd, 2018 0.013324237 discount factor 0.94736181

Zero 51M: April 22nd, 2018 0.014343294 discount factor 0.94007493

Zero 54M: July 22nd, 2018 0.015349671 discount factor 0.93238305

Zero 57M: October 22nd, 2018 0.016340753 discount factor 0.92430982

Zero 60M: January 22nd, 2019 0.017303495 discount factor 0.91597412

Zero 63M: April 22nd, 2019 0.018216268 discount factor 0.90760046

Zero 66M: July 22nd, 2019 0.019109012 discount factor 0.89894562

Zero 69M: October 22nd, 2019 0.019979907 discount factor 0.89003548

Zero 72M: January 22nd, 2020 0.02081814 discount factor 0.8809966

Zero 75M: April 22nd, 2020 0.02161429 discount factor 0.871961

Zero 78M: July 22nd, 2020 0.02237673 discount factor 0.86286249

Zero 81M: October 22nd, 2020 0.02311232 discount factor 0.85363191

Zero 84M: January 22nd, 2021 0.023811523 discount factor 0.84440085

Zero 87M: April 22nd, 2021 0.02446009 discount factor 0.83539584

Zero 90M: July 22nd, 2021 0.025082903 discount factor 0.82632311

Zero 93M: October 22nd, 2021 0.025682361 discount factor 0.81718326

Zero 96M: January 22nd, 2022 0.026254993 discount factor 0.80807288

Zero 99M: April 22nd, 2022 0.026792146 discount factor 0.79918649

Zero 102M: July 22nd, 2022 0.027312938 discount factor 0.79023702

Zero 105M: October 22nd, 2022 0.027816886 discount factor 0.78123845

Zero 108M: January 22nd, 2023 0.028298407 discount factor 0.77230157

Zero 111M: April 22nd, 2023 0.028748215 discount factor 0.76362822

Zero 114M: July 22nd, 2023 0.029182995 discount factor 0.75493055

Zero 117M: October 22nd, 2023 0.029603684 discount factor 0.7462105

Zero 120M: January 22nd, 2024 0.030007023 discount factor 0.73756241

Zero 123M: April 22nd, 2024 0.030390789 discount factor 0.72907418

Zero 126M: July 22nd, 2024 0.030760488 discount factor 0.7206518

Zero 129M: October 22nd, 2024 0.031120285 discount factor 0.71220891

Zero 132M: January 22nd, 2025 0.031466383 discount factor 0.70384311

Zero 135M: April 22nd, 2025 0.03179203 discount factor 0.69573782

Zero 138M: July 22nd, 2025 0.032108624 discount factor 0.68762516

Zero 141M: October 22nd, 2025 0.032416082 discount factor 0.67951111

Zero 144M: January 22nd, 2026 0.032711196 discount factor 0.67148821

Zero 147M: April 22nd, 2026 0.03298828 discount factor 0.66373031

Zero 150M: July 22nd, 2026 0.03325709 discount factor 0.65597933

Zero 153M: October 22nd, 2026 0.033517587 discount factor 0.6482401

Zero 156M: January 22nd, 2027 0.033767097 discount factor 0.64059972

Zero 159M: April 22nd, 2027 0.034000878 discount factor 0.63322212

Zero 162M: July 22nd, 2027 0.034227224 discount factor 0.62586052

Zero 165M: October 22nd, 2027 0.034446139 discount factor 0.61851863

Zero 168M: January 22nd, 2028 0.034655422 discount factor 0.6112781

Zero 171M: April 22nd, 2028 0.034853289 discount factor 0.60421592

Zero 174M: July 22nd, 2028 0.035042398 discount factor 0.59725252

Zero 177M: October 22nd, 2028 0.035225017 discount factor 0.59031249

Zero 180M: January 22nd, 2029 0.035399364 discount factor 0.58347209

Zero 183M: April 22nd, 2029 0.035563263 discount factor 0.57686678

Zero 186M: July 22nd, 2029 0.035723509 discount factor 0.57026567

Zero 189M: October 22nd, 2029 0.035880014 discount factor 0.56367193

Zero 192M: January 22nd, 2030 0.036031083 discount factor 0.55715903

Zero 195M: April 22nd, 2030 0.0361737 discount factor 0.5508663

Zero 198M: July 22nd, 2030 0.036312798 discount factor 0.54458294

Zero 201M: October 22nd, 2030 0.036448302 discount factor 0.53831177

Zero 204M: January 22nd, 2031 0.036578751 discount factor 0.53212234

Zero 207M: April 22nd, 2031 0.036701566 discount factor 0.52614657

Zero 210M: July 22nd, 2031 0.036821012 discount factor 0.52018385

Zero 213M: October 22nd, 2031 0.036937028 discount factor 0.51423665

Zero 216M: January 22nd, 2032 0.03704837 discount factor 0.50837069

Zero 219M: April 22nd, 2032 0.037153998 discount factor 0.50264808

Zero 222M: July 22nd, 2032 0.037255241 discount factor 0.49700425

Zero 225M: October 22nd, 2032 0.037353234 discount factor 0.49137804

Zero 228M: January 22nd, 2033 0.037446935 discount factor 0.48583137

Zero 231M: April 22nd, 2033 0.037534539 discount factor 0.4804817

Zero 234M: July 22nd, 2033 0.037619126 discount factor 0.47514882

Zero 237M: October 22nd, 2033 0.037700659 discount factor 0.46983458

Zero 240M: January 22nd, 2034 0.037778282 discount factor 0.46459728

Zero 243M: April 22nd, 2034 0.037850526 discount factor 0.45954754

Zero 246M: July 22nd, 2034 0.037919953 discount factor 0.454515

Zero 249M: October 22nd, 2034 0.037986539 discount factor 0.44950125

Zero 252M: January 22nd, 2035 0.038049596 discount factor 0.4445611

Zero 255M: April 22nd, 2035 0.038107959 discount factor 0.43979867

Zero 258M: July 22nd, 2035 0.038163723 discount factor 0.4350531

Zero 261M: October 22nd, 2035 0.038216873 discount factor 0.43032573

Zero 264M: January 22nd, 2036 0.038266876 discount factor 0.42566807

Zero 267M: April 22nd, 2036 0.038313333 discount factor 0.42112858

Zero 270M: July 22nd, 2036 0.038356897 discount factor 0.41665523

Zero 273M: October 22nd, 2036 0.038398095 discount factor 0.41219887

Zero 276M: January 22nd, 2037 0.038436527 discount factor 0.4078079

Zero 279M: April 22nd, 2037 0.03847154 discount factor 0.40357457

Zero 282M: July 22nd, 2037 0.038504436 discount factor 0.39935562

Zero 285M: October 22nd, 2037 0.038535227 discount factor 0.39515195

Zero 288M: January 22nd, 2038 0.038563634 discount factor 0.39100908

Zero 291M: April 22nd, 2038 0.038589209 discount factor 0.38701395

Zero 294M: July 22nd, 2038 0.038612933 discount factor 0.38303127

Zero 297M: October 22nd, 2038 0.038634831 discount factor 0.37906173

Zero 300M: January 22nd, 2039 0.038654725 discount factor 0.37514819

Zero 303M: April 22nd, 2039 0.038672341 discount factor 0.37137273

Zero 306M: July 22nd, 2039 0.038688389 discount factor 0.36760743

Zero 309M: October 22nd, 2039 0.038702905 discount factor 0.3638528

Zero 312M: January 22nd, 2040 0.038715799 discount factor 0.36014925

Zero 315M: April 22nd, 2040 0.038727052 discount factor 0.35653498

Zero 318M: July 22nd, 2040 0.038736905 discount factor 0.35296826

Zero 321M: October 22nd, 2040 0.038745538 discount factor 0.34940945

Zero 324M: January 22nd, 2041 0.038752931 discount factor 0.34589673

Zero 327M: April 22nd, 2041 0.038759057 discount factor 0.34250378

Zero 330M: July 22nd, 2041 0.038764229 discount factor 0.33911557

Zero 333M: October 22nd, 2041 0.038768509 discount factor 0.33573228

Zero 336M: January 22nd, 2042 0.038771931 discount factor 0.33239012

Zero 339M: April 22nd, 2042 0.03877454 discount factor 0.32915922

Zero 342M: July 22nd, 2042 0.038776529 discount factor 0.32593004

Zero 345M: October 22nd, 2042 0.038777969 discount factor 0.32270261

Zero 348M: January 22nd, 2043 0.038778931 discount factor 0.3195114

Zero 351M: April 22nd, 2043 0.038779504 discount factor 0.31642341

Zero 354M: July 22nd, 2043 0.038779803 discount factor 0.31333398

Zero 357M: October 22nd, 2043 0.038779915 discount factor 0.31024301

Zero 360M: January 22nd, 2044 0.038779931 discount factor 0.3071834

 

3m Forward Rates...

0 x 3 Fwd : 0.0023653005

3 x 6 Fwd : 0.0021860069

6 x 9 Fwd : 0.0032733606

9 x 12 Fwd : 0.0035647945

12 x 15 Fwd : 0.0047483244

15 x 18 Fwd : 0.0061160423

18 x 21 Fwd : 0.0079262072

21 x 24 Fwd : 0.010099431

24 x 27 Fwd : 0.012675677

27 x 30 Fwd : 0.015534102

30 x 33 Fwd : 0.018265327

33 x 36 Fwd : 0.020877095

36 x 39 Fwd : 0.023402501

39 x 42 Fwd : 0.025411231

42 x 45 Fwd : 0.027324354

45 x 48 Fwd : 0.029161396

48 x 51 Fwd : 0.030885983

51 x 54 Fwd : 0.032502315

54 x 57 Fwd : 0.034029417

57 x 60 Fwd : 0.035449091

60 x 63 Fwd : 0.036735406

63 x 66 Fwd : 0.037905685

66 x 69 Fwd : 0.038978677

69 x 72 Fwd : 0.039942605

72 x 75 Fwd : 0.04078315

75 x 78 Fwd : 0.041496367

78 x 81 Fwd : 0.042085756

81 x 84 Fwd : 0.042545605

84 x 87 Fwd : 0.042886573

87 x 90 Fwd : 0.043199236

90 x 93 Fwd : 0.043522775

93 x 96 Fwd : 0.043869627

96 x 99 Fwd : 0.044231727

99 x 102 Fwd : 0.044550577

102 x 105 Fwd : 0.04481419

105 x 108 Fwd : 0.045020768

108 x 111 Fwd : 0.045176223

111 x 114 Fwd : 0.045317632

114 x 117 Fwd : 0.045461827

117 x 120 Fwd : 0.045614485

120 x 123 Fwd : 0.045792055

123 x 126 Fwd : 0.04596687

126 x 129 Fwd : 0.04611445

129 x 132 Fwd : 0.046235741

132 x 135 Fwd : 0.046330338

135 x 138 Fwd : 0.046400593

138 x 141 Fwd : 0.046448871

141 x 144 Fwd : 0.046475719

144 x 147 Fwd : 0.046482225

147 x 150 Fwd : 0.046470149

150 x 153 Fwd : 0.046440521

153 x 156 Fwd : 0.046394441

156 x 159 Fwd : 0.046334137

159 x 162 Fwd : 0.046260894

162 x 165 Fwd : 0.046174758

165 x 168 Fwd : 0.046077263

168 x 171 Fwd : 0.045970816

171 x 174 Fwd : 0.045856891

174 x 177 Fwd : 0.045735577

177 x 180 Fwd : 0.04560813

180 x 183 Fwd : 0.045541077

183 x 186 Fwd : 0.045530178

186 x 189 Fwd : 0.045508462

189 x 192 Fwd : 0.045476174

192 x 195 Fwd : 0.045434309

195 x 198 Fwd : 0.045383208

198 x 201 Fwd : 0.045322345

201 x 204 Fwd : 0.045252216

204 x 207 Fwd : 0.045174418

207 x 210 Fwd : 0.045089064

210 x 213 Fwd : 0.044995071

213 x 216 Fwd : 0.044893149

216 x 219 Fwd : 0.044784786

219 x 222 Fwd : 0.044670457

222 x 225 Fwd : 0.044549284

225 x 228 Fwd : 0.044421557

228 x 231 Fwd : 0.044289787

231 x 234 Fwd : 0.044153728

234 x 237 Fwd : 0.044011474

237 x 240 Fwd : 0.043864071

240 x 243 Fwd : 0.043714334

243 x 246 Fwd : 0.043561893

246 x 249 Fwd : 0.043404574

249 x 252 Fwd : 0.043243543

252 x 255 Fwd : 0.043081824

255 x 258 Fwd : 0.04291895

258 x 261 Fwd : 0.042752583

261 x 264 Fwd : 0.042583974

264 x 267 Fwd : 0.042415333

267 x 270 Fwd : 0.042247049

270 x 273 Fwd : 0.042077651

273 x 276 Fwd : 0.041907517

276 x 279 Fwd : 0.041739792

279 x 282 Fwd : 0.041573917

282 x 285 Fwd : 0.04140752

285 x 288 Fwd : 0.041241923

288 x 291 Fwd : 0.041080184

291 x 294 Fwd : 0.040921743

294 x 297 Fwd : 0.040764365

297 x 300 Fwd : 0.040609354

300 x 303 Fwd : 0.040459583

303 x 306 Fwd : 0.040314529

306 x 309 Fwd : 0.040172185

309 x 312 Fwd : 0.04003381

312 x 315 Fwd : 0.039901286

315 x 318 Fwd : 0.039774917

318 x 321 Fwd : 0.039653689

321 x 324 Fwd : 0.039538069

324 x 327 Fwd : 0.03943026

327 x 330 Fwd : 0.039329909

330 x 333 Fwd : 0.039235765

333 x 336 Fwd : 0.039148896

336 x 339 Fwd : 0.039071023

339 x 342 Fwd : 0.039001926

342 x 345 Fwd : 0.038940882

345 x 348 Fwd : 0.038888814

348 x 351 Fwd : 0.03884686

351 x 354 Fwd : 0.038814969

354 x 357 Fwd : 0.038793041

357 x 360 Fwd : 0.038781823

360 x 363 Fwd : 0.03858163

 

 

From: Guan Wang [mailto:[hidden email]]
Sent: 11 June 2015 21:47
To: [hidden email]
Subject: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi,

 

I am trying to build a yield curve using the following inputs:

 

USD Libor 1m, 3m

EDF prices (12 of them, 3m apart, let's suppose convexity adjustment is zero)

Swap rates (5yr to 50yr)

 

To be able to interpolate with swap rates, I have to set my calendar to be the joint calendar of US and UK. Theses are the errors I am getting:

 

For pricing date 1/17/2014:

negative time (-0.00277778) given

 

For pricing date 2/13/2014:

interpolation range is [0.0777778, 7.10278]: extrapolation at 0.075 not allowed

 

To avoid out of range errors, I also have to enable extrapolation for the yield curve builder.

 

Can anybody help me with this? The stand alone code is as follows:

 

#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 ;

}

 

}

 

 


------------------------------------------------------------------------------

_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Piecewise Yield Curve Errors

Neo G.W.
In the sample code peicewiseyieldcurve.cpp, vars.today is equivalent to my pricingDate, and vars.settlement, which is 2 business days after vars.today, is equivalent to my zeroDate. The reference dates of the curveHandle term structure are vars.settlement and zeroDate respectively. I do not find any inconsistency in terms of the reference date between the sample program and mine.

The exception is thrown on that line. However, I am not sure it is a systematic error related to the reference date. The term structure "knows" about the pricingDate when you do this:

Settings::instance().evaluationDate() = pricingDate;


In fact, if you change my pricingDate to any date other than 20140117, in most cases the program will work just fine.

Yours,
Guan

On Fri, Jun 12, 2015 at 7:46 PM, Ed James <[hidden email]> wrote:

Hi Guan,

          In your original code you had a pricingDate = 20140117 and a zeroDate = 20140122. The term structure is set up using the zeroDate as its reference date as follows:

 

boost::shared_ptr <QuantLib::YieldTermStructure> yieldCurve = boost::shared_ptr < YieldTermStructure >( new PiecewiseYieldCurve < ZeroYield , Cubic, IterativeBootstrap >( zeroDate , instruments , dc, myCubic));

 

You then have a LiborIndex which takes a handle to the term structure as follows:

 

Libor index("USDLibor", depositData[i].n*depositData[i].units, 2,

USDCurrency(),

calendar,

Actual360(), ycHandle);

 

You then try and calculate a rate for the pricingDate as follows:

 

estimatedRate = index.fixing(pricingDate);

 

So the pricingDate here is before the reference date of the term structure so you get a negative number of days and it throws an exception, that’s what I got when I stepped through the code, it subtracts the reference date from the date you pass in and the result has to be positive. The term structure can’t be used for dates before its reference date. In the function testCurveConsistency() what’s the relationship between the vars.today date and the reference date of the curveHandle term structure ?

 

Can you try stepping through your original code and confirm that you see an exception thrown on this line:

 

estimatedRate = index.fixing(pricingDate);

 

Thanks

Ed

 

From: Guan Wang [mailto:[hidden email]]
Sent: 12 June 2015 20:49
To: Ed James
Cc: [hidden email]
Subject: Re: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi Ed,

 

I am not sure about the change you made in the deposit check. If you take a look at ../quantlib/1.5/test-suite/piecewiseyieldcurve.cpp, in the function testCurveConsistency():

 

Euribor index(depositData[i].n*depositData[i].units,curveHandle);

Rate expectedRate = depositData[i].rate/100,

estimatedRate = index.fixing(vars.today);

 

In my code the pricing date is equivalent to "today" here. The sample driver program seems to suggest using pricing date to index fixing. Your change is not exactly in accordance with the sample code, is it? As a result, the 1M and 3M estimated rates are quite off.

 

Thanks!

Guan

 

On Fri, Jun 12, 2015 at 3:17 PM, Ed James <[hidden email]> wrote:

Hi Guan,

The deposit check is requesting a rate for the zerodate and hence getting a negative time of 1 day in years (for 360 days). Change the deposit check to this so you are actually asking for a rate on the deposit data point.

 

       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;

              Date l_DateToUse = pricingDate + (depositData[i].n*depositData[i].units);

              Rate estimatedRate = index.fixing(l_DateToUse);

              //if (std::fabs(estimatedRate - inputRate) > tolerance)

              cout << depositData[i].n*depositData[i].units << " (" << l_DateToUse << ") "

                     << " Deposit:"

                     << setprecision(8)

                     << "\n\t estimated rate: " << estimatedRate

                     << "\n\t input rate: " << inputRate

                     << endl;

       }

 

I get the following output – the deposit rates for 1M and 3M are off although the zero yield rates for 0M and 3M look better – I’m not sure why at the moment.

 

Thanks

Ed

 

 

zero date is January 22nd, 2014

Checking estimated rates against input...

1M (February 17th, 2014)  Deposit:

                estimated rate: 0.0020672531

                input rate: 0.00157

3M (April 17th, 2014)  Deposit:

                estimated rate: 0.0021845006

                input rate: 0.002366

5Y Swap :

                estimated rate: 0.0173377

                input rate: 0.0173377

6Y Swap :

                estimated rate: 0.02074532

                input rate: 0.02074532

7Y Swap :

                estimated rate: 0.0236113

                input rate: 0.0236113

8Y Swap :

                estimated rate: 0.02592213

                input rate: 0.02592213

9Y Swap :

                estimated rate: 0.02781181

                input rate: 0.02781181

10Y Swap :

                estimated rate: 0.02937271

                input rate: 0.02937271

15Y Swap :

                estimated rate: 0.03418712

                input rate: 0.03418712

30Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

35Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

40Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

45Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

50Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

Zero-yield Rates...

Zero 0M: January 22nd, 2014 0.001569887 discount factor 1

Zero 3M: April 22nd, 2014 0.0023653005 discount factor 0.99940885

Zero 6M: July 22nd, 2014 0.0022751584 discount factor 0.99885675

Zero 9M: October 22nd, 2014 0.0026115489 discount factor 0.99802154

Zero 12M: January 22nd, 2015 0.002851819 discount factor 0.99711275

Zero 15M: April 22nd, 2015 0.003226952 discount factor 0.9959298

Zero 18M: July 22nd, 2015 0.003708467 discount factor 0.99439128

Zero 21M: October 22nd, 2015 0.0043166678 discount factor 0.99237909

Zero 24M: January 22nd, 2016 0.0050454544 discount factor 0.9898211

Zero 27M: April 22nd, 2016 0.0058911916 discount factor 0.98665466

Zero 30M: July 22nd, 2016 0.006853368 discount factor 0.98278798

Zero 33M: October 22nd, 2016 0.0078990854 discount factor 0.97821121

Zero 36M: January 22nd, 2017 0.0089884804 discount factor 0.9730061

Zero 39M: April 22nd, 2017 0.010082293 discount factor 0.96733002

Zero 42M: July 22nd, 2017 0.011174645 discount factor 0.9611364

Zero 45M: October 22nd, 2017 0.012259943 discount factor 0.95444826

Zero 48M: January 22nd, 2018 0.013324237 discount factor 0.94736181

Zero 51M: April 22nd, 2018 0.014343294 discount factor 0.94007493

Zero 54M: July 22nd, 2018 0.015349671 discount factor 0.93238305

Zero 57M: October 22nd, 2018 0.016340753 discount factor 0.92430982

Zero 60M: January 22nd, 2019 0.017303495 discount factor 0.91597412

Zero 63M: April 22nd, 2019 0.018216268 discount factor 0.90760046

Zero 66M: July 22nd, 2019 0.019109012 discount factor 0.89894562

Zero 69M: October 22nd, 2019 0.019979907 discount factor 0.89003548

Zero 72M: January 22nd, 2020 0.02081814 discount factor 0.8809966

Zero 75M: April 22nd, 2020 0.02161429 discount factor 0.871961

Zero 78M: July 22nd, 2020 0.02237673 discount factor 0.86286249

Zero 81M: October 22nd, 2020 0.02311232 discount factor 0.85363191

Zero 84M: January 22nd, 2021 0.023811523 discount factor 0.84440085

Zero 87M: April 22nd, 2021 0.02446009 discount factor 0.83539584

Zero 90M: July 22nd, 2021 0.025082903 discount factor 0.82632311

Zero 93M: October 22nd, 2021 0.025682361 discount factor 0.81718326

Zero 96M: January 22nd, 2022 0.026254993 discount factor 0.80807288

Zero 99M: April 22nd, 2022 0.026792146 discount factor 0.79918649

Zero 102M: July 22nd, 2022 0.027312938 discount factor 0.79023702

Zero 105M: October 22nd, 2022 0.027816886 discount factor 0.78123845

Zero 108M: January 22nd, 2023 0.028298407 discount factor 0.77230157

Zero 111M: April 22nd, 2023 0.028748215 discount factor 0.76362822

Zero 114M: July 22nd, 2023 0.029182995 discount factor 0.75493055

Zero 117M: October 22nd, 2023 0.029603684 discount factor 0.7462105

Zero 120M: January 22nd, 2024 0.030007023 discount factor 0.73756241

Zero 123M: April 22nd, 2024 0.030390789 discount factor 0.72907418

Zero 126M: July 22nd, 2024 0.030760488 discount factor 0.7206518

Zero 129M: October 22nd, 2024 0.031120285 discount factor 0.71220891

Zero 132M: January 22nd, 2025 0.031466383 discount factor 0.70384311

Zero 135M: April 22nd, 2025 0.03179203 discount factor 0.69573782

Zero 138M: July 22nd, 2025 0.032108624 discount factor 0.68762516

Zero 141M: October 22nd, 2025 0.032416082 discount factor 0.67951111

Zero 144M: January 22nd, 2026 0.032711196 discount factor 0.67148821

Zero 147M: April 22nd, 2026 0.03298828 discount factor 0.66373031

Zero 150M: July 22nd, 2026 0.03325709 discount factor 0.65597933

Zero 153M: October 22nd, 2026 0.033517587 discount factor 0.6482401

Zero 156M: January 22nd, 2027 0.033767097 discount factor 0.64059972

Zero 159M: April 22nd, 2027 0.034000878 discount factor 0.63322212

Zero 162M: July 22nd, 2027 0.034227224 discount factor 0.62586052

Zero 165M: October 22nd, 2027 0.034446139 discount factor 0.61851863

Zero 168M: January 22nd, 2028 0.034655422 discount factor 0.6112781

Zero 171M: April 22nd, 2028 0.034853289 discount factor 0.60421592

Zero 174M: July 22nd, 2028 0.035042398 discount factor 0.59725252

Zero 177M: October 22nd, 2028 0.035225017 discount factor 0.59031249

Zero 180M: January 22nd, 2029 0.035399364 discount factor 0.58347209

Zero 183M: April 22nd, 2029 0.035563263 discount factor 0.57686678

Zero 186M: July 22nd, 2029 0.035723509 discount factor 0.57026567

Zero 189M: October 22nd, 2029 0.035880014 discount factor 0.56367193

Zero 192M: January 22nd, 2030 0.036031083 discount factor 0.55715903

Zero 195M: April 22nd, 2030 0.0361737 discount factor 0.5508663

Zero 198M: July 22nd, 2030 0.036312798 discount factor 0.54458294

Zero 201M: October 22nd, 2030 0.036448302 discount factor 0.53831177

Zero 204M: January 22nd, 2031 0.036578751 discount factor 0.53212234

Zero 207M: April 22nd, 2031 0.036701566 discount factor 0.52614657

Zero 210M: July 22nd, 2031 0.036821012 discount factor 0.52018385

Zero 213M: October 22nd, 2031 0.036937028 discount factor 0.51423665

Zero 216M: January 22nd, 2032 0.03704837 discount factor 0.50837069

Zero 219M: April 22nd, 2032 0.037153998 discount factor 0.50264808

Zero 222M: July 22nd, 2032 0.037255241 discount factor 0.49700425

Zero 225M: October 22nd, 2032 0.037353234 discount factor 0.49137804

Zero 228M: January 22nd, 2033 0.037446935 discount factor 0.48583137

Zero 231M: April 22nd, 2033 0.037534539 discount factor 0.4804817

Zero 234M: July 22nd, 2033 0.037619126 discount factor 0.47514882

Zero 237M: October 22nd, 2033 0.037700659 discount factor 0.46983458

Zero 240M: January 22nd, 2034 0.037778282 discount factor 0.46459728

Zero 243M: April 22nd, 2034 0.037850526 discount factor 0.45954754

Zero 246M: July 22nd, 2034 0.037919953 discount factor 0.454515

Zero 249M: October 22nd, 2034 0.037986539 discount factor 0.44950125

Zero 252M: January 22nd, 2035 0.038049596 discount factor 0.4445611

Zero 255M: April 22nd, 2035 0.038107959 discount factor 0.43979867

Zero 258M: July 22nd, 2035 0.038163723 discount factor 0.4350531

Zero 261M: October 22nd, 2035 0.038216873 discount factor 0.43032573

Zero 264M: January 22nd, 2036 0.038266876 discount factor 0.42566807

Zero 267M: April 22nd, 2036 0.038313333 discount factor 0.42112858

Zero 270M: July 22nd, 2036 0.038356897 discount factor 0.41665523

Zero 273M: October 22nd, 2036 0.038398095 discount factor 0.41219887

Zero 276M: January 22nd, 2037 0.038436527 discount factor 0.4078079

Zero 279M: April 22nd, 2037 0.03847154 discount factor 0.40357457

Zero 282M: July 22nd, 2037 0.038504436 discount factor 0.39935562

Zero 285M: October 22nd, 2037 0.038535227 discount factor 0.39515195

Zero 288M: January 22nd, 2038 0.038563634 discount factor 0.39100908

Zero 291M: April 22nd, 2038 0.038589209 discount factor 0.38701395

Zero 294M: July 22nd, 2038 0.038612933 discount factor 0.38303127

Zero 297M: October 22nd, 2038 0.038634831 discount factor 0.37906173

Zero 300M: January 22nd, 2039 0.038654725 discount factor 0.37514819

Zero 303M: April 22nd, 2039 0.038672341 discount factor 0.37137273

Zero 306M: July 22nd, 2039 0.038688389 discount factor 0.36760743

Zero 309M: October 22nd, 2039 0.038702905 discount factor 0.3638528

Zero 312M: January 22nd, 2040 0.038715799 discount factor 0.36014925

Zero 315M: April 22nd, 2040 0.038727052 discount factor 0.35653498

Zero 318M: July 22nd, 2040 0.038736905 discount factor 0.35296826

Zero 321M: October 22nd, 2040 0.038745538 discount factor 0.34940945

Zero 324M: January 22nd, 2041 0.038752931 discount factor 0.34589673

Zero 327M: April 22nd, 2041 0.038759057 discount factor 0.34250378

Zero 330M: July 22nd, 2041 0.038764229 discount factor 0.33911557

Zero 333M: October 22nd, 2041 0.038768509 discount factor 0.33573228

Zero 336M: January 22nd, 2042 0.038771931 discount factor 0.33239012

Zero 339M: April 22nd, 2042 0.03877454 discount factor 0.32915922

Zero 342M: July 22nd, 2042 0.038776529 discount factor 0.32593004

Zero 345M: October 22nd, 2042 0.038777969 discount factor 0.32270261

Zero 348M: January 22nd, 2043 0.038778931 discount factor 0.3195114

Zero 351M: April 22nd, 2043 0.038779504 discount factor 0.31642341

Zero 354M: July 22nd, 2043 0.038779803 discount factor 0.31333398

Zero 357M: October 22nd, 2043 0.038779915 discount factor 0.31024301

Zero 360M: January 22nd, 2044 0.038779931 discount factor 0.3071834

 

3m Forward Rates...

0 x 3 Fwd : 0.0023653005

3 x 6 Fwd : 0.0021860069

6 x 9 Fwd : 0.0032733606

9 x 12 Fwd : 0.0035647945

12 x 15 Fwd : 0.0047483244

15 x 18 Fwd : 0.0061160423

18 x 21 Fwd : 0.0079262072

21 x 24 Fwd : 0.010099431

24 x 27 Fwd : 0.012675677

27 x 30 Fwd : 0.015534102

30 x 33 Fwd : 0.018265327

33 x 36 Fwd : 0.020877095

36 x 39 Fwd : 0.023402501

39 x 42 Fwd : 0.025411231

42 x 45 Fwd : 0.027324354

45 x 48 Fwd : 0.029161396

48 x 51 Fwd : 0.030885983

51 x 54 Fwd : 0.032502315

54 x 57 Fwd : 0.034029417

57 x 60 Fwd : 0.035449091

60 x 63 Fwd : 0.036735406

63 x 66 Fwd : 0.037905685

66 x 69 Fwd : 0.038978677

69 x 72 Fwd : 0.039942605

72 x 75 Fwd : 0.04078315

75 x 78 Fwd : 0.041496367

78 x 81 Fwd : 0.042085756

81 x 84 Fwd : 0.042545605

84 x 87 Fwd : 0.042886573

87 x 90 Fwd : 0.043199236

90 x 93 Fwd : 0.043522775

93 x 96 Fwd : 0.043869627

96 x 99 Fwd : 0.044231727

99 x 102 Fwd : 0.044550577

102 x 105 Fwd : 0.04481419

105 x 108 Fwd : 0.045020768

108 x 111 Fwd : 0.045176223

111 x 114 Fwd : 0.045317632

114 x 117 Fwd : 0.045461827

117 x 120 Fwd : 0.045614485

120 x 123 Fwd : 0.045792055

123 x 126 Fwd : 0.04596687

126 x 129 Fwd : 0.04611445

129 x 132 Fwd : 0.046235741

132 x 135 Fwd : 0.046330338

135 x 138 Fwd : 0.046400593

138 x 141 Fwd : 0.046448871

141 x 144 Fwd : 0.046475719

144 x 147 Fwd : 0.046482225

147 x 150 Fwd : 0.046470149

150 x 153 Fwd : 0.046440521

153 x 156 Fwd : 0.046394441

156 x 159 Fwd : 0.046334137

159 x 162 Fwd : 0.046260894

162 x 165 Fwd : 0.046174758

165 x 168 Fwd : 0.046077263

168 x 171 Fwd : 0.045970816

171 x 174 Fwd : 0.045856891

174 x 177 Fwd : 0.045735577

177 x 180 Fwd : 0.04560813

180 x 183 Fwd : 0.045541077

183 x 186 Fwd : 0.045530178

186 x 189 Fwd : 0.045508462

189 x 192 Fwd : 0.045476174

192 x 195 Fwd : 0.045434309

195 x 198 Fwd : 0.045383208

198 x 201 Fwd : 0.045322345

201 x 204 Fwd : 0.045252216

204 x 207 Fwd : 0.045174418

207 x 210 Fwd : 0.045089064

210 x 213 Fwd : 0.044995071

213 x 216 Fwd : 0.044893149

216 x 219 Fwd : 0.044784786

219 x 222 Fwd : 0.044670457

222 x 225 Fwd : 0.044549284

225 x 228 Fwd : 0.044421557

228 x 231 Fwd : 0.044289787

231 x 234 Fwd : 0.044153728

234 x 237 Fwd : 0.044011474

237 x 240 Fwd : 0.043864071

240 x 243 Fwd : 0.043714334

243 x 246 Fwd : 0.043561893

246 x 249 Fwd : 0.043404574

249 x 252 Fwd : 0.043243543

252 x 255 Fwd : 0.043081824

255 x 258 Fwd : 0.04291895

258 x 261 Fwd : 0.042752583

261 x 264 Fwd : 0.042583974

264 x 267 Fwd : 0.042415333

267 x 270 Fwd : 0.042247049

270 x 273 Fwd : 0.042077651

273 x 276 Fwd : 0.041907517

276 x 279 Fwd : 0.041739792

279 x 282 Fwd : 0.041573917

282 x 285 Fwd : 0.04140752

285 x 288 Fwd : 0.041241923

288 x 291 Fwd : 0.041080184

291 x 294 Fwd : 0.040921743

294 x 297 Fwd : 0.040764365

297 x 300 Fwd : 0.040609354

300 x 303 Fwd : 0.040459583

303 x 306 Fwd : 0.040314529

306 x 309 Fwd : 0.040172185

309 x 312 Fwd : 0.04003381

312 x 315 Fwd : 0.039901286

315 x 318 Fwd : 0.039774917

318 x 321 Fwd : 0.039653689

321 x 324 Fwd : 0.039538069

324 x 327 Fwd : 0.03943026

327 x 330 Fwd : 0.039329909

330 x 333 Fwd : 0.039235765

333 x 336 Fwd : 0.039148896

336 x 339 Fwd : 0.039071023

339 x 342 Fwd : 0.039001926

342 x 345 Fwd : 0.038940882

345 x 348 Fwd : 0.038888814

348 x 351 Fwd : 0.03884686

351 x 354 Fwd : 0.038814969

354 x 357 Fwd : 0.038793041

357 x 360 Fwd : 0.038781823

360 x 363 Fwd : 0.03858163

 

 

From: Guan Wang [mailto:[hidden email]]
Sent: 11 June 2015 21:47
To: [hidden email]
Subject: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi,

 

I am trying to build a yield curve using the following inputs:

 

USD Libor 1m, 3m

EDF prices (12 of them, 3m apart, let's suppose convexity adjustment is zero)

Swap rates (5yr to 50yr)

 

To be able to interpolate with swap rates, I have to set my calendar to be the joint calendar of US and UK. Theses are the errors I am getting:

 

For pricing date 1/17/2014:

negative time (-0.00277778) given

 

For pricing date 2/13/2014:

interpolation range is [0.0777778, 7.10278]: extrapolation at 0.075 not allowed

 

To avoid out of range errors, I also have to enable extrapolation for the yield curve builder.

 

Can anybody help me with this? The stand alone code is as follows:

 

#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 ;

}

 

}

 

 



------------------------------------------------------------------------------

_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Piecewise Yield Curve Errors

Luigi Ballabio
Hello,
     I haven't had time to step through your code and go into details, but it might have to do with your choice of the calendar. The USD Libor is fixed in London, so its fixing dates don't take US holidays into account. The joint calendar is giving you January 22nd as the spot date, so you're using that as the reference date for the curve, but the Libor fixing at the pricing date will need a discount for January 21st (that is, what the Libor thinks is the spot date) and the curve complains about the date being before its reference date. If you use the UK calendar, I still see discrepancies in the swap rates that should be investigated, but the code at least runs.

Luigi
 

On Tue, Jun 16, 2015 at 11:34 AM Guan Wang <[hidden email]> wrote:
In the sample code peicewiseyieldcurve.cpp, vars.today is equivalent to my pricingDate, and vars.settlement, which is 2 business days after vars.today, is equivalent to my zeroDate. The reference dates of the curveHandle term structure are vars.settlement and zeroDate respectively. I do not find any inconsistency in terms of the reference date between the sample program and mine.

The exception is thrown on that line. However, I am not sure it is a systematic error related to the reference date. The term structure "knows" about the pricingDate when you do this:

Settings::instance().evaluationDate() = pricingDate;


In fact, if you change my pricingDate to any date other than 20140117, in most cases the program will work just fine.

Yours,
Guan

On Fri, Jun 12, 2015 at 7:46 PM, Ed James <[hidden email]> wrote:

Hi Guan,

          In your original code you had a pricingDate = 20140117 and a zeroDate = 20140122. The term structure is set up using the zeroDate as its reference date as follows:

 

boost::shared_ptr <QuantLib::YieldTermStructure> yieldCurve = boost::shared_ptr < YieldTermStructure >( new PiecewiseYieldCurve < ZeroYield , Cubic, IterativeBootstrap >( zeroDate , instruments , dc, myCubic));

 

You then have a LiborIndex which takes a handle to the term structure as follows:

 

Libor index("USDLibor", depositData[i].n*depositData[i].units, 2,

USDCurrency(),

calendar,

Actual360(), ycHandle);

 

You then try and calculate a rate for the pricingDate as follows:

 

estimatedRate = index.fixing(pricingDate);

 

So the pricingDate here is before the reference date of the term structure so you get a negative number of days and it throws an exception, that’s what I got when I stepped through the code, it subtracts the reference date from the date you pass in and the result has to be positive. The term structure can’t be used for dates before its reference date. In the function testCurveConsistency() what’s the relationship between the vars.today date and the reference date of the curveHandle term structure ?

 

Can you try stepping through your original code and confirm that you see an exception thrown on this line:

 

estimatedRate = index.fixing(pricingDate);

 

Thanks

Ed

 

From: Guan Wang [mailto:[hidden email]]
Sent: 12 June 2015 20:49
To: Ed James
Cc: [hidden email]
Subject: Re: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi Ed,

 

I am not sure about the change you made in the deposit check. If you take a look at ../quantlib/1.5/test-suite/piecewiseyieldcurve.cpp, in the function testCurveConsistency():

 

Euribor index(depositData[i].n*depositData[i].units,curveHandle);

Rate expectedRate = depositData[i].rate/100,

estimatedRate = index.fixing(vars.today);

 

In my code the pricing date is equivalent to "today" here. The sample driver program seems to suggest using pricing date to index fixing. Your change is not exactly in accordance with the sample code, is it? As a result, the 1M and 3M estimated rates are quite off.

 

Thanks!

Guan

On Fri, Jun 12, 2015 at 3:17 PM, Ed James <[hidden email]> wrote:

Hi Guan,

The deposit check is requesting a rate for the zerodate and hence getting a negative time of 1 day in years (for 360 days). Change the deposit check to this so you are actually asking for a rate on the deposit data point.

 

       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;

              Date l_DateToUse = pricingDate + (depositData[i].n*depositData[i].units);

              Rate estimatedRate = index.fixing(l_DateToUse);

              //if (std::fabs(estimatedRate - inputRate) > tolerance)

              cout << depositData[i].n*depositData[i].units << " (" << l_DateToUse << ") "

                     << " Deposit:"

                     << setprecision(8)

                     << "\n\t estimated rate: " << estimatedRate

                     << "\n\t input rate: " << inputRate

                     << endl;

       }

 

I get the following output – the deposit rates for 1M and 3M are off although the zero yield rates for 0M and 3M look better – I’m not sure why at the moment.

 

Thanks

Ed

 

 

zero date is January 22nd, 2014

Checking estimated rates against input...

1M (February 17th, 2014)  Deposit:

                estimated rate: 0.0020672531

                input rate: 0.00157

3M (April 17th, 2014)  Deposit:

                estimated rate: 0.0021845006

                input rate: 0.002366

5Y Swap :

                estimated rate: 0.0173377

                input rate: 0.0173377

6Y Swap :

                estimated rate: 0.02074532

                input rate: 0.02074532

7Y Swap :

                estimated rate: 0.0236113

                input rate: 0.0236113

8Y Swap :

                estimated rate: 0.02592213

                input rate: 0.02592213

9Y Swap :

                estimated rate: 0.02781181

                input rate: 0.02781181

10Y Swap :

                estimated rate: 0.02937271

                input rate: 0.02937271

15Y Swap :

                estimated rate: 0.03418712

                input rate: 0.03418712

30Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

35Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

40Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

45Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

50Y Swap :

                estimated rate: 0.03742963

                input rate: 0.03742963

Zero-yield Rates...

Zero 0M: January 22nd, 2014 0.001569887 discount factor 1

Zero 3M: April 22nd, 2014 0.0023653005 discount factor 0.99940885

Zero 6M: July 22nd, 2014 0.0022751584 discount factor 0.99885675

Zero 9M: October 22nd, 2014 0.0026115489 discount factor 0.99802154

Zero 12M: January 22nd, 2015 0.002851819 discount factor 0.99711275

Zero 15M: April 22nd, 2015 0.003226952 discount factor 0.9959298

Zero 18M: July 22nd, 2015 0.003708467 discount factor 0.99439128

Zero 21M: October 22nd, 2015 0.0043166678 discount factor 0.99237909

Zero 24M: January 22nd, 2016 0.0050454544 discount factor 0.9898211

Zero 27M: April 22nd, 2016 0.0058911916 discount factor 0.98665466

Zero 30M: July 22nd, 2016 0.006853368 discount factor 0.98278798

Zero 33M: October 22nd, 2016 0.0078990854 discount factor 0.97821121

Zero 36M: January 22nd, 2017 0.0089884804 discount factor 0.9730061

Zero 39M: April 22nd, 2017 0.010082293 discount factor 0.96733002

Zero 42M: July 22nd, 2017 0.011174645 discount factor 0.9611364

Zero 45M: October 22nd, 2017 0.012259943 discount factor 0.95444826

Zero 48M: January 22nd, 2018 0.013324237 discount factor 0.94736181

Zero 51M: April 22nd, 2018 0.014343294 discount factor 0.94007493

Zero 54M: July 22nd, 2018 0.015349671 discount factor 0.93238305

Zero 57M: October 22nd, 2018 0.016340753 discount factor 0.92430982

Zero 60M: January 22nd, 2019 0.017303495 discount factor 0.91597412

Zero 63M: April 22nd, 2019 0.018216268 discount factor 0.90760046

Zero 66M: July 22nd, 2019 0.019109012 discount factor 0.89894562

Zero 69M: October 22nd, 2019 0.019979907 discount factor 0.89003548

Zero 72M: January 22nd, 2020 0.02081814 discount factor 0.8809966

Zero 75M: April 22nd, 2020 0.02161429 discount factor 0.871961

Zero 78M: July 22nd, 2020 0.02237673 discount factor 0.86286249

Zero 81M: October 22nd, 2020 0.02311232 discount factor 0.85363191

Zero 84M: January 22nd, 2021 0.023811523 discount factor 0.84440085

Zero 87M: April 22nd, 2021 0.02446009 discount factor 0.83539584

Zero 90M: July 22nd, 2021 0.025082903 discount factor 0.82632311

Zero 93M: October 22nd, 2021 0.025682361 discount factor 0.81718326

Zero 96M: January 22nd, 2022 0.026254993 discount factor 0.80807288

Zero 99M: April 22nd, 2022 0.026792146 discount factor 0.79918649

Zero 102M: July 22nd, 2022 0.027312938 discount factor 0.79023702

Zero 105M: October 22nd, 2022 0.027816886 discount factor 0.78123845

Zero 108M: January 22nd, 2023 0.028298407 discount factor 0.77230157

Zero 111M: April 22nd, 2023 0.028748215 discount factor 0.76362822

Zero 114M: July 22nd, 2023 0.029182995 discount factor 0.75493055

Zero 117M: October 22nd, 2023 0.029603684 discount factor 0.7462105

Zero 120M: January 22nd, 2024 0.030007023 discount factor 0.73756241

Zero 123M: April 22nd, 2024 0.030390789 discount factor 0.72907418

Zero 126M: July 22nd, 2024 0.030760488 discount factor 0.7206518

Zero 129M: October 22nd, 2024 0.031120285 discount factor 0.71220891

Zero 132M: January 22nd, 2025 0.031466383 discount factor 0.70384311

Zero 135M: April 22nd, 2025 0.03179203 discount factor 0.69573782

Zero 138M: July 22nd, 2025 0.032108624 discount factor 0.68762516

Zero 141M: October 22nd, 2025 0.032416082 discount factor 0.67951111

Zero 144M: January 22nd, 2026 0.032711196 discount factor 0.67148821

Zero 147M: April 22nd, 2026 0.03298828 discount factor 0.66373031

Zero 150M: July 22nd, 2026 0.03325709 discount factor 0.65597933

Zero 153M: October 22nd, 2026 0.033517587 discount factor 0.6482401

Zero 156M: January 22nd, 2027 0.033767097 discount factor 0.64059972

Zero 159M: April 22nd, 2027 0.034000878 discount factor 0.63322212

Zero 162M: July 22nd, 2027 0.034227224 discount factor 0.62586052

Zero 165M: October 22nd, 2027 0.034446139 discount factor 0.61851863

Zero 168M: January 22nd, 2028 0.034655422 discount factor 0.6112781

Zero 171M: April 22nd, 2028 0.034853289 discount factor 0.60421592

Zero 174M: July 22nd, 2028 0.035042398 discount factor 0.59725252

Zero 177M: October 22nd, 2028 0.035225017 discount factor 0.59031249

Zero 180M: January 22nd, 2029 0.035399364 discount factor 0.58347209

Zero 183M: April 22nd, 2029 0.035563263 discount factor 0.57686678

Zero 186M: July 22nd, 2029 0.035723509 discount factor 0.57026567

Zero 189M: October 22nd, 2029 0.035880014 discount factor 0.56367193

Zero 192M: January 22nd, 2030 0.036031083 discount factor 0.55715903

Zero 195M: April 22nd, 2030 0.0361737 discount factor 0.5508663

Zero 198M: July 22nd, 2030 0.036312798 discount factor 0.54458294

Zero 201M: October 22nd, 2030 0.036448302 discount factor 0.53831177

Zero 204M: January 22nd, 2031 0.036578751 discount factor 0.53212234

Zero 207M: April 22nd, 2031 0.036701566 discount factor 0.52614657

Zero 210M: July 22nd, 2031 0.036821012 discount factor 0.52018385

Zero 213M: October 22nd, 2031 0.036937028 discount factor 0.51423665

Zero 216M: January 22nd, 2032 0.03704837 discount factor 0.50837069

Zero 219M: April 22nd, 2032 0.037153998 discount factor 0.50264808

Zero 222M: July 22nd, 2032 0.037255241 discount factor 0.49700425

Zero 225M: October 22nd, 2032 0.037353234 discount factor 0.49137804

Zero 228M: January 22nd, 2033 0.037446935 discount factor 0.48583137

Zero 231M: April 22nd, 2033 0.037534539 discount factor 0.4804817

Zero 234M: July 22nd, 2033 0.037619126 discount factor 0.47514882

Zero 237M: October 22nd, 2033 0.037700659 discount factor 0.46983458

Zero 240M: January 22nd, 2034 0.037778282 discount factor 0.46459728

Zero 243M: April 22nd, 2034 0.037850526 discount factor 0.45954754

Zero 246M: July 22nd, 2034 0.037919953 discount factor 0.454515

Zero 249M: October 22nd, 2034 0.037986539 discount factor 0.44950125

Zero 252M: January 22nd, 2035 0.038049596 discount factor 0.4445611

Zero 255M: April 22nd, 2035 0.038107959 discount factor 0.43979867

Zero 258M: July 22nd, 2035 0.038163723 discount factor 0.4350531

Zero 261M: October 22nd, 2035 0.038216873 discount factor 0.43032573

Zero 264M: January 22nd, 2036 0.038266876 discount factor 0.42566807

Zero 267M: April 22nd, 2036 0.038313333 discount factor 0.42112858

Zero 270M: July 22nd, 2036 0.038356897 discount factor 0.41665523

Zero 273M: October 22nd, 2036 0.038398095 discount factor 0.41219887

Zero 276M: January 22nd, 2037 0.038436527 discount factor 0.4078079

Zero 279M: April 22nd, 2037 0.03847154 discount factor 0.40357457

Zero 282M: July 22nd, 2037 0.038504436 discount factor 0.39935562

Zero 285M: October 22nd, 2037 0.038535227 discount factor 0.39515195

Zero 288M: January 22nd, 2038 0.038563634 discount factor 0.39100908

Zero 291M: April 22nd, 2038 0.038589209 discount factor 0.38701395

Zero 294M: July 22nd, 2038 0.038612933 discount factor 0.38303127

Zero 297M: October 22nd, 2038 0.038634831 discount factor 0.37906173

Zero 300M: January 22nd, 2039 0.038654725 discount factor 0.37514819

Zero 303M: April 22nd, 2039 0.038672341 discount factor 0.37137273

Zero 306M: July 22nd, 2039 0.038688389 discount factor 0.36760743

Zero 309M: October 22nd, 2039 0.038702905 discount factor 0.3638528

Zero 312M: January 22nd, 2040 0.038715799 discount factor 0.36014925

Zero 315M: April 22nd, 2040 0.038727052 discount factor 0.35653498

Zero 318M: July 22nd, 2040 0.038736905 discount factor 0.35296826

Zero 321M: October 22nd, 2040 0.038745538 discount factor 0.34940945

Zero 324M: January 22nd, 2041 0.038752931 discount factor 0.34589673

Zero 327M: April 22nd, 2041 0.038759057 discount factor 0.34250378

Zero 330M: July 22nd, 2041 0.038764229 discount factor 0.33911557

Zero 333M: October 22nd, 2041 0.038768509 discount factor 0.33573228

Zero 336M: January 22nd, 2042 0.038771931 discount factor 0.33239012

Zero 339M: April 22nd, 2042 0.03877454 discount factor 0.32915922

Zero 342M: July 22nd, 2042 0.038776529 discount factor 0.32593004

Zero 345M: October 22nd, 2042 0.038777969 discount factor 0.32270261

Zero 348M: January 22nd, 2043 0.038778931 discount factor 0.3195114

Zero 351M: April 22nd, 2043 0.038779504 discount factor 0.31642341

Zero 354M: July 22nd, 2043 0.038779803 discount factor 0.31333398

Zero 357M: October 22nd, 2043 0.038779915 discount factor 0.31024301

Zero 360M: January 22nd, 2044 0.038779931 discount factor 0.3071834

 

3m Forward Rates...

0 x 3 Fwd : 0.0023653005

3 x 6 Fwd : 0.0021860069

6 x 9 Fwd : 0.0032733606

9 x 12 Fwd : 0.0035647945

12 x 15 Fwd : 0.0047483244

15 x 18 Fwd : 0.0061160423

18 x 21 Fwd : 0.0079262072

21 x 24 Fwd : 0.010099431

24 x 27 Fwd : 0.012675677

27 x 30 Fwd : 0.015534102

30 x 33 Fwd : 0.018265327

33 x 36 Fwd : 0.020877095

36 x 39 Fwd : 0.023402501

39 x 42 Fwd : 0.025411231

42 x 45 Fwd : 0.027324354

45 x 48 Fwd : 0.029161396

48 x 51 Fwd : 0.030885983

51 x 54 Fwd : 0.032502315

54 x 57 Fwd : 0.034029417

57 x 60 Fwd : 0.035449091

60 x 63 Fwd : 0.036735406

63 x 66 Fwd : 0.037905685

66 x 69 Fwd : 0.038978677

69 x 72 Fwd : 0.039942605

72 x 75 Fwd : 0.04078315

75 x 78 Fwd : 0.041496367

78 x 81 Fwd : 0.042085756

81 x 84 Fwd : 0.042545605

84 x 87 Fwd : 0.042886573

87 x 90 Fwd : 0.043199236

90 x 93 Fwd : 0.043522775

93 x 96 Fwd : 0.043869627

96 x 99 Fwd : 0.044231727

99 x 102 Fwd : 0.044550577

102 x 105 Fwd : 0.04481419

105 x 108 Fwd : 0.045020768

108 x 111 Fwd : 0.045176223

111 x 114 Fwd : 0.045317632

114 x 117 Fwd : 0.045461827

117 x 120 Fwd : 0.045614485

120 x 123 Fwd : 0.045792055

123 x 126 Fwd : 0.04596687

126 x 129 Fwd : 0.04611445

129 x 132 Fwd : 0.046235741

132 x 135 Fwd : 0.046330338

135 x 138 Fwd : 0.046400593

138 x 141 Fwd : 0.046448871

141 x 144 Fwd : 0.046475719

144 x 147 Fwd : 0.046482225

147 x 150 Fwd : 0.046470149

150 x 153 Fwd : 0.046440521

153 x 156 Fwd : 0.046394441

156 x 159 Fwd : 0.046334137

159 x 162 Fwd : 0.046260894

162 x 165 Fwd : 0.046174758

165 x 168 Fwd : 0.046077263

168 x 171 Fwd : 0.045970816

171 x 174 Fwd : 0.045856891

174 x 177 Fwd : 0.045735577

177 x 180 Fwd : 0.04560813

180 x 183 Fwd : 0.045541077

183 x 186 Fwd : 0.045530178

186 x 189 Fwd : 0.045508462

189 x 192 Fwd : 0.045476174

192 x 195 Fwd : 0.045434309

195 x 198 Fwd : 0.045383208

198 x 201 Fwd : 0.045322345

201 x 204 Fwd : 0.045252216

204 x 207 Fwd : 0.045174418

207 x 210 Fwd : 0.045089064

210 x 213 Fwd : 0.044995071

213 x 216 Fwd : 0.044893149

216 x 219 Fwd : 0.044784786

219 x 222 Fwd : 0.044670457

222 x 225 Fwd : 0.044549284

225 x 228 Fwd : 0.044421557

228 x 231 Fwd : 0.044289787

231 x 234 Fwd : 0.044153728

234 x 237 Fwd : 0.044011474

237 x 240 Fwd : 0.043864071

240 x 243 Fwd : 0.043714334

243 x 246 Fwd : 0.043561893

246 x 249 Fwd : 0.043404574

249 x 252 Fwd : 0.043243543

252 x 255 Fwd : 0.043081824

255 x 258 Fwd : 0.04291895

258 x 261 Fwd : 0.042752583

261 x 264 Fwd : 0.042583974

264 x 267 Fwd : 0.042415333

267 x 270 Fwd : 0.042247049

270 x 273 Fwd : 0.042077651

273 x 276 Fwd : 0.041907517

276 x 279 Fwd : 0.041739792

279 x 282 Fwd : 0.041573917

282 x 285 Fwd : 0.04140752

285 x 288 Fwd : 0.041241923

288 x 291 Fwd : 0.041080184

291 x 294 Fwd : 0.040921743

294 x 297 Fwd : 0.040764365

297 x 300 Fwd : 0.040609354

300 x 303 Fwd : 0.040459583

303 x 306 Fwd : 0.040314529

306 x 309 Fwd : 0.040172185

309 x 312 Fwd : 0.04003381

312 x 315 Fwd : 0.039901286

315 x 318 Fwd : 0.039774917

318 x 321 Fwd : 0.039653689

321 x 324 Fwd : 0.039538069

324 x 327 Fwd : 0.03943026

327 x 330 Fwd : 0.039329909

330 x 333 Fwd : 0.039235765

333 x 336 Fwd : 0.039148896

336 x 339 Fwd : 0.039071023

339 x 342 Fwd : 0.039001926

342 x 345 Fwd : 0.038940882

345 x 348 Fwd : 0.038888814

348 x 351 Fwd : 0.03884686

351 x 354 Fwd : 0.038814969

354 x 357 Fwd : 0.038793041

357 x 360 Fwd : 0.038781823

360 x 363 Fwd : 0.03858163

 

 

From: Guan Wang [mailto:[hidden email]]
Sent: 11 June 2015 21:47
To: [hidden email]
Subject: [Quantlib-users] Piecewise Yield Curve Errors

 

Hi,

 

I am trying to build a yield curve using the following inputs:

 

USD Libor 1m, 3m

EDF prices (12 of them, 3m apart, let's suppose convexity adjustment is zero)

Swap rates (5yr to 50yr)

 

To be able to interpolate with swap rates, I have to set my calendar to be the joint calendar of US and UK. Theses are the errors I am getting:

 

For pricing date 1/17/2014:

negative time (-0.00277778) given

 

For pricing date 2/13/2014:

interpolation range is [0.0777778, 7.10278]: extrapolation at 0.075 not allowed

 

To avoid out of range errors, I also have to enable extrapolation for the yield curve builder.

 

Can anybody help me with this? The stand alone code is as follows:

 

#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 <

--

------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users