19#include <boost/assign.hpp>
21#include <boost/test/unit_test.hpp>
22#include <boost/test/data/test_case.hpp>
24#include <boost/variant.hpp>
29#include <ql/math/interpolations/backwardflatinterpolation.hpp>
30#include <ql/quotes/simplequote.hpp>
36using namespace boost::unit_test_framework;
39using boost::assign::list_of;
40using boost::assign::map_list_of;
46using std::setprecision;
57 : referenceDate(5, Feb, 2016), settlementDays(0), calendar(TARGET()), bdc(Following),
58 dayCounter(Actual365Fixed()), tolerance(1.0e-12) {
61 Settings::instance().evaluationDate() = referenceDate;
66 volQuotes.resize(tenors.size());
67 volHandles.resize(tenors.size());
68 for (Size i = 0; i < tenors.size(); ++i) {
69 volQuotes[i] = QuantLib::ext::make_shared<SimpleQuote>(testData.
nAtmVols[i]);
70 volHandles[i] = Handle<Quote>(volQuotes[i]);
78 Natural settlementDays;
80 BusinessDayConvention bdc;
81 DayCounter dayCounter;
87 vector<Period> tenors;
88 vector<QuantLib::ext::shared_ptr<SimpleQuote> > volQuotes;
89 vector<Handle<Quote> > volHandles;
93typedef boost::variant<Linear, BackwardFlat, QuantExt::LinearFlat, Cubic, QuantExt::CubicFlat> InterpolationType;
95vector<InterpolationType> interpolationTypes = list_of(InterpolationType(Linear()))(InterpolationType(BackwardFlat()))(
99vector<bool> isMovingValues = list_of(
true)(
false);
102vector<bool> flatFirstPeriodValues = list_of(
true)(
false);
105string to_string(
const InterpolationType& interpolationType) {
107 switch (interpolationType.which()) {
112 result =
"BackwardFlat";
115 result =
"LinearFlat";
121 result =
"CubicFlat";
124 BOOST_FAIL(
"Unexpected interpolation type");
134namespace test_tools {
136template <>
struct print_log_value<InterpolationType> {
137 void operator()(ostream& os,
const InterpolationType& interpolationType) { os << to_string(interpolationType); }
145BOOST_AUTO_TEST_SUITE(CapFloorTermVolCurveTests)
148 bdata::make(interpolationTypes) *
bdata::make(isMovingValues) *
149 bdata::make(flatFirstPeriodValues),
150 interpolationType, isMoving, flatFirstPeriod) {
152 BOOST_TEST_MESSAGE(
"Testing cap floor term volatility curve with different interpolation methods");
154 BOOST_TEST_MESSAGE(
"Test inputs are:");
155 BOOST_TEST_MESSAGE(
" Interpolation type: " << to_string(interpolationType));
156 BOOST_TEST_MESSAGE(
" Floating reference date: " << boolalpha << isMoving);
157 BOOST_TEST_MESSAGE(
" Flat first period: " << boolalpha << flatFirstPeriod);
160 QuantLib::ext::shared_ptr<CapFloorTermVolatilityStructure> cftvs;
161 switch (interpolationType.which()) {
164 BOOST_TEST_MESSAGE(
"Using Linear interpolation with a moving reference date");
166 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
168 BOOST_TEST_MESSAGE(
"Using Linear interpolation with a fixed reference date");
170 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
175 BOOST_TEST_MESSAGE(
"Using BackwardFlat interpolation with a moving reference date");
177 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
179 BOOST_TEST_MESSAGE(
"Using BackwardFlat interpolation with a fixed reference date");
181 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
186 BOOST_TEST_MESSAGE(
"Using LinearFlat interpolation with a moving reference date");
188 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
190 BOOST_TEST_MESSAGE(
"Using LinearFlat interpolation with a fixed reference date");
192 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
197 BOOST_TEST_MESSAGE(
"Using Cubic interpolation with a moving reference date");
199 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
201 BOOST_TEST_MESSAGE(
"Using Cubic interpolation with a fixed reference date");
203 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
208 BOOST_TEST_MESSAGE(
"Using CubicFlat interpolation with a moving reference date");
210 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
212 BOOST_TEST_MESSAGE(
"Using CubicFlat interpolation with a fixed reference date");
214 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
218 BOOST_FAIL(
"Unexpected interpolation type");
221 BOOST_TEST_MESSAGE(
"Test the initial curve dates");
222 for (Size i = 0; i < tenors.size(); ++i) {
223 Date curveDate = cftvs->optionDateFromTenor(tenors[i]);
224 Date manualDate = calendar.advance(referenceDate, tenors[i], bdc);
225 BOOST_CHECK_EQUAL(curveDate, manualDate);
228 BOOST_TEST_MESSAGE(
"Test that curve returns input values on pillars");
229 for (Size i = 0; i < tenors.size(); ++i) {
230 Volatility vol = cftvs->volatility(tenors[i], 0.01);
231 BOOST_CHECK_SMALL(volQuotes[i]->value() - vol, tolerance);
236 Volatility bump = 0.0005;
237 Volatility baseValue = volQuotes[idx]->value();
238 volQuotes[idx]->setValue(baseValue + bump);
240 BOOST_TEST_MESSAGE(
"Test that curve returns input values on pillars after bump");
241 for (Size i = 0; i < tenors.size(); ++i) {
242 Volatility vol = cftvs->volatility(tenors[i], 0.01);
243 BOOST_CHECK_SMALL(volQuotes[i]->value() - vol, tolerance);
246 BOOST_CHECK_SMALL(vol - baseValue - bump, tolerance);
250 BOOST_TEST_MESSAGE(
"Test the curve dates after moving the evaluation date");
252 Date newDate = calendar.advance(referenceDate, 1 * Months);
253 Settings::instance().evaluationDate() = newDate;
254 for (Size i = 0; i < tenors.size(); ++i) {
255 Date curveDate = cftvs->optionDateFromTenor(tenors[i]);
257 isMoving ? calendar.advance(newDate, tenors[i], bdc) : calendar.advance(referenceDate, tenors[i], bdc);
258 BOOST_CHECK_EQUAL(curveDate, manualDate);
261 BOOST_TEST_MESSAGE(
"Test that curve returns input values after moving the evaluation date");
262 for (Size i = 0; i < tenors.size(); ++i) {
263 Volatility vol = cftvs->volatility(tenors[i], 0.01);
264 BOOST_CHECK_SMALL(volQuotes[i]->value() - vol, tolerance);
268 Settings::instance().evaluationDate() = referenceDate;
270 BOOST_TEST_MESSAGE(
"Test extrapolation settings with out of range date");
271 Date oorDate = cftvs->maxDate() + 1 * Months;
272 BOOST_CHECK_NO_THROW(cftvs->volatility(oorDate, 0.01,
true));
273 BOOST_CHECK_THROW(cftvs->volatility(oorDate, 0.01), Error);
274 cftvs->enableExtrapolation();
275 BOOST_CHECK_NO_THROW(cftvs->volatility(oorDate, 0.01));
278BOOST_AUTO_TEST_SUITE_END()
280BOOST_AUTO_TEST_SUITE_END()
structs containing capfloor market data that can be used in tests
BOOST_DATA_TEST_CASE_F(CommonVars, testCapFloorTermVolCurveInterpolation, bdata::make(interpolationTypes) *bdata::make(isMovingValues) *bdata::make(flatFirstPeriodValues), interpolationType, isMoving, flatFirstPeriod)
Cap floor at-the-money term volatility curve.
Cubic interpolation and flat extrapolation factory and traits.
Interpolated cap floor term volatility curve.
Linear-interpolation and flat extrapolation factory and traits
vector< Period > atmTenors
vector< Volatility > nAtmVols
Fixture that can be used at top level.