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 |
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]] 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 |
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:
------------------------------------------------------------------------------ _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
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]] 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]] 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 |
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:
------------------------------------------------------------------------------ _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
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:
-- <http://leanpub.com/implementingquantlib/> ------------------------------------------------------------------------------ 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 |
Free forum by Nabble | Edit this page |