T-Bill/T-Bond Yield Curve Construction

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

T-Bill/T-Bond Yield Curve Construction

rob.philipp
Hello, I've been using QL for constructing the US Treasury yield curve. The zero rates for the short-end of the yield curve seemed a bit off. So I tried to create a flat par curve (8%) across all terms, and expected that the zero rates equal the par yields for all terms. But they don't. In particular, it seems that zero rates for the t-bills are off. I've attached the code below, followed by the output.

I've tried playing with the day count conventions, using the fixed rate bond helper for the discount notes, changing the input rates to discount rates and equivalent simple interest. Nothing seems to work. Has anyone had a similar issue? Does anyone know what I'm doing wrong?

Thanks,
Rob

Code (modified from Bond.cpp):
        /*********************
         ***  MARKET DATA  ***
         *********************/

        Calendar calendar = TARGET();

        Date settlementDate(18, September, 2008);
        // must be a business day
        settlementDate = calendar.adjust(settlementDate);

        Integer fixingDays = 3;
        Natural settlementDays = 3;

        Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days);
        // nothing to do with Date::todaysDate
        Settings::instance().evaluationDate() = todaysDate;

        std::cout << "Today: " << todaysDate.weekday()
        << ", " << todaysDate << std::endl;

        std::cout << "Settlement date: " << settlementDate.weekday()
        << ", " << settlementDate << std::endl;


        // Building of the bonds discounting yield curve

        /*********************
         ***  RATE HELPERS ***
         *********************/

        // RateHelpers are built from the above quotes together with
        // other instrument dependant infos.  Quotes are passed in
        // relinkable handles which could be relinked to some other
        // data source later.

        // Common data

        // ZC rates for the short end
         //Rate zc3mQuote=0.0096;
         //Rate zc6mQuote=0.0145;
         //Rate zc1yQuote=0.0194;
                 const double FLAT_RATE = 0.08;
         Rate zc3mQuote=FLAT_RATE;
         Rate zc6mQuote=FLAT_RATE;
         Rate zc1yQuote=FLAT_RATE;

         boost::shared_ptr<Quote> zc3mRate(new SimpleQuote(zc3mQuote));
         boost::shared_ptr<Quote> zc6mRate(new SimpleQuote(zc6mQuote));
         boost::shared_ptr<Quote> zc1yRate(new SimpleQuote(zc1yQuote));

         DayCounter zcBondsDayCounter = Actual365Fixed();

         boost::shared_ptr<RateHelper> zc3m(new DepositRateHelper(
                 Handle<Quote>(zc3mRate),
                 3*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, zcBondsDayCounter));
         boost::shared_ptr<RateHelper> zc6m(new DepositRateHelper(
                 Handle<Quote>(zc6mRate),
                 6*Months, fixingDays,
                 calendar, ModifiedFollowing,
                 true, zcBondsDayCounter));
         boost::shared_ptr<RateHelper> zc1y(new DepositRateHelper(
                 Handle<Quote>(zc1yRate),
                 1*Years, fixingDays,
                 calendar, ModifiedFollowing,
                 true, zcBondsDayCounter));

        // setup bonds
        Real redemption = 100.0;

        //const Size numberOfBonds = 5;
        const Size numberOfBonds = 7;

        Date issueDates[] = {
                //Date (15, March, 2005),
                //Date (15, June, 2005),
                //Date (30, June, 2006),
                //Date (15, November, 2002),
                //Date (15, May, 1987)
                        Date (18, September, 2008),
                        Date (18, September, 2008),
                        Date (18, September, 2008),
                        Date (18, September, 2008),
                        Date (18, September, 2008),
                        Date (18, September, 2008),
                        Date (18, September, 2008)
        };

        Date maturities[] = {
                //Date (31, August, 2010),
                //Date (31, August, 2011),
                //Date (31, August, 2013),
                //Date (15, August, 2018),
                //Date (15, May, 2038)
                        Date (18, September, 2010),
                        Date (18, September, 2011),
                        Date (18, September, 2013),
                        Date (18, September, 2015),
                        Date (18, September, 2018),
                        Date (18, September, 2028),
                        Date (18, September, 2030)
        };

        Real couponRates[] = {
                        FLAT_RATE,
                        FLAT_RATE,
                        FLAT_RATE,
                        FLAT_RATE,
                        FLAT_RATE,
                        FLAT_RATE,
                        FLAT_RATE
                //0.04,
                //0.04625,
                //0.03125,
                //0.04000,
                //0.04500
        };

        Real marketQuotes[] = {
                        100.0,
                        100.0,
                        100.0,
                        100.0,
                        100.0,
                        100.0,
                        100.0
                //100.390625,
                //106.21875,
                //100.59375,
                //101.6875,
                //102.140625
        };

        std::vector< boost::shared_ptr<SimpleQuote> > quote;
        for (Size i=0; i<numberOfBonds; i++) {
            boost::shared_ptr<SimpleQuote> cp(new SimpleQuote(marketQuotes[i]));
            quote.push_back(cp);
        }

        RelinkableHandle<Quote> quoteHandle[numberOfBonds];
        for (Size i=0; i<numberOfBonds; i++) {
            quoteHandle[i].linkTo(quote[i]);
        }

        // Definition of the rate helpers
        std::vector<boost::shared_ptr<FixedRateBondHelper> > bondsHelpers;

        for (Size i=0; i<numberOfBonds; i++) {

            Schedule schedule(issueDates[i], maturities[i], Period(Semiannual), UnitedStates(UnitedStates::GovernmentBond),
                    Unadjusted, Unadjusted, DateGeneration::Backward, false);

            boost::shared_ptr<FixedRateBondHelper> bondHelper(new FixedRateBondHelper(
                    quoteHandle[i],
                    settlementDays,
                    100.0,
                    schedule,
                    std::vector<Rate>(1,couponRates[i]),
                    ActualActual(ActualActual::Bond),
                    Unadjusted,
                    redemption,
                    issueDates[i]));

            bondsHelpers.push_back(bondHelper);
        }

        /*********************
         **  CURVE BUILDING **
         *********************/

         // Any DayCounter would be fine.
         // ActualActual::ISDA ensures that 30 years is 30.0
         DayCounter termStructureDayCounter =
             ActualActual(ActualActual::ISDA);

         double tolerance = 1.0e-15;

         // A depo-bond curve
         std::vector<boost::shared_ptr<RateHelper> > bondInstruments;

         // Adding the ZC bonds to the curve for the short end
         bondInstruments.push_back(zc3m);
         bondInstruments.push_back(zc6m);
         bondInstruments.push_back(zc1y);

         // Adding the Fixed rate bonds to the curve for the long end
         for (Size i=0; i<numberOfBonds; i++) {
             bondInstruments.push_back(bondsHelpers[i]);
         }

         boost::shared_ptr<YieldTermStructure> bondDiscountingTermStructure(
                 new PiecewiseYieldCurve<Discount,LogLinear>(
                         settlementDate, bondInstruments,
                         termStructureDayCounter,
                         tolerance));

                std::cout << "disc-bond Curve Data" << std::endl;
                //boost::shared_ptr< PiecewiseYieldCurve< Discount, LogLinear > > discBond = boost::dynamic_pointer_cast< PiecewiseYieldCurve< Discount, LogLinear > >( bondDiscountingTermStructure );
                boost::shared_ptr< PiecewiseYieldCurve< Discount, LogLinear > > discBond = boost::dynamic_pointer_cast< PiecewiseYieldCurve< Discount, LogLinear > >( bondDiscountingTermStructure );
                std::vector< Real > discBondData = discBond->data();
                std::vector< Date > discBondDates = discBond->dates();
                std::vector< Real >::iterator iter = discBondData.begin();
                std::vector< Date >::iterator date_iter = discBondDates.begin();
                for( ; iter < discBondData.end() && date_iter < discBondDates.end(); ++iter, ++date_iter )
                {
                        std::cout << *iter << ", " << *date_iter << std::endl;
                }

                for( Time t = 0; t < 180; ++t )
                {
                        std::cout << t << ", " << discBond->zeroRate( t / 12, Compounded, Semiannual ).rate()
                                                   << ", " << discBond->forwardRate( t/12, t/12, Compounded, Semiannual ).rate()
                                                   << std::endl;
                }

...and the results:
time, zero rates, forward rates
0 0.081028 0.081028
1 0.081028 0.081028
2 0.081028 0.081028
3 0.0810183 0.0792496
4 0.080576 0.0792496
5 0.0803106 0.0792496
6 0.0801111 0.0769354
7 0.0796571 0.0769354
8 0.0793167 0.0769354
9 0.079052 0.0769354
10 0.0788402 0.0769354
11 0.078667 0.0769354
12 0.0785263 0.0816607
13 0.0787673 0.0816607
14 0.0789738 0.0816607
15 0.0791528 0.0816607
16 0.0793095 0.0816607
17 0.0794477 0.0816607
18 0.0795706 0.0816607
19 0.0796806 0.0816607
20 0.0797795 0.0816607
21 0.0798691 0.0816607
22 0.0799505 0.0816607
23 0.0800248 0.0816607
24 0.0800923 0.0800132
25 0.0800891 0.0800132
26 0.0800862 0.0800132
27 0.0800835 0.0800132
28 0.080081 0.0800132
29 0.0800786 0.0800132
30 0.0800765 0.0800132
31 0.0800744 0.0800132
32 0.0800725 0.0800132
33 0.0800707 0.0800132
34 0.080069 0.0800132
35 0.0800674 0.0800132
36 0.0800659 0.0800083
37 0.0800643 0.0800083
38 0.0800629 0.0800083
39 0.0800615 0.0800083
40 0.0800601 0.0800083
41 0.0800589 0.0800083
42 0.0800577 0.0800083
43 0.0800565 0.0800083
44 0.0800554 0.0800083
45 0.0800544 0.0800083
46 0.0800534 0.0800083
47 0.0800524 0.0800083
48 0.0800515 0.0800083
49 0.0800506 0.0800083
50 0.0800498 0.0800083
51 0.080049 0.0800083
52 0.0800482 0.0800083
53 0.0800474 0.0800083
54 0.0800467 0.0800083
55 0.080046 0.0800083
56 0.0800453 0.0800083
57 0.0800447 0.0800083
58 0.0800441 0.0800083
59 0.0800434 0.0800083
60 0.0800429 0.0800132
61 0.0800424 0.0800132
62 0.0800419 0.0800132
63 0.0800414 0.0800132
64 0.080041 0.0800132
65 0.0800406 0.0800132
66 0.0800402 0.0800132
67 0.0800398 0.0800132
68 0.0800394 0.0800132
69 0.080039 0.0800132
70 0.0800386 0.0800132
71 0.0800383 0.0800132
72 0.0800379 0.0800132
73 0.0800376 0.0800132
74 0.0800372 0.0800132
75 0.0800369 0.0800132
76 0.0800366 0.0800132
77 0.0800363 0.0800132
78 0.080036 0.0800132
79 0.0800357 0.0800132
80 0.0800354 0.0800132
81 0.0800352 0.0800132
82 0.0800349 0.0800132
83 0.0800346 0.0800132
84 0.0800344 0.0800098
85 0.0800341 0.0800098
86 0.0800338 0.0800098
87 0.0800335 0.0800098
88 0.0800333 0.0800098
89 0.080033 0.0800098
90 0.0800327 0.0800098
91 0.0800325 0.0800098
92 0.0800322 0.0800098
93 0.080032 0.0800098
94 0.0800318 0.0800098
95 0.0800315 0.0800098
96 0.0800313 0.0800098
97 0.0800311 0.0800098
98 0.0800309 0.0800098
99 0.0800306 0.0800098
100 0.0800304 0.0800098
101 0.0800302 0.0800098
102 0.08003 0.0800098
103 0.0800298 0.0800098
104 0.0800296 0.0800098
105 0.0800295 0.0800098
106 0.0800293 0.0800098
107 0.0800291 0.0800098
108 0.0800289 0.0800098
109 0.0800287 0.0800098
110 0.0800286 0.0800098
111 0.0800284 0.0800098
112 0.0800282 0.0800098
113 0.0800281 0.0800098
114 0.0800279 0.0800098
115 0.0800277 0.0800098
116 0.0800276 0.0800098
117 0.0800274 0.0800098
118 0.0800273 0.0800098
119 0.0800271 0.0800098
120 0.080027 0.0800063
121 0.0800268 0.0800063
122 0.0800267 0.0800063
123 0.0800265 0.0800063
124 0.0800263 0.0800063
125 0.0800262 0.0800063
126 0.080026 0.0800063
127 0.0800259 0.0800063
128 0.0800257 0.0800063
129 0.0800256 0.0800063
130 0.0800254 0.0800063
131 0.0800253 0.0800063
132 0.0800251 0.0800063
133 0.080025 0.0800063
134 0.0800248 0.0800063
135 0.0800247 0.0800063
136 0.0800246 0.0800063
137 0.0800244 0.0800063
138 0.0800243 0.0800063
139 0.0800242 0.0800063
140 0.080024 0.0800063
141 0.0800239 0.0800063
142 0.0800238 0.0800063
143 0.0800237 0.0800063
144 0.0800235 0.0800063
145 0.0800234 0.0800063
146 0.0800233 0.0800063
147 0.0800232 0.0800063
148 0.0800231 0.0800063
149 0.080023 0.0800063
150 0.0800229 0.0800063
151 0.0800227 0.0800063
152 0.0800226 0.0800063
153 0.0800225 0.0800063
154 0.0800224 0.0800063
155 0.0800223 0.0800063
156 0.0800222 0.0800063
157 0.0800221 0.0800063
158 0.080022 0.0800063
159 0.0800219 0.0800063
160 0.0800218 0.0800063
161 0.0800217 0.0800063
162 0.0800216 0.0800063
163 0.0800215 0.0800063
164 0.0800214 0.0800063
165 0.0800214 0.0800063
166 0.0800213 0.0800063
167 0.0800212 0.0800063
168 0.0800211 0.0800063
169 0.080021 0.0800063
170 0.0800209 0.0800063
171 0.0800208 0.0800063
172 0.0800207 0.0800063
173 0.0800207 0.0800063
174 0.0800206 0.0800063
175 0.0800205 0.0800063
176 0.0800204 0.0800063
177 0.0800203 0.0800063
178 0.0800203 0.0800063
179 0.0800202 0.0800063