19#include <boost/assign/list_of.hpp>
20#include <boost/make_shared.hpp>
21#include <boost/test/unit_test.hpp>
23#include <ql/currencies/america.hpp>
24#include <ql/math/interpolations/all.hpp>
25#include <ql/quotes/simplequote.hpp>
26#include <ql/time/daycounters/actual365fixed.hpp>
32using namespace boost::unit_test_framework;
33using namespace boost::assign;
43 vector<Date> testDates;
44 vector<Period> curveTenors;
46 vector<Real> shiftedPrices;
47 vector<QuantLib::ext::shared_ptr<SimpleQuote> > pQuotes;
48 vector<Handle<Quote> > quotes;
51 vector<Date> interpolationDates;
52 vector<Time> interpolationTimes;
54 vector<Real> baseExpInterpResults;
57 vector<Real> afterExpInterpResults;
60 vector<Real> baseNewInterpResults;
64 vector<Real> afterNewInterpResults;
67 vector<Real> expLogInterpResults;
69 DayCounter curveDayCounter;
79 : testDates(2), curveTenors(6), prices(6), shiftedPrices(6), pQuotes(6), quotes(6), interpolationDates(3),
80 interpolationTimes(3), baseExpInterpResults(3), afterExpInterpResults(3), baseNewInterpResults(3),
81 afterNewInterpResults(3), expLogInterpResults(3), curveDayCounter(Actual365Fixed()), tolerance(1e-10),
85 testDates[0] = Date(15, Feb, 2018);
86 testDates[1] = Date(15, Mar, 2018);
89 curveTenors[0] = 0 * Days;
91 shiftedPrices[0] = 16.6;
92 curveTenors[1] = 181 * Days;
94 shiftedPrices[1] = 19.9;
95 curveTenors[2] = 365 * Days;
97 shiftedPrices[2] = 24.4;
98 curveTenors[3] = 546 * Days;
100 shiftedPrices[3] = 31.3;
101 curveTenors[4] = 730 * Days;
103 shiftedPrices[4] = 38.1;
104 curveTenors[5] = 1826 * Days;
106 shiftedPrices[5] = 54.5;
109 for (Size i = 0; i < quotes.size(); i++) {
110 pQuotes[i] = QuantLib::ext::make_shared<SimpleQuote>(prices[i]);
111 quotes[i] = Handle<Quote>(pQuotes[i]);
115 interpolationDates[0] = Date(1, Jan, 2019);
116 interpolationDates[1] = Date(1, Jun, 2021);
117 interpolationDates[2] = Date(1, Aug, 2025);
119 for (Size i = 0; i < interpolationDates.size(); i++) {
120 interpolationTimes[i] = curveDayCounter.yearFraction(testDates[0], interpolationDates[i]);
123 baseExpInterpResults[0] = 19.1173913043478;
124 baseExpInterpResults[1] = 32.9357664233577;
125 baseExpInterpResults[2] = 47.2392335766423;
127 afterExpInterpResults[0] = 18.6304347826087;
128 afterExpInterpResults[1] = 32.6726277372263;
129 afterExpInterpResults[2] = 46.9760948905109;
131 baseNewInterpResults[0] = 23.2994565217391;
132 baseNewInterpResults[1] = 45.1627737226277;
133 baseNewInterpResults[2] = 67.9372262773723;
135 afterNewInterpResults[0] = 22.6146739130435;
136 afterNewInterpResults[1] = 44.7437956204380;
137 afterNewInterpResults[2] = 67.5182481751825;
139 expLogInterpResults[0] = 19.0648200765280;
140 expLogInterpResults[1] = 32.5497181830507;
141 expLogInterpResults[2] = 49.9589077461237;
145 vector<Date> dates(Size testDatesIdx)
const {
146 vector<Date> result(curveTenors.size());
147 for (Size i = 0; i < result.size(); i++) {
148 result[i] = testDates[testDatesIdx] + curveTenors[i];
154 void updateQuotes()
const {
155 for (Size i = 0; i < quotes.size(); i++) {
156 pQuotes[i]->setValue(shiftedPrices[i]);
163 BOOST_TEST_MESSAGE(
"Performing common curve checks");
166 for (Size i = 0; i < td.dates(0).size(); i++) {
167 BOOST_CHECK_CLOSE(td.prices[i], priceCurve.
price(td.dates(0)[i], td.extrapolate), td.tolerance);
171 vector<Real> expResults = isLogLinear ? td.expLogInterpResults : td.baseExpInterpResults;
173 for (Size i = 0; i < td.interpolationDates.size(); i++) {
174 BOOST_CHECK_CLOSE(expResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate), td.tolerance);
175 BOOST_CHECK_CLOSE(expResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate), td.tolerance);
183BOOST_AUTO_TEST_SUITE(PriceCurveTest)
187 BOOST_TEST_MESSAGE(
"Testing interpolated price curve built from periods and prices");
192 Settings::instance().evaluationDate() = td.testDates[0];
198 commonChecks(td, priceCurve,
false);
204 commonChecks(td, logPriceCurve,
true);
207 Settings::instance().evaluationDate() = td.testDates[1];
210 BOOST_CHECK_EQUAL(priceCurve.referenceDate(), td.testDates[1]);
214 for (Size i = 0; i < td.interpolationTimes.size(); i++) {
215 BOOST_CHECK_CLOSE(td.baseExpInterpResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate),
217 BOOST_CHECK_CLOSE(td.afterExpInterpResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate),
224 BOOST_TEST_MESSAGE(
"Testing interpolated price curve built from periods and quotes");
229 Settings::instance().evaluationDate() = td.testDates[0];
235 commonChecks(td, priceCurve,
false);
241 commonChecks(td, logPriceCurve,
true);
244 Settings::instance().evaluationDate() = td.testDates[1];
247 BOOST_CHECK_EQUAL(priceCurve.referenceDate(), td.testDates[1]);
251 for (Size i = 0; i < td.interpolationTimes.size(); i++) {
252 BOOST_CHECK_CLOSE(td.baseExpInterpResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate),
254 BOOST_CHECK_CLOSE(td.afterExpInterpResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate),
260 for (Size i = 0; i < td.interpolationTimes.size(); i++) {
261 BOOST_CHECK_CLOSE(td.baseNewInterpResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate),
263 BOOST_CHECK_CLOSE(td.afterNewInterpResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate),
268 Settings::instance().evaluationDate() = td.testDates[0];
271 for (Size i = 0; i < td.interpolationTimes.size(); i++) {
272 BOOST_CHECK_CLOSE(td.baseNewInterpResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate),
274 BOOST_CHECK_CLOSE(td.baseNewInterpResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate),
281 BOOST_TEST_MESSAGE(
"Testing interpolated price curve built from dates and prices");
286 Settings::instance().evaluationDate() = td.testDates[0];
289 vector<Date> dates = td.dates(0);
293 commonChecks(td, priceCurve,
false);
299 commonChecks(td, logPriceCurve,
true);
302 Settings::instance().evaluationDate() = td.testDates[1];
305 BOOST_CHECK_EQUAL(priceCurve.referenceDate(), td.testDates[0]);
309 for (Size i = 0; i < td.interpolationTimes.size(); i++) {
310 BOOST_CHECK_CLOSE(td.baseExpInterpResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate),
312 BOOST_CHECK_CLOSE(td.baseExpInterpResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate),
319 BOOST_TEST_MESSAGE(
"Testing interpolated price curve built from dates and quotes");
324 Settings::instance().evaluationDate() = td.testDates[0];
327 vector<Date> dates = td.dates(0);
331 commonChecks(td, priceCurve,
false);
337 commonChecks(td, logPriceCurve,
true);
340 Settings::instance().evaluationDate() = td.testDates[1];
343 BOOST_CHECK_EQUAL(priceCurve.referenceDate(), td.testDates[0]);
347 for (Size i = 0; i < td.interpolationTimes.size(); i++) {
348 BOOST_CHECK_CLOSE(td.baseExpInterpResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate),
350 BOOST_CHECK_CLOSE(td.baseExpInterpResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate),
356 for (Size i = 0; i < td.interpolationTimes.size(); i++) {
357 BOOST_CHECK_CLOSE(td.baseNewInterpResults[i], priceCurve.
price(td.interpolationTimes[i], td.extrapolate),
359 BOOST_CHECK_CLOSE(td.baseNewInterpResults[i], priceCurve.
price(td.interpolationDates[i], td.extrapolate),
366 BOOST_TEST_MESSAGE(
"Test building with periods without a time 0 works with extrapolation on");
371 Settings::instance().evaluationDate() = td.testDates[0];
374 vector<Period> tenors = td.curveTenors;
375 tenors.erase(tenors.begin());
376 td.prices.erase(td.prices.begin());
380 BOOST_CHECK_CLOSE(15.1391304347826, priceCurve.
price(0.25, td.extrapolate), td.tolerance);
381 BOOST_CHECK_CLOSE(13.5521739130435, priceCurve.
price(0.0, td.extrapolate), td.tolerance);
385 BOOST_CHECK_CLOSE(15.331307232214800, logPriceCurve.
price(0.25, td.extrapolate), td.tolerance);
386 BOOST_CHECK_CLOSE(14.054688467053400, logPriceCurve.
price(0.0, td.extrapolate), td.tolerance);
389 BOOST_CHECK_THROW(priceCurve.
price(0.25,
false), QuantLib::Error);
394 BOOST_TEST_MESSAGE(
"Test that requesting a price at a time before zero throws");
399 Date today = td.testDates[0];
400 Settings::instance().evaluationDate() = today;
407 Date d = today - 1 * Weeks;
408 BOOST_CHECK_THROW(priceCurve.
price(t, td.extrapolate), QuantLib::Error);
409 BOOST_CHECK_THROW(priceCurve.
price(d, td.extrapolate), QuantLib::Error);
412 Settings::instance().evaluationDate() = today + 1 * Weeks;
413 BOOST_CHECK_THROW(priceCurve.
price(today, td.extrapolate), QuantLib::Error);
416BOOST_AUTO_TEST_SUITE_END()
418BOOST_AUTO_TEST_SUITE_END()
Interpolated price curve.
QuantLib::Real price(QuantLib::Time t, bool extrapolate=false) const
BOOST_AUTO_TEST_CASE(testPeriodsAndPricesCurve)
Interpolated price curve.
Fixture that can be used at top level.