C++:实现量化BlackDelta测试实例
C++:实现量化BlackDelta测试实例
#include "blackdeltacalculator.hpp"
#include "utilities.hpp"
#include <ql/experimental/fx/blackdeltacalculator.hpp>
#include <ql/experimental/fx/deltavolquote.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp>
#include <ql/instruments/europeanoption.hpp>
#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
#include <ql/time/daycounters/actual360.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/quotes/simplequote.hpp>using namespace QuantLib;
using namespace boost::unit_test_framework;using std::sqrt;namespace black_delta_calculator_test {struct DeltaData {Option::Type ot;DeltaVolQuote::DeltaType dt;Real spot;DiscountFactor dDf; // domestic discountDiscountFactor fDf; // foreign discountReal stdDev;Real strike;Real value;};struct EuropeanOptionData {Option::Type type;Real strike;Real s; // spotRate q; // dividendRate r; // risk-free rateTime t; // time to maturityVolatility v; // volatilityReal result; // expected resultReal tol; // tolerance};}void BlackDeltaCalculatorTest::testDeltaValues(){BOOST_TEST_MESSAGE("Testing delta calculator values...");using namespace black_delta_calculator_test;DeltaData values[] = {// Values taken from parallel implementation in R{Option::Call, DeltaVolQuote::Spot, 1.421, 0.997306, 0.992266, 0.1180654, 1.608080, 0.15},{Option::Call, DeltaVolQuote::PaSpot, 1.421, 0.997306, 0.992266, 0.1180654, 1.600545, 0.15},{Option::Call, DeltaVolQuote::Fwd, 1.421, 0.997306, 0.992266, 0.1180654, 1.609029, 0.15},{Option::Call, DeltaVolQuote::PaFwd, 1.421, 0.997306, 0.992266, 0.1180654, 1.601550, 0.15},{Option::Call, DeltaVolQuote::Spot, 122.121, 0.9695434,0.9872347, 0.0887676, 119.8031, 0.67},{Option::Call, DeltaVolQuote::PaSpot, 122.121, 0.9695434,0.9872347, 0.0887676, 117.7096, 0.67},{Option::Call, DeltaVolQuote::Fwd, 122.121, 0.9695434,0.9872347, 0.0887676, 120.0592, 0.67},{Option::Call, DeltaVolQuote::PaFwd, 122.121, 0.9695434,0.9872347, 0.0887676, 118.0532, 0.67},{Option::Put, DeltaVolQuote::Spot, 3.4582, 0.99979, 0.9250616, 0.3199034, 4.964924, -0.821},{Option::Put, DeltaVolQuote::PaSpot, 3.4582, 0.99979, 0.9250616, 0.3199034, 3.778327, -0.821},{Option::Put, DeltaVolQuote::Fwd, 3.4582, 0.99979, 0.9250616, 0.3199034, 4.51896, -0.821},{Option::Put, DeltaVolQuote::PaFwd, 3.4582, 0.99979, 0.9250616, 0.3199034, 3.65728, -0.821},// JPYUSD Data taken from Castagnas "FX Options and Smile Risk" (Wiley 2009){Option::Put, DeltaVolQuote::Spot, 103.00, 0.99482, 0.98508, 0.07247845, 97.47, -0.25},{Option::Put, DeltaVolQuote::PaSpot, 103.00, 0.99482, 0.98508, 0.07247845, 97.22, -0.25}};Option::Type currOt;DeltaVolQuote::DeltaType currDt;Real currSpot;Real currdDf;Real currfDf;Real currStdDev;Real currStrike;Real expected;Real currDelta;Real calculated;Real error;Real tolerance;for (Size i=0; i<LENGTH(values); i++) {currOt =values[i].ot;currDt =values[i].dt;currSpot =values[i].spot;currdDf =values[i].dDf;currfDf =values[i].fDf;currStdDev =values[i].stdDev;currStrike =values[i].strike;currDelta =values[i].value;BlackDeltaCalculator myCalc(currOt, currDt, currSpot,currdDf, currfDf, currStdDev);tolerance=1.0e-3;expected =currDelta;calculated =myCalc.deltaFromStrike(currStrike);error =std::fabs(calculated-expected);if (error>tolerance) {BOOST_ERROR("\n Delta-from-strike calculation failed for delta. \n"<< "Iteration: "<< i << "\n"<< "Calculated Strike:" << calculated << "\n"<< "Expected Strike:" << expected << "\n"<< "Error: " << error);}tolerance=1.0e-2;// tolerance not that small, but sufficient for strikes in// particular since they might be results of a numerical// procedureexpected =currStrike;calculated =myCalc.strikeFromDelta(currDelta);error =std::fabs(calculated-expected);if (error>tolerance) {BOOST_ERROR("\n Strike-from-delta calculation failed for delta. \n"<< "Iteration: "<< i << "\n"<< "Calculated Strike:" << calculated << "\n"<< "Expected Strike:" << expected << "\n"<< "Error: " << error);}}
}void BlackDeltaCalculatorTest::testDeltaPriceConsistency() {BOOST_TEST_MESSAGE("Testing premium-adjusted delta price consistency...");using namespace black_delta_calculator_test;// This function tests for price consistencies with the standard// Black Scholes calculator, since premium adjusted deltas can be calculated// from spot deltas by adding/subtracting the premium.SavedSettings backup;// actually, value and tol won't be needed for testingEuropeanOptionData values[] = {// type, strike, spot, rd, rf, t, vol, value, tol{ Option::Call, 0.9123, 1.2212, 0.0231, 0.0000, 0.25, 0.301, 0.0, 0.0},{ Option::Call, 0.9234, 1.2212, 0.0231, 0.0000, 0.35, 0.111, 0.0, 0.0},{ Option::Call, 0.9783, 1.2212, 0.0231, 0.0000, 0.45, 0.071, 0.0, 0.0},{ Option::Call, 1.0000, 1.2212, 0.0231, 0.0000, 0.55, 0.082, 0.0, 0.0},{ Option::Call, 1.1230, 1.2212, 0.0231, 0.0000, 0.65, 0.012, 0.0, 0.0},{ Option::Call, 1.2212, 1.2212, 0.0231, 0.0000, 0.75, 0.129, 0.0, 0.0},{ Option::Call, 1.3212, 1.2212, 0.0231, 0.0000, 0.85, 0.034, 0.0, 0.0},{ Option::Call, 1.3923, 1.2212, 0.0131, 0.2344, 0.95, 0.001, 0.0, 0.0},{ Option::Call, 1.3455, 1.2212, 0.0000, 0.0000, 1.00, 0.127, 0.0, 0.0},{ Option::Put, 0.9123, 1.2212, 0.0231, 0.0000, 0.25, 0.301, 0.0, 0.0},{ Option::Put, 0.9234, 1.2212, 0.0231, 0.0000, 0.35, 0.111, 0.0, 0.0},{ Option::Put, 0.9783, 1.2212, 0.0231, 0.0000, 0.45, 0.071, 0.0, 0.0},{ Option::Put, 1.0000, 1.2212, 0.0231, 0.0000, 0.55, 0.082, 0.0, 0.0},{ Option::Put, 1.1230, 1.2212, 0.0231, 0.0000, 0.65, 0.012, 0.0, 0.0},{ Option::Put, 1.2212, 1.2212, 0.0231, 0.0000, 0.75, 0.129, 0.0, 0.0},{ Option::Put, 1.3212, 1.2212, 0.0231, 0.0000, 0.85, 0.034, 0.0, 0.0},{ Option::Put, 1.3923, 1.2212, 0.0131, 0.2344, 0.95, 0.001, 0.0, 0.0},{ Option::Put, 1.3455, 1.2212, 0.0000, 0.0000, 1.00, 0.127, 0.0, 0.0},// extreme case: zero vol{ Option::Put, 1.3455, 1.2212, 0.0000, 0.0000, 0.50, 0.000, 0.0, 0.0},// extreme case: zero strike{ Option::Put, 0.0000, 1.2212, 0.0000, 0.0000, 1.50, 0.133, 0.0, 0.0},// extreme case: zero strike+zero vol{ Option::Put, 0.0000, 1.2212, 0.0000, 0.0000, 1.00, 0.133, 0.0, 0.0},};DayCounter dc = Actual360();Calendar calendar = TARGET();Date today = Date::todaysDate();// Start setup of market dataReal discFor =0.0;Real discDom =0.0;Real implVol =0.0;Real expectedVal =0.0;Real calculatedVal =0.0;Real error =0.0;ext::shared_ptr<SimpleQuote> spotQuote(new SimpleQuote(0.0));Handle<Quote> spotHandle(spotQuote);ext::shared_ptr<SimpleQuote> qQuote(new SimpleQuote(0.0));Handle<Quote> qHandle(qQuote);ext::shared_ptr<YieldTermStructure> qTS(new FlatForward(today, qHandle, dc));ext::shared_ptr<SimpleQuote> rQuote(new SimpleQuote(0.0));Handle<Quote> rHandle(qQuote);ext::shared_ptr<YieldTermStructure> rTS(new FlatForward(today, rHandle, dc));ext::shared_ptr<SimpleQuote> volQuote(new SimpleQuote(0.0));Handle<Quote> volHandle(volQuote);ext::shared_ptr<BlackVolTermStructure> volTS(new BlackConstantVol(today, calendar, volHandle, dc));ext::shared_ptr<BlackScholesMertonProcess> stochProcess;ext::shared_ptr<PricingEngine> engine;ext::shared_ptr<StrikedTypePayoff> payoff;Date exDate;ext::shared_ptr<Exercise> exercise;// Setup of market data finishedReal tolerance=1.0e-10;for (auto& value : values) {payoff =ext::shared_ptr<StrikedTypePayoff>(new PlainVanillaPayoff(value.type, value.strike));exDate = today + timeToDays(value.t);exercise = ext::shared_ptr<Exercise>(new EuropeanExercise(exDate));spotQuote->setValue(value.s);volQuote->setValue(value.v);rQuote->setValue(value.r);qQuote->setValue(value.q);discDom =rTS->discount(exDate);discFor =qTS->discount(exDate);implVol =sqrt(volTS->blackVariance(exDate,0.0));BlackDeltaCalculator myCalc(value.type, DeltaVolQuote::PaSpot, spotQuote->value(), discDom,discFor, implVol);stochProcess=ext::make_shared<BlackScholesMertonProcess> (spotHandle,Handle<YieldTermStructure>(qTS),Handle<YieldTermStructure>(rTS),Handle<BlackVolTermStructure>(volTS));engine = ext::shared_ptr<PricingEngine>(new AnalyticEuropeanEngine(stochProcess));EuropeanOption option(payoff, exercise);option.setPricingEngine(engine);calculatedVal = myCalc.deltaFromStrike(value.strike);Real delta = 0.0;if (implVol > 0.0) {delta = option.delta();}else {const Real fwd = spotQuote->value()*discFor/discDom;if (payoff->optionType() == Option::Call && fwd > payoff->strike())delta = 1.0;else if (payoff->optionType() == Option::Put && fwd < payoff->strike())delta = -1.0;}expectedVal=delta-option.NPV()/spotQuote->value();error=std::fabs(expectedVal-calculatedVal);if(error>tolerance){BOOST_ERROR("\n Premium-adjusted spot delta test failed. \n" \<< "Calculated Delta: " << calculatedVal << "\n"<< "Expected Value: " << expectedVal << "\n"<< "Error: "<< error);}myCalc.setDeltaType(DeltaVolQuote::PaFwd);calculatedVal = myCalc.deltaFromStrike(value.strike);expectedVal=expectedVal/discFor; // Premium adjusted Fwd Delta is PA spot without discounterror=std::fabs(expectedVal-calculatedVal);if(error>tolerance){BOOST_ERROR("\n Premium-adjusted forward delta test failed. \n"<< "Calculated Delta: " << calculatedVal << "\n"<< "Expected Value: " << expectedVal << "\n"<< "Error: "<< error);}// Test consistency with BlackScholes Calculator for Spot DeltamyCalc.setDeltaType(DeltaVolQuote::Spot);calculatedVal = myCalc.deltaFromStrike(value.strike);expectedVal=delta;error=std::fabs(calculatedVal-expectedVal);if(error>tolerance){BOOST_ERROR("\n spot delta in BlackDeltaCalculator differs ""from delta in BlackScholesCalculator. \n"<< "Calculated Value: " << calculatedVal << "\n"<< "Expected Value: " << expectedVal << "\n"<< "Error: " << error);}}
}void BlackDeltaCalculatorTest::testPutCallParity(){BOOST_TEST_MESSAGE("Testing put-call parity for deltas...");using namespace black_delta_calculator_test;// Test for put call parity between put and call deltas.SavedSettings backup;/* The data below are from"Option pricing formulas", E.G. Haug, McGraw-Hill 1998pag 11-16*/EuropeanOptionData values[] = {// pag 2-8// type, strike, spot, q, r, t, vol, value, tol{ Option::Call, 65.00, 60.00, 0.00, 0.08, 0.25, 0.30, 2.1334, 1.0e-4},{ Option::Put, 95.00, 100.00, 0.05, 0.10, 0.50, 0.20, 2.4648, 1.0e-4},{ Option::Put, 19.00, 19.00, 0.10, 0.10, 0.75, 0.28, 1.7011, 1.0e-4},{ Option::Call, 19.00, 19.00, 0.10, 0.10, 0.75, 0.28, 1.7011, 1.0e-4},{ Option::Call, 1.60, 1.56, 0.08, 0.06, 0.50, 0.12, 0.0291, 1.0e-4},{ Option::Put, 70.00, 75.00, 0.05, 0.10, 0.50, 0.35, 4.0870, 1.0e-4},// pag 24{ Option::Call, 100.00, 90.00, 0.10, 0.10, 0.10, 0.15, 0.0205, 1.0e-4},{ Option::Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.15, 1.8734, 1.0e-4},{ Option::Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.15, 9.9413, 1.0e-4},{ Option::Call, 100.00, 90.00, 0.10, 0.10, 0.10, 0.25, 0.3150, 1.0e-4},{ Option::Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.25, 3.1217, 1.0e-4},{ Option::Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.25, 10.3556, 1.0e-4},{ Option::Call, 100.00, 90.00, 0.10, 0.10, 0.10, 0.35, 0.9474, 1.0e-4},{ Option::Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.35, 4.3693, 1.0e-4},{ Option::Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.35, 11.1381, 1.0e-4},{ Option::Call, 100.00, 90.00, 0.10, 0.10, 0.50, 0.15, 0.8069, 1.0e-4},{ Option::Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.15, 4.0232, 1.0e-4},{ Option::Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.15, 10.5769, 1.0e-4},{ Option::Call, 100.00, 90.00, 0.10, 0.10, 0.50, 0.25, 2.7026, 1.0e-4},{ Option::Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.25, 6.6997, 1.0e-4},{ Option::Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.25, 12.7857, 1.0e-4},{ Option::Call, 100.00, 90.00, 0.10, 0.10, 0.50, 0.35, 4.9329, 1.0e-4},{ Option::Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.35, 9.3679, 1.0e-4},{ Option::Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.35, 15.3086, 1.0e-4},{ Option::Put, 100.00, 90.00, 0.10, 0.10, 0.10, 0.15, 9.9210, 1.0e-4},{ Option::Put, 100.00, 100.00, 0.10, 0.10, 0.10, 0.15, 1.8734, 1.0e-4},{ Option::Put, 100.00, 110.00, 0.10, 0.10, 0.10, 0.15, 0.0408, 1.0e-4},{ Option::Put, 100.00, 90.00, 0.10, 0.10, 0.10, 0.25, 10.2155, 1.0e-4},{ Option::Put, 100.00, 100.00, 0.10, 0.10, 0.10, 0.25, 3.1217, 1.0e-4},{ Option::Put, 100.00, 110.00, 0.10, 0.10, 0.10, 0.25, 0.4551, 1.0e-4},{ Option::Put, 100.00, 90.00, 0.10, 0.10, 0.10, 0.35, 10.8479, 1.0e-4},{ Option::Put, 100.00, 100.00, 0.10, 0.10, 0.10, 0.35, 4.3693, 1.0e-4},{ Option::Put, 100.00, 110.00, 0.10, 0.10, 0.10, 0.35, 1.2376, 1.0e-4},{ Option::Put, 100.00, 90.00, 0.10, 0.10, 0.50, 0.15, 10.3192, 1.0e-4},{ Option::Put, 100.00, 100.00, 0.10, 0.10, 0.50, 0.15, 4.0232, 1.0e-4},{ Option::Put, 100.00, 110.00, 0.10, 0.10, 0.50, 0.15, 1.0646, 1.0e-4},{ Option::Put, 100.00, 90.00, 0.10, 0.10, 0.50, 0.25, 12.2149, 1.0e-4},{ Option::Put, 100.00, 100.00, 0.10, 0.10, 0.50, 0.25, 6.6997, 1.0e-4},{ Option::Put, 100.00, 110.00, 0.10, 0.10, 0.50, 0.25, 3.2734, 1.0e-4},{ Option::Put, 100.00, 90.00, 0.10, 0.10, 0.50, 0.35, 14.4452, 1.0e-4},{ Option::Put, 100.00, 100.00, 0.10, 0.10, 0.50, 0.35, 9.3679, 1.0e-4},{ Option::Put, 100.00, 110.00, 0.10, 0.10, 0.50, 0.35, 5.7963, 1.0e-4},// pag 27{ Option::Call, 40.00, 42.00, 0.08, 0.04, 0.75, 0.35, 5.0975, 1.0e-4}};DayCounter dc = Actual360();Calendar calendar = TARGET();Date today = Date::todaysDate();Real discFor =0.0;Real discDom =0.0;Real implVol =0.0;Real deltaCall =0.0;Real deltaPut =0.0;Real expectedDiff =0.0;Real calculatedDiff =0.0;Real error =0.0;Real forward =0.0;ext::shared_ptr<SimpleQuote> spotQuote(new SimpleQuote(0.0));ext::shared_ptr<SimpleQuote> qQuote(new SimpleQuote(0.0));Handle<Quote> qHandle(qQuote);ext::shared_ptr<YieldTermStructure> qTS(new FlatForward(today, qHandle, dc));ext::shared_ptr<SimpleQuote> rQuote(new SimpleQuote(0.0));Handle<Quote> rHandle(qQuote);ext::shared_ptr<YieldTermStructure> rTS(new FlatForward(today, rHandle, dc));ext::shared_ptr<SimpleQuote> volQuote(new SimpleQuote(0.0));Handle<Quote> volHandle(volQuote);ext::shared_ptr<BlackVolTermStructure> volTS(new BlackConstantVol(today, calendar, volHandle, dc));ext::shared_ptr<StrikedTypePayoff> payoff;Date exDate;ext::shared_ptr<Exercise> exercise;Real tolerance=1.0e-10;for (auto& value : values) {payoff =ext::shared_ptr<StrikedTypePayoff>(new PlainVanillaPayoff(Option::Call, value.strike));exDate = today + timeToDays(value.t);exercise = ext::shared_ptr<Exercise>(new EuropeanExercise(exDate));spotQuote->setValue(value.s);volQuote->setValue(value.v);rQuote->setValue(value.r);qQuote->setValue(value.q);discDom=rTS->discount(exDate);discFor=qTS->discount(exDate);implVol=sqrt(volTS->blackVariance(exDate,0.0));forward=spotQuote->value()*discFor/discDom;BlackDeltaCalculator myCalc(Option::Call, DeltaVolQuote::Spot,spotQuote->value(),discDom, discFor, implVol);deltaCall = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Put);deltaPut = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Call);expectedDiff=discFor;calculatedDiff=deltaCall-deltaPut;error=std::fabs(expectedDiff-calculatedDiff);if(error>tolerance){BOOST_ERROR("\n Put-call parity failed for spot delta. \n"<< "Calculated Call Delta: " << deltaCall << "\n"<< "Calculated Put Delta: " << deltaPut << "\n"<< "Expected Difference: " << expectedDiff << "\n"<< "Calculated Difference: " << calculatedDiff);}myCalc.setDeltaType(DeltaVolQuote::Fwd);deltaCall = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Put);deltaPut = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Call);expectedDiff=1.0;calculatedDiff=deltaCall-deltaPut;error=std::fabs(expectedDiff-calculatedDiff);if(error>tolerance){BOOST_ERROR("\n Put-call parity failed for forward delta. \n"<< "Calculated Call Delta: " << deltaCall << "\n"<< "Calculated Put Delta: " << deltaPut << "\n"<< "Expected Difference: " << expectedDiff << "\n"<< "Calculated Difference: " << calculatedDiff );}myCalc.setDeltaType(DeltaVolQuote::PaSpot);deltaCall = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Put);deltaPut = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Call);expectedDiff = discFor * value.strike / forward;calculatedDiff=deltaCall-deltaPut;error=std::fabs(expectedDiff-calculatedDiff);if(error>tolerance){BOOST_ERROR("\n Put-call parity failed for ""premium-adjusted spot delta. \n"<< "Calculated Call Delta: " << deltaCall << "\n"<< "Calculated Put Delta: " << deltaPut << "\n"<< "Expected Difference: " << expectedDiff << "\n"<< "Calculated Difference: " << calculatedDiff);}myCalc.setDeltaType(DeltaVolQuote::PaFwd);deltaCall = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Put);deltaPut = myCalc.deltaFromStrike(value.strike);;myCalc.setOptionType(Option::Call);expectedDiff = value.strike / forward;calculatedDiff=deltaCall-deltaPut;error=std::fabs(expectedDiff-calculatedDiff);if(error>tolerance){BOOST_ERROR("\n Put-call parity failed for premium-adjusted ""forward delta. \n"<< "Calculated Call Delta: " << deltaCall << "\n"<< "Calculated Put Delta: " << deltaPut << "\n"<< "Expected Difference: " << expectedDiff << "\n"<< "Calculated Difference: " << calculatedDiff);}}
}void BlackDeltaCalculatorTest::testAtmCalcs(){BOOST_TEST_MESSAGE("Testing delta-neutral ATM quotations...");using namespace black_delta_calculator_test;SavedSettings backup;DeltaData values[] = {{Option::Call, DeltaVolQuote::Spot, 1.421, 0.997306, 0.992266, 0.1180654, 1.608080, 0.15},{Option::Call, DeltaVolQuote::PaSpot, 1.421, 0.997306, 0.992266, 0.1180654, 1.600545, 0.15},{Option::Call, DeltaVolQuote::Fwd, 1.421, 0.997306, 0.992266, 0.1180654, 1.609029, 0.15},{Option::Call, DeltaVolQuote::PaFwd, 1.421, 0.997306, 0.992266, 0.1180654, 1.601550, 0.15},{Option::Call, DeltaVolQuote::Spot, 122.121, 0.9695434,0.9872347, 0.0887676, 119.8031, 0.67},{Option::Call, DeltaVolQuote::PaSpot, 122.121, 0.9695434,0.9872347, 0.0887676, 117.7096, 0.67},{Option::Call, DeltaVolQuote::Fwd, 122.121, 0.9695434,0.9872347, 0.0887676, 120.0592, 0.67},{Option::Call, DeltaVolQuote::PaFwd, 122.121, 0.9695434,0.9872347, 0.0887676, 118.0532, 0.67},{Option::Put, DeltaVolQuote::Spot, 3.4582, 0.99979, 0.9250616, 0.3199034, 4.964924, -0.821},{Option::Put, DeltaVolQuote::PaSpot, 3.4582, 0.99979, 0.9250616, 0.3199034, 3.778327, -0.821},{Option::Put, DeltaVolQuote::Fwd, 3.4582, 0.99979, 0.9250616, 0.3199034, 4.51896, -0.821},{Option::Put, DeltaVolQuote::PaFwd, 3.4582, 0.99979, 0.9250616, 0.3199034, 3.65728, -0.821},// Data taken from Castagnas "FX Options and Smile Risk" (Wiley 2009){Option::Put, DeltaVolQuote::Spot, 103.00, 0.99482, 0.98508, 0.07247845, 97.47, -0.25},{Option::Put, DeltaVolQuote::PaSpot, 103.00, 0.99482, 0.98508, 0.07247845, 97.22, -0.25},// Extreme case: zero vol, ATM Fwd strike{Option::Call, DeltaVolQuote::Fwd, 103.00, 0.99482, 0.98508, 0.0, 101.0013,0.5},{Option::Call, DeltaVolQuote::Spot, 103.00, 0.99482, 0.98508, 0.0, 101.0013,0.99482*0.5}};DeltaVolQuote::DeltaType currDt;Real currSpot;Real currdDf;Real currfDf;Real currStdDev;Real expected;Real calculated;Real error;Real tolerance=1.0e-2; // not that small, but sufficient for strikesReal currAtmStrike;Real currCallDelta;Real currPutDelta;Real currFwd;for (Size i=0; i<LENGTH(values); i++) {currDt =values[i].dt;currSpot =values[i].spot;currdDf =values[i].dDf;currfDf =values[i].fDf;currStdDev =values[i].stdDev;currFwd =currSpot*currfDf/currdDf;BlackDeltaCalculator myCalc(Option::Call, currDt, currSpot, currdDf,currfDf, currStdDev);currAtmStrike=myCalc.atmStrike(DeltaVolQuote::AtmDeltaNeutral);currCallDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Put);currPutDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Call);expected =0.0;calculated =currCallDelta+currPutDelta;error =std::fabs(calculated-expected);if(error>tolerance){BOOST_ERROR("\n Delta neutrality failed for spot delta ""in Delta Calculator. \n"<< "Iteration: "<< i << "\n"<< "Calculated Delta Sum: " << calculated << "\n"<< "Expected Delta Sum: " << expected << "\n"<< "Error: " << error);}myCalc.setDeltaType(DeltaVolQuote::Fwd);currAtmStrike=myCalc.atmStrike(DeltaVolQuote::AtmDeltaNeutral);currCallDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Put);currPutDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Call);expected =0.0;calculated =currCallDelta+currPutDelta;error =std::fabs(calculated-expected);if(error>tolerance){BOOST_ERROR("\n Delta neutrality failed for forward delta ""in Delta Calculator. \n"<< "Iteration: " << i << "\n"<< "Calculated Delta Sum: " << calculated << "\n"<< "Expected Delta Sum: " << expected << "\n"<< "Error: " << error);}myCalc.setDeltaType(DeltaVolQuote::PaSpot);currAtmStrike=myCalc.atmStrike(DeltaVolQuote::AtmDeltaNeutral);currCallDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Put);currPutDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Call);expected =0.0;calculated =currCallDelta+currPutDelta;error =std::fabs(calculated-expected);if(error>tolerance){BOOST_ERROR("\n Delta neutrality failed for premium-adjusted ""spot delta in Delta Calculator. \n"<< "Iteration: " << i << "\n"<< "Calculated Delta Sum: " << calculated << "\n"<< "Expected Delta Sum: " << expected << "\n"<< "Error: " << error);}myCalc.setDeltaType(DeltaVolQuote::PaFwd);currAtmStrike=myCalc.atmStrike(DeltaVolQuote::AtmDeltaNeutral);currCallDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Put);currPutDelta=myCalc.deltaFromStrike(currAtmStrike);myCalc.setOptionType(Option::Call);expected =0.0;calculated =currCallDelta+currPutDelta;error =std::fabs(calculated-expected);if(error>tolerance){BOOST_ERROR("\n Delta neutrality failed for premium-adjusted ""forward delta in Delta Calculator. \n"<< "Iteration: " << i << "\n"<< "Calculated Delta Sum: " << calculated << "\n"<< "Expected Delta Sum: " << expected << "\n"<< "Error: " << error);}// Test ATM forward Calculationscalculated=myCalc.atmStrike(DeltaVolQuote::AtmFwd);expected=currFwd;error=std::fabs(expected-calculated);if(error>tolerance){BOOST_ERROR("\n Atm forward test failed. \n"<< "Calculated Value: " << calculated << "\n"<< "Expected Value: " << expected << "\n"<< "Error: " << error);}// Test ATM 0.50 delta calculationsmyCalc.setDeltaType(DeltaVolQuote::Fwd);Real atmFiftyStrike=myCalc.atmStrike(DeltaVolQuote::AtmPutCall50);calculated=std::fabs(myCalc.deltaFromStrike(atmFiftyStrike));expected=0.50;error=std::fabs(expected-calculated);if(error>tolerance){BOOST_ERROR("\n Atm 0.50 delta strike test failed. \n"<< "Iteration:" << i << "\n"<< "Calculated Value: " << calculated << "\n"<< "Expected Value: " << expected << "\n"<< "Error: " << error);}}
}test_suite* BlackDeltaCalculatorTest::suite() {auto* suite = BOOST_TEST_SUITE("Black delta calculator tests");suite->add(QUANTLIB_TEST_CASE(&BlackDeltaCalculatorTest::testDeltaValues));suite->add(QUANTLIB_TEST_CASE(&BlackDeltaCalculatorTest::testDeltaPriceConsistency));suite->add(QUANTLIB_TEST_CASE(&BlackDeltaCalculatorTest::testPutCallParity));suite->add(QUANTLIB_TEST_CASE(&BlackDeltaCalculatorTest::testAtmCalcs));return suite;
}
该博文为原创文章,未经博主同意不得转。
本文章博客地址:https://cplusplus.blog.csdn.net/article/details/128310966
C++:实现量化BlackDelta测试实例相关推荐
- C++:实现 VOL量化指标测试实例
C++:实现 VOL量化指标测试实例 #include "inflationvolatility.hpp" #include "utilities.hpp"#i ...
- C++:实现量化OptionletStripper测试实例
C++:实现量化OptionletStripper测试实例 #include "optionletstripper.hpp" #include "utilities.hp ...
- C++:实现量化可转换债券测试实例
C++:实现量化可转换债券测试实例 #include "convertiblebonds.hpp" #include "utilities.hpp" #incl ...
- C++:实现量化相关的Interpolation插值测试实例
C++:实现量化相关的Interpolation插值测试实例 #include "interpolations.hpp" #include "utilities.hpp& ...
- C++:实现量化期权交易CDS加密货币衍生品测试实例
C++:实现量化期权交易CDS加密货币衍生品测试实例 #include <ql/qldefines.hpp> #if !defined(BOOST_ALL_NO_LIB) &&am ...
- C++:实现量化daycounters 日计数器测试实例
C++:实现量化daycounters 日计数器测试实例 #include "daycounters.hpp" #include "utilities.hpp" ...
- C++:实现量化CPI债券交换测试实例
C++:实现量化CPI债券交换测试实例 #include "utilities.hpp" #include "inflationcpiswap.hpp" #in ...
- C++:实现量化SMM Caplet均匀校准测试实例
C++:实现量化SMM Caplet均匀校准测试实例 #include "markovfunctional.hpp" #include "utilities.hpp&qu ...
- C++:实现量化Overnight-indexed swap 隔夜指数掉期测试实例
C++:实现量化Overnight-indexed swap 隔夜指数掉期测试实例 #include "overnightindexedswap.hpp" #include &qu ...
最新文章
- 自己制作 SPx N合1 自动安装盘(x86)
- 语言 提取列名_学习健明老师发布的R语言练习题的学习笔记(二)
- php 地址传递,PHP引用符传递存储地址
- Java中PO、DO、TO、DTO、 VO、 BO、POJO 、DAO的概念
- MySQL版本升级5.6到5.7版本
- 用计算机计算的结构图怎么画,冯·诺依曼计算机结构图解析
- 页面加载出现白页是什么原因造成的
- python websockets 网络聊天室V1
- WPF中资源字典(ResourceDictionary)的使用
- 一个如何在bash中使用getopts的例子
- java 实现回收站功能,回收站功能在 Linux 中的实现
- 根据某一字段值相同合并字符串
- 计算机兴趣画图活动记录,电脑绘画活动记录表(教案)
- 随机森林模型sklearn_Sklearn_随机森林
- 车载对讲机 计算机重启,对讲机常见问题解答
- 锐捷链路聚合实验配置
- webpack踩坑之路 (2)——图片的路径与打包
- contig纠错工具
- 驾考宝典携手HMS Core统一扫码服务,构建复杂场景中的流畅扫码体验
- 计算机和科学有关系吗,软件测试和计算机科学没有很大关系