150 {
151
152 BOOST_TEST_MESSAGE("Testing cap floor term volatility curve with different interpolation methods");
153
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);
158
159
160 QuantLib::ext::shared_ptr<CapFloorTermVolatilityStructure> cftvs;
161 switch (interpolationType.which()) {
162 case 0:
163 if (isMoving) {
164 BOOST_TEST_MESSAGE("Using Linear interpolation with a moving reference date");
166 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
167 } else {
168 BOOST_TEST_MESSAGE("Using Linear interpolation with a fixed reference date");
170 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
171 }
172 break;
173 case 1:
174 if (isMoving) {
175 BOOST_TEST_MESSAGE("Using BackwardFlat interpolation with a moving reference date");
177 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
178 } else {
179 BOOST_TEST_MESSAGE("Using BackwardFlat interpolation with a fixed reference date");
181 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
182 }
183 break;
184 case 2:
185 if (isMoving) {
186 BOOST_TEST_MESSAGE("Using LinearFlat interpolation with a moving reference date");
188 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
189 } else {
190 BOOST_TEST_MESSAGE("Using LinearFlat interpolation with a fixed reference date");
192 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
193 }
194 break;
195 case 3:
196 if (isMoving) {
197 BOOST_TEST_MESSAGE("Using Cubic interpolation with a moving reference date");
199 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
200 } else {
201 BOOST_TEST_MESSAGE("Using Cubic interpolation with a fixed reference date");
203 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
204 }
205 break;
206 case 4:
207 if (isMoving) {
208 BOOST_TEST_MESSAGE("Using CubicFlat interpolation with a moving reference date");
210 settlementDays, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
211 } else {
212 BOOST_TEST_MESSAGE("Using CubicFlat interpolation with a fixed reference date");
214 referenceDate, calendar, bdc, tenors, volHandles, dayCounter, flatFirstPeriod));
215 }
216 break;
217 default:
218 BOOST_FAIL("Unexpected interpolation type");
219 }
220
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);
226 }
227
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);
232 }
233
234
235 Size idx = 2;
236 Volatility bump = 0.0005;
237 Volatility baseValue = volQuotes[idx]->value();
238 volQuotes[idx]->setValue(baseValue + bump);
239
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);
244
245 if (i == idx) {
246 BOOST_CHECK_SMALL(vol - baseValue - bump, tolerance);
247 }
248 }
249
250 BOOST_TEST_MESSAGE("Test the curve dates after moving the evaluation date");
251 Date manualDate;
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]);
256 manualDate =
257 isMoving ? calendar.advance(newDate, tenors[i], bdc) : calendar.advance(referenceDate, tenors[i], bdc);
258 BOOST_CHECK_EQUAL(curveDate, manualDate);
259 }
260
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);
265 }
266
267
268 Settings::instance().evaluationDate() = referenceDate;
269
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));
276}
Interpolated cap floor term volatility curve.