315 {
316
317 BOOST_TEST_MESSAGE("Testing variance swap with replicating cost engine...");
318
319 ReplicatingVarianceSwapData values[] = {
320
321
322
323
324
325
326
327 {Position::Long, 0.04, 50000, 100.0, 0.00, 0.05, 0.246575, 0.20, 0.041888574, 1.0e-4}
328
329 };
330
331 Datum replicatingOptionData[] = {
332
333
334
335
336
337 {Option::Put, 50, 0.30}, {Option::Put, 55, 0.29}, {Option::Put, 60, 0.28}, {Option::Put, 65, 0.27},
338 {Option::Put, 70, 0.26}, {Option::Put, 75, 0.25}, {Option::Put, 80, 0.24}, {Option::Put, 85, 0.23},
339 {Option::Put, 90, 0.22}, {Option::Put, 95, 0.21}, {Option::Put, 100, 0.20}, {Option::Call, 100, 0.20},
340 {Option::Call, 105, 0.19}, {Option::Call, 110, 0.18}, {Option::Call, 115, 0.17}, {Option::Call, 120, 0.16},
341 {Option::Call, 125, 0.15}, {Option::Call, 130, 0.14}, {Option::Call, 135, 0.13}};
342
343 SavedSettings backup;
344 DayCounter dc = Actual365Fixed();
345 Date today = Date::todaysDate();
346 Settings::instance().evaluationDate() = today;
347
348 QuantLib::ext::shared_ptr<SimpleQuote> spot(new SimpleQuote(0.0));
349 QuantLib::ext::shared_ptr<SimpleQuote> qRate(new SimpleQuote(0.0));
350 QuantLib::ext::shared_ptr<YieldTermStructure> qTS =
351 QuantLib::ext::shared_ptr<YieldTermStructure>(new FlatForward(today, Handle<Quote>(qRate), dc));
352 QuantLib::ext::shared_ptr<SimpleQuote> rRate(new SimpleQuote(0.0));
353 QuantLib::ext::shared_ptr<YieldTermStructure> rTS =
354 QuantLib::ext::shared_ptr<YieldTermStructure>(new FlatForward(today, Handle<Quote>(rRate), dc));
355
356 for (Size i = 0; i <
LENGTH(values); i++) {
357 Date exDate = today + Integer(values[i].t * 365 + 0.5);
358 std::vector<Date> dates(1);
359 dates[0] = exDate;
360
361 spot->setValue(values[i].s);
362 qRate->setValue(values[i].q);
363 rRate->setValue(values[i].r);
364
365 Size options =
LENGTH(replicatingOptionData);
366 std::vector<Real> callStrikes, putStrikes, callVols, putVols;
367
368
369 Size j;
370 for (j = 0; j < options; j++) {
371 if (replicatingOptionData[j].type == Option::Call) {
372 callStrikes.push_back(replicatingOptionData[j].strike);
373 callVols.push_back(replicatingOptionData[j].v);
374 } else if (replicatingOptionData[j].type == Option::Put) {
375 putStrikes.push_back(replicatingOptionData[j].strike);
376 putVols.push_back(replicatingOptionData[j].v);
377 } else {
378 QL_FAIL("unknown option type");
379 }
380 }
381
382 Matrix vols(options - 1, 1);
384 for (j = 0; j < putVols.size(); j++) {
385 vols[j][0] = putVols[j];
386 strikes.push_back(putStrikes[j]);
387 }
388
389 for (Size k = 1; k < callVols.size(); k++) {
390 Size j = putVols.size() - 1;
391 vols[j + k][0] = callVols[k];
392 strikes.push_back(callStrikes[k]);
393 }
394
395 QuantLib::ext::shared_ptr<BlackVolTermStructure> volTS(
396 new BlackVarianceSurface(today, NullCalendar(), dates, strikes, vols, dc));
397
398 QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess> stochProcess(
399 new BlackScholesMertonProcess(Handle<Quote>(spot), Handle<YieldTermStructure>(qTS),
400 Handle<YieldTermStructure>(rTS), Handle<BlackVolTermStructure>(volTS)));
401
402 QuantLib::ext::shared_ptr<PricingEngine> engine(
403 new ReplicatingVarianceSwapEngine(stochProcess, 5.0, callStrikes, putStrikes));
404
405 QuantLib::VarianceSwap varianceSwap(values[i].type, values[i].varStrike, values[i].nominal, today, exDate);
406 varianceSwap.setPricingEngine(engine);
407
408 Real calculated = varianceSwap.variance();
409 Real expected = values[i].result;
410 Real tol = 1.0e-4;
411 BOOST_CHECK_CLOSE(calculated, expected, tol);
412 }
413}