| 1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 | |
| 3 | /* |
| 4 | Copyright (C) 2003 RiskMap srl |
| 5 | |
| 6 | This file is part of QuantLib, a free-software/open-source library |
| 7 | for financial quantitative analysts and developers - http://quantlib.org/ |
| 8 | |
| 9 | QuantLib is free software: you can redistribute it and/or modify it |
| 10 | under the terms of the QuantLib license. You should have received a |
| 11 | copy of the license along with this program; if not, please email |
| 12 | <quantlib-dev@lists.sf.net>. The license is also available online at |
| 13 | <http://quantlib.org/license.shtml>. |
| 14 | |
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT |
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 17 | FOR A PARTICULAR PURPOSE. See the license for more details. |
| 18 | */ |
| 19 | |
| 20 | #include "termstructures.hpp" |
| 21 | #include "utilities.hpp" |
| 22 | #include <ql/termstructures/yield/compositezeroyieldstructure.hpp> |
| 23 | #include <ql/termstructures/yield/ratehelpers.hpp> |
| 24 | #include <ql/termstructures/yield/flatforward.hpp> |
| 25 | #include <ql/termstructures/yield/piecewiseyieldcurve.hpp> |
| 26 | #include <ql/termstructures/yield/impliedtermstructure.hpp> |
| 27 | #include <ql/termstructures/yield/forwardspreadedtermstructure.hpp> |
| 28 | #include <ql/termstructures/yield/zerospreadedtermstructure.hpp> |
| 29 | #include <ql/time/calendars/target.hpp> |
| 30 | #include <ql/time/calendars/nullcalendar.hpp> |
| 31 | #include <ql/time/daycounters/actual360.hpp> |
| 32 | #include <ql/time/daycounters/thirty360.hpp> |
| 33 | #include <ql/math/comparison.hpp> |
| 34 | #include <ql/indexes/iborindex.hpp> |
| 35 | #include <ql/currency.hpp> |
| 36 | #include <ql/utilities/dataformatters.hpp> |
| 37 | |
| 38 | using namespace QuantLib; |
| 39 | using namespace boost::unit_test_framework; |
| 40 | |
| 41 | namespace term_structures_test { |
| 42 | |
| 43 | struct Datum { |
| 44 | Integer n; |
| 45 | TimeUnit units; |
| 46 | Rate rate; |
| 47 | }; |
| 48 | |
| 49 | struct CommonVars { |
| 50 | // common data |
| 51 | Calendar calendar; |
| 52 | Natural settlementDays; |
| 53 | ext::shared_ptr<YieldTermStructure> termStructure; |
| 54 | ext::shared_ptr<YieldTermStructure> dummyTermStructure; |
| 55 | |
| 56 | // setup |
| 57 | CommonVars() { |
| 58 | calendar = TARGET(); |
| 59 | settlementDays = 2; |
| 60 | Date today = calendar.adjust(Date::todaysDate()); |
| 61 | Settings::instance().evaluationDate() = today; |
| 62 | Date settlement = calendar.advance(today,n: settlementDays,unit: Days); |
| 63 | Datum depositData[] = { |
| 64 | { .n: 1, .units: Months, .rate: 4.581 }, |
| 65 | { .n: 2, .units: Months, .rate: 4.573 }, |
| 66 | { .n: 3, .units: Months, .rate: 4.557 }, |
| 67 | { .n: 6, .units: Months, .rate: 4.496 }, |
| 68 | { .n: 9, .units: Months, .rate: 4.490 } |
| 69 | }; |
| 70 | Datum swapData[] = { |
| 71 | { .n: 1, .units: Years, .rate: 4.54 }, |
| 72 | { .n: 5, .units: Years, .rate: 4.99 }, |
| 73 | { .n: 10, .units: Years, .rate: 5.47 }, |
| 74 | { .n: 20, .units: Years, .rate: 5.89 }, |
| 75 | { .n: 30, .units: Years, .rate: 5.96 } |
| 76 | }; |
| 77 | Size deposits = LENGTH(depositData), |
| 78 | swaps = LENGTH(swapData); |
| 79 | |
| 80 | std::vector<ext::shared_ptr<RateHelper> > instruments( |
| 81 | deposits+swaps); |
| 82 | for (Size i=0; i<deposits; i++) { |
| 83 | instruments[i] = ext::shared_ptr<RateHelper>(new |
| 84 | DepositRateHelper(depositData[i].rate/100, |
| 85 | depositData[i].n*depositData[i].units, |
| 86 | settlementDays, calendar, |
| 87 | ModifiedFollowing, true, |
| 88 | Actual360())); |
| 89 | } |
| 90 | ext::shared_ptr<IborIndex> index(new IborIndex("dummy" , |
| 91 | 6*Months, |
| 92 | settlementDays, |
| 93 | Currency(), |
| 94 | calendar, |
| 95 | ModifiedFollowing, |
| 96 | false, |
| 97 | Actual360())); |
| 98 | for (Size i=0; i<swaps; ++i) { |
| 99 | instruments[i+deposits] = ext::shared_ptr<RateHelper>(new |
| 100 | SwapRateHelper(swapData[i].rate/100, |
| 101 | swapData[i].n*swapData[i].units, |
| 102 | calendar, |
| 103 | Annual, Unadjusted, Thirty360(Thirty360::BondBasis), |
| 104 | index)); |
| 105 | } |
| 106 | termStructure = ext::shared_ptr<YieldTermStructure>(new |
| 107 | PiecewiseYieldCurve<Discount,LogLinear>(settlement, |
| 108 | instruments, Actual360())); |
| 109 | dummyTermStructure = ext::shared_ptr<YieldTermStructure>(new |
| 110 | PiecewiseYieldCurve<Discount,LogLinear>(settlement, |
| 111 | instruments, Actual360())); |
| 112 | } |
| 113 | }; |
| 114 | |
| 115 | Real sub(Real x, Real y) { return x - y; } |
| 116 | } |
| 117 | |
| 118 | void TermStructureTest::testReferenceChange() { |
| 119 | |
| 120 | BOOST_TEST_MESSAGE("Testing term structure against evaluation date change..." ); |
| 121 | |
| 122 | using namespace term_structures_test; |
| 123 | |
| 124 | CommonVars vars; |
| 125 | |
| 126 | ext::shared_ptr<SimpleQuote> flatRate (new SimpleQuote); |
| 127 | Handle<Quote> flatRateHandle(flatRate); |
| 128 | vars.termStructure = ext::shared_ptr<YieldTermStructure>( |
| 129 | new FlatForward(vars.settlementDays, NullCalendar(), |
| 130 | flatRateHandle, Actual360())); |
| 131 | Date today = Settings::instance().evaluationDate(); |
| 132 | flatRate->setValue(.03); |
| 133 | Integer days[] = { 10, 30, 60, 120, 360, 720 }; |
| 134 | Size i; |
| 135 | |
| 136 | std::vector<DiscountFactor> expected(LENGTH(days)); |
| 137 | for (i=0; i<LENGTH(days); i++) |
| 138 | expected[i] = vars.termStructure->discount(d: today+days[i]); |
| 139 | |
| 140 | Settings::instance().evaluationDate() = today+30; |
| 141 | std::vector<DiscountFactor> calculated(LENGTH(days)); |
| 142 | for (i=0; i<LENGTH(days); i++) |
| 143 | calculated[i] = vars.termStructure->discount(d: today+30+days[i]); |
| 144 | |
| 145 | for (i=0; i<LENGTH(days); i++) { |
| 146 | if (!close(x: expected[i],y: calculated[i])) |
| 147 | BOOST_ERROR("\n Discount at " << days[i] << " days:\n" |
| 148 | << std::setprecision(12) |
| 149 | << " before date change: " << expected[i] << "\n" |
| 150 | << " after date change: " << calculated[i]); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | |
| 155 | void TermStructureTest::testImplied() { |
| 156 | |
| 157 | BOOST_TEST_MESSAGE("Testing consistency of implied term structure..." ); |
| 158 | |
| 159 | using namespace term_structures_test; |
| 160 | |
| 161 | CommonVars vars; |
| 162 | |
| 163 | Real tolerance = 1.0e-10; |
| 164 | Date today = Settings::instance().evaluationDate(); |
| 165 | Date newToday = today + 3*Years; |
| 166 | Date newSettlement = vars.calendar.advance(newToday, |
| 167 | n: vars.settlementDays,unit: Days); |
| 168 | Date testDate = newSettlement + 5*Years; |
| 169 | ext::shared_ptr<YieldTermStructure> implied( |
| 170 | new ImpliedTermStructure(Handle<YieldTermStructure>(vars.termStructure), |
| 171 | newSettlement)); |
| 172 | DiscountFactor baseDiscount = vars.termStructure->discount(d: newSettlement); |
| 173 | DiscountFactor discount = vars.termStructure->discount(d: testDate); |
| 174 | DiscountFactor impliedDiscount = implied->discount(d: testDate); |
| 175 | if (std::fabs(x: discount - baseDiscount*impliedDiscount) > tolerance) |
| 176 | BOOST_ERROR( |
| 177 | "unable to reproduce discount from implied curve\n" |
| 178 | << std::fixed << std::setprecision(10) |
| 179 | << " calculated: " << baseDiscount*impliedDiscount << "\n" |
| 180 | << " expected: " << discount); |
| 181 | } |
| 182 | |
| 183 | void TermStructureTest::testImpliedObs() { |
| 184 | |
| 185 | BOOST_TEST_MESSAGE("Testing observability of implied term structure..." ); |
| 186 | |
| 187 | using namespace term_structures_test; |
| 188 | |
| 189 | CommonVars vars; |
| 190 | |
| 191 | Date today = Settings::instance().evaluationDate(); |
| 192 | Date newToday = today + 3*Years; |
| 193 | Date newSettlement = vars.calendar.advance(newToday, |
| 194 | n: vars.settlementDays,unit: Days); |
| 195 | RelinkableHandle<YieldTermStructure> h; |
| 196 | ext::shared_ptr<YieldTermStructure> implied( |
| 197 | new ImpliedTermStructure(h, newSettlement)); |
| 198 | Flag flag; |
| 199 | flag.registerWith(h: implied); |
| 200 | h.linkTo(h: vars.termStructure); |
| 201 | if (!flag.isUp()) |
| 202 | BOOST_ERROR("Observer was not notified of term structure change" ); |
| 203 | } |
| 204 | |
| 205 | void TermStructureTest::testFSpreaded() { |
| 206 | |
| 207 | BOOST_TEST_MESSAGE("Testing consistency of forward-spreaded term structure..." ); |
| 208 | |
| 209 | using namespace term_structures_test; |
| 210 | |
| 211 | CommonVars vars; |
| 212 | |
| 213 | Real tolerance = 1.0e-10; |
| 214 | ext::shared_ptr<Quote> me(new SimpleQuote(0.01)); |
| 215 | Handle<Quote> mh(me); |
| 216 | ext::shared_ptr<YieldTermStructure> spreaded( |
| 217 | new ForwardSpreadedTermStructure( |
| 218 | Handle<YieldTermStructure>(vars.termStructure),mh)); |
| 219 | Date testDate = vars.termStructure->referenceDate() + 5*Years; |
| 220 | DayCounter tsdc = vars.termStructure->dayCounter(); |
| 221 | DayCounter sprdc = spreaded->dayCounter(); |
| 222 | Rate forward = vars.termStructure->forwardRate(d1: testDate, d2: testDate, resultDayCounter: tsdc, |
| 223 | comp: Continuous, freq: NoFrequency); |
| 224 | Rate spreadedForward = spreaded->forwardRate(d1: testDate, d2: testDate, resultDayCounter: sprdc, |
| 225 | comp: Continuous, freq: NoFrequency); |
| 226 | if (std::fabs(x: forward - (spreadedForward-me->value())) > tolerance) |
| 227 | BOOST_ERROR( |
| 228 | "unable to reproduce forward from spreaded curve\n" |
| 229 | << std::setprecision(10) |
| 230 | << " calculated: " |
| 231 | << io::rate(spreadedForward-me->value()) << "\n" |
| 232 | << " expected: " << io::rate(forward)); |
| 233 | } |
| 234 | |
| 235 | void TermStructureTest::testFSpreadedObs() { |
| 236 | |
| 237 | BOOST_TEST_MESSAGE("Testing observability of forward-spreaded " |
| 238 | "term structure..." ); |
| 239 | |
| 240 | using namespace term_structures_test; |
| 241 | |
| 242 | CommonVars vars; |
| 243 | |
| 244 | ext::shared_ptr<SimpleQuote> me(new SimpleQuote(0.01)); |
| 245 | Handle<Quote> mh(me); |
| 246 | RelinkableHandle<YieldTermStructure> h; //(vars.dummyTermStructure); |
| 247 | ext::shared_ptr<YieldTermStructure> spreaded( |
| 248 | new ForwardSpreadedTermStructure(h,mh)); |
| 249 | Flag flag; |
| 250 | flag.registerWith(h: spreaded); |
| 251 | h.linkTo(h: vars.termStructure); |
| 252 | if (!flag.isUp()) |
| 253 | BOOST_ERROR("Observer was not notified of term structure change" ); |
| 254 | flag.lower(); |
| 255 | me->setValue(0.005); |
| 256 | if (!flag.isUp()) |
| 257 | BOOST_ERROR("Observer was not notified of spread change" ); |
| 258 | } |
| 259 | |
| 260 | void TermStructureTest::testZSpreaded() { |
| 261 | |
| 262 | BOOST_TEST_MESSAGE("Testing consistency of zero-spreaded term structure..." ); |
| 263 | |
| 264 | using namespace term_structures_test; |
| 265 | |
| 266 | CommonVars vars; |
| 267 | |
| 268 | Real tolerance = 1.0e-10; |
| 269 | ext::shared_ptr<Quote> me(new SimpleQuote(0.01)); |
| 270 | Handle<Quote> mh(me); |
| 271 | ext::shared_ptr<YieldTermStructure> spreaded( |
| 272 | new ZeroSpreadedTermStructure( |
| 273 | Handle<YieldTermStructure>(vars.termStructure),mh)); |
| 274 | Date testDate = vars.termStructure->referenceDate() + 5*Years; |
| 275 | DayCounter rfdc = vars.termStructure->dayCounter(); |
| 276 | Rate zero = vars.termStructure->zeroRate(d: testDate, resultDayCounter: rfdc, |
| 277 | comp: Continuous, freq: NoFrequency); |
| 278 | Rate spreadedZero = spreaded->zeroRate(d: testDate, resultDayCounter: rfdc, |
| 279 | comp: Continuous, freq: NoFrequency); |
| 280 | if (std::fabs(x: zero - (spreadedZero-me->value())) > tolerance) |
| 281 | BOOST_ERROR( |
| 282 | "unable to reproduce zero yield from spreaded curve\n" |
| 283 | << std::setprecision(10) |
| 284 | << " calculated: " << io::rate(spreadedZero-me->value()) << "\n" |
| 285 | << " expected: " << io::rate(zero)); |
| 286 | } |
| 287 | |
| 288 | void TermStructureTest::testZSpreadedObs() { |
| 289 | |
| 290 | BOOST_TEST_MESSAGE("Testing observability of zero-spreaded term structure..." ); |
| 291 | |
| 292 | using namespace term_structures_test; |
| 293 | |
| 294 | CommonVars vars; |
| 295 | |
| 296 | ext::shared_ptr<SimpleQuote> me(new SimpleQuote(0.01)); |
| 297 | Handle<Quote> mh(me); |
| 298 | RelinkableHandle<YieldTermStructure> h(vars.dummyTermStructure); |
| 299 | |
| 300 | ext::shared_ptr<YieldTermStructure> spreaded( |
| 301 | new ZeroSpreadedTermStructure(h,mh)); |
| 302 | Flag flag; |
| 303 | flag.registerWith(h: spreaded); |
| 304 | h.linkTo(h: vars.termStructure); |
| 305 | if (!flag.isUp()) |
| 306 | BOOST_ERROR("Observer was not notified of term structure change" ); |
| 307 | flag.lower(); |
| 308 | me->setValue(0.005); |
| 309 | if (!flag.isUp()) |
| 310 | BOOST_ERROR("Observer was not notified of spread change" ); |
| 311 | } |
| 312 | |
| 313 | void TermStructureTest::testCreateWithNullUnderlying() { |
| 314 | BOOST_TEST_MESSAGE( |
| 315 | "Testing that a zero-spreaded curve can be created with " |
| 316 | "a null underlying curve..." ); |
| 317 | |
| 318 | using namespace term_structures_test; |
| 319 | |
| 320 | CommonVars vars; |
| 321 | |
| 322 | Handle<Quote> spread(ext::shared_ptr<Quote>(new SimpleQuote(0.01))); |
| 323 | RelinkableHandle<YieldTermStructure> underlying; |
| 324 | // this shouldn't throw |
| 325 | ext::shared_ptr<YieldTermStructure> spreaded( |
| 326 | new ZeroSpreadedTermStructure(underlying,spread)); |
| 327 | // if we do this, the curve can work. |
| 328 | underlying.linkTo(h: vars.termStructure); |
| 329 | // check that we can use it |
| 330 | spreaded->referenceDate(); |
| 331 | } |
| 332 | |
| 333 | void TermStructureTest::testLinkToNullUnderlying() { |
| 334 | BOOST_TEST_MESSAGE( |
| 335 | "Testing that an underlying curve can be relinked to " |
| 336 | "a null underlying curve..." ); |
| 337 | |
| 338 | using namespace term_structures_test; |
| 339 | |
| 340 | CommonVars vars; |
| 341 | |
| 342 | Handle<Quote> spread(ext::shared_ptr<Quote>(new SimpleQuote(0.01))); |
| 343 | RelinkableHandle<YieldTermStructure> underlying(vars.termStructure); |
| 344 | ext::shared_ptr<YieldTermStructure> spreaded( |
| 345 | new ZeroSpreadedTermStructure(underlying,spread)); |
| 346 | // check that we can use it |
| 347 | spreaded->referenceDate(); |
| 348 | // if we do this, the curve can't work anymore. But it shouldn't |
| 349 | // throw as long as we don't try to use it. |
| 350 | underlying.linkTo(h: ext::shared_ptr<YieldTermStructure>()); |
| 351 | } |
| 352 | |
| 353 | void TermStructureTest::testCompositeZeroYieldStructures() { |
| 354 | BOOST_TEST_MESSAGE( |
| 355 | "Testing composite zero yield structures..." ); |
| 356 | |
| 357 | using namespace term_structures_test; |
| 358 | |
| 359 | Settings::instance().evaluationDate() = Date(10, Nov, 2017); |
| 360 | |
| 361 | // First curve |
| 362 | std::vector<Date> dates = {Date(10, Nov, 2017), Date(13, Nov, 2017), Date(12, Feb, 2018), |
| 363 | Date(10, May, 2018), Date(10, Aug, 2018), Date(12, Nov, 2018), |
| 364 | Date(21, Dec, 2018), Date(15, Jan, 2020), Date(31, Mar, 2021), |
| 365 | Date(28, Feb, 2023), Date(21, Dec, 2026), Date(31, Jan, 2030), |
| 366 | Date(28, Feb, 2031), Date(31, Mar, 2036), Date(28, Feb, 2041), |
| 367 | Date(28, Feb, 2048), Date(31, Dec, 2141)}; |
| 368 | |
| 369 | std::vector<Rate> rates = {0.0655823213132524, 0.0655823213132524, 0.0699455024156877, |
| 370 | 0.0799107139233497, 0.0813931951022577, 0.0841615820666691, |
| 371 | 0.0501297919004145, 0.0823483583439658, 0.0860720030924466, |
| 372 | 0.0922887604375688, 0.10588902278996, 0.117021968693922, |
| 373 | 0.109824660896137, 0.109231572878364, 0.119218123236241, |
| 374 | 0.128647300167664, 0.0506086995288751}; |
| 375 | |
| 376 | ext::shared_ptr<YieldTermStructure> termStructure1 = ext::shared_ptr<YieldTermStructure>( |
| 377 | new ForwardCurve(dates, rates, Actual365Fixed(), NullCalendar())); |
| 378 | |
| 379 | // Second curve |
| 380 | dates = {Date(10, Nov, 2017), Date(13, Nov, 2017), Date(11, Dec, 2017), Date(12, Feb, 2018), |
| 381 | Date(10, May, 2018), Date(31, Jan, 2022), Date(7, Dec, 2023), Date(31, Jan, 2025), |
| 382 | Date(31, Mar, 2028), Date(7, Dec, 2033), Date(1, Feb, 2038), Date(2, Apr, 2046), |
| 383 | Date(2, Jan, 2051), Date(31, Dec, 2141)}; |
| 384 | |
| 385 | rates = {0.056656806197189, 0.056656806197189, 0.0419541633454473, 0.0286681050019797, |
| 386 | 0.0148840226959593, 0.0246680238374363, 0.0255349067810599, 0.0298907184711927, |
| 387 | 0.0263943927922053, 0.0291924526539802, 0.0270049276163556, 0.028775807327614, |
| 388 | 0.0293567711641792, 0.010518655099659}; |
| 389 | |
| 390 | ext::shared_ptr<YieldTermStructure> termStructure2 = ext::shared_ptr<YieldTermStructure>( |
| 391 | new ForwardCurve(dates, rates, Actual365Fixed(), NullCalendar())); |
| 392 | |
| 393 | typedef Real(*binary_f)(Real, Real); |
| 394 | |
| 395 | ext::shared_ptr<YieldTermStructure> compoundCurve = ext::shared_ptr<YieldTermStructure>( |
| 396 | new CompositeZeroYieldStructure<binary_f>(Handle<YieldTermStructure>(termStructure1), Handle<YieldTermStructure>(termStructure2), sub)); |
| 397 | |
| 398 | // Expected values |
| 399 | dates = {Date(10, Nov, 2017), Date(15, Dec, 2017), Date(15, Jun, 2018), Date(15, Sep, 2029), |
| 400 | Date(15, Sep, 2038), Date(15, Mar, 2046), Date(15, Dec, 2141)}; |
| 401 | |
| 402 | rates = {0.00892551511527986, 0.0278755322562788, 0.0512001768603456, 0.0729941474263546, |
| 403 | 0.0778333309498459, 0.0828451659139004, 0.0503573807521742}; |
| 404 | |
| 405 | Real tolerance = 1.0e-10; |
| 406 | for (Size i = 0; i < dates.size(); ++i) { |
| 407 | Rate actual = compoundCurve->zeroRate(d: dates[i], resultDayCounter: Actual365Fixed(), comp: Continuous).rate(); |
| 408 | Rate expected = rates[i]; |
| 409 | |
| 410 | if (std::fabs(x: actual - expected) > tolerance) |
| 411 | BOOST_ERROR( |
| 412 | "unable to reproduce zero yield rate from composite input curve\n" |
| 413 | << std::fixed << std::setprecision(10) |
| 414 | << " calculated: " << actual << "\n" |
| 415 | << " expected: " << expected); |
| 416 | } |
| 417 | } |
| 418 | |
| 419 | |
| 420 | void TermStructureTest::testNullTimeToReference() { |
| 421 | BOOST_TEST_MESSAGE("Testing zero-rate calculation for null time-to-reference..." ); |
| 422 | |
| 423 | Rate rate = 0.02; |
| 424 | auto dayCount = Thirty360(Thirty360::BondBasis); |
| 425 | auto curve = FlatForward(Date(30, August, 2023), rate, dayCount); |
| 426 | |
| 427 | // the time between August 30th and 31st is null for the 30/360 day count convention |
| 428 | Rate expected = rate; |
| 429 | Rate calculated = curve.zeroRate(d: Date(31, August, 2023), resultDayCounter: dayCount, comp: Continuous); |
| 430 | Real tolerance = 1.0e-10; |
| 431 | |
| 432 | if (std::fabs(x: calculated - expected) > tolerance) |
| 433 | BOOST_ERROR("unable to reproduce zero yield rate from curve\n" |
| 434 | << std::fixed << std::setprecision(10) |
| 435 | << " calculated: " << calculated << "\n" |
| 436 | << " expected: " << expected); |
| 437 | } |
| 438 | |
| 439 | test_suite* TermStructureTest::suite() { |
| 440 | auto* suite = BOOST_TEST_SUITE("Term structure tests" ); |
| 441 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testReferenceChange)); |
| 442 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testImplied)); |
| 443 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testImpliedObs)); |
| 444 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testFSpreaded)); |
| 445 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testFSpreadedObs)); |
| 446 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testZSpreaded)); |
| 447 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testZSpreadedObs)); |
| 448 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testCreateWithNullUnderlying)); |
| 449 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testLinkToNullUnderlying)); |
| 450 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testCompositeZeroYieldStructures)); |
| 451 | suite->add(QUANTLIB_TEST_CASE(&TermStructureTest::testNullTimeToReference)); |
| 452 | return suite; |
| 453 | } |
| 454 | |
| 455 | |