183 {
184
185 BOOST_TEST_MESSAGE("Testing fx vanna volga surface");
186
187 SavedSettings backup;
188
189
190
191
192
193 Date asof(12, Feb, 2004);
194 Settings::instance().evaluationDate() = asof;
195
196 Handle<Quote> fxSpot(QuantLib::ext::shared_ptr<Quote>(new SimpleQuote(1.2832)));
197
198
199
200 VolData volData[] = { { "1W", 11.75, 0.50, 0.190, 0.0192, 0.999804, 0.999606 },
201 { "2W", 11.60, 0.50, 0.190, 0.0384, 0.999595, 0.999208 },
202 { "1M", 11.50, 0.60, 0.190, 0.0877, 0.999044, 0.998179 },
203 { "2M", 11.25, 0.60, 0.210, 0.1726, 0.998083, 0.996404 },
204 { "3M", 11.00, 0.60, 0.220, 0.2493, 0.997187, 0.994803 },
205 { "6M", 10.87, 0.65, 0.235, 0.5014, 0.993959, 0.989548 },
206 { "9M", 10.83, 0.69, 0.235, 0.7589, 0.990101, 0.984040 },
207 { "1Y", 10.80, 0.70, 0.240, 1.0110, 0.985469, 0.978479 },
208 { "2Y", 10.70, 0.65, 0.255, 2.0110, 0.960102, 0.951092 } };
209
210
211 DayCounter dc = ActualActual(ActualActual::ISDA);
212 Calendar cal = TARGET();
213
214
215 Size len = sizeof(volData) / sizeof(volData[0]);
216 vector<Date> dates(len);
217 vector<Volatility> atm(len);
218 vector<Volatility> rr(len);
219 vector<Volatility> bf(len);
220
221 vector<Date> discountDates(len + 1);
222 vector<DiscountFactor> dfDom(len + 1);
223 vector<DiscountFactor> dfFor(len + 1);
224 discountDates[0] = asof;
225 dfDom[0] = 1.0;
226 dfFor[0] = 1.0;
227
228 for (Size i = 0; i < sizeof(volData) / sizeof(volData[0]); i++) {
229 dates[i] = asof + PeriodParser::parse(volData[i].tenor);
230
231
232
233
234
235
236
237
238 atm[i] = volData[i].atm / 100;
239 rr[i] = volData[i].rr / 100;
240 bf[i] = volData[i].bf / 100;
241
242 discountDates[i + 1] = dates[i];
243 dfDom[i + 1] = volData[i].df_d;
244 dfFor[i + 1] = volData[i].df_f;
245 }
246
247
248 Handle<YieldTermStructure> domYTS(
249 QuantLib::ext::shared_ptr<YieldTermStructure>(new DiscountCurve(discountDates, dfDom, dc)));
250 Handle<YieldTermStructure> forYTS(
251 QuantLib::ext::shared_ptr<YieldTermStructure>(new DiscountCurve(discountDates, dfFor, dc)));
252
253
255
256
257 Real vol = volSurface.blackVol(1.75, 1.55);
258 Real expected = 0.121507;
259 if (fabs(vol - expected) > 0.00001)
260 BOOST_FAIL("Failed to get expected vol from surface " << vol);
261
262
263
264
265
266
267
268
269 for (Size i = 0; i < len; i++) {
270 Real vol = volSurface.blackVol(dates[i], Null<Real>());
271 Real vol2 = volSurface.blackVol(dates[i], 0);
272 if (fabs(vol - atm[i]) > 0.00001)
273 BOOST_FAIL("Failed to get expected atm vol from surface: " << vol);
274 if (fabs(vol2 - atm[i]) > 0.00001)
275 BOOST_FAIL("Failed to get expected atm vol from surface: " << vol);
276 }
277}
Fx Black vanna volga volatility surface.