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测试实例相关推荐

  1. C++:实现 VOL量化指标测试实例

    C++:实现 VOL量化指标测试实例 #include "inflationvolatility.hpp" #include "utilities.hpp"#i ...

  2. C++:实现量化OptionletStripper测试实例

    C++:实现量化OptionletStripper测试实例 #include "optionletstripper.hpp" #include "utilities.hp ...

  3. C++:实现量化可转换债券测试实例

    C++:实现量化可转换债券测试实例 #include "convertiblebonds.hpp" #include "utilities.hpp" #incl ...

  4. C++:实现量化相关的Interpolation插值测试实例

    C++:实现量化相关的Interpolation插值测试实例 #include "interpolations.hpp" #include "utilities.hpp& ...

  5. C++:实现量化期权交易CDS加密货币衍生品测试实例

    C++:实现量化期权交易CDS加密货币衍生品测试实例 #include <ql/qldefines.hpp> #if !defined(BOOST_ALL_NO_LIB) &&am ...

  6. C++:实现量化daycounters 日计数器测试实例

    C++:实现量化daycounters 日计数器测试实例 #include "daycounters.hpp" #include "utilities.hpp" ...

  7. C++:实现量化CPI债券交换测试实例

    C++:实现量化CPI债券交换测试实例 #include "utilities.hpp" #include "inflationcpiswap.hpp" #in ...

  8. C++:实现量化SMM Caplet均匀校准测试实例

    C++:实现量化SMM Caplet均匀校准测试实例 #include "markovfunctional.hpp" #include "utilities.hpp&qu ...

  9. C++:实现量化Overnight-indexed swap 隔夜指数掉期测试实例

    C++:实现量化Overnight-indexed swap 隔夜指数掉期测试实例 #include "overnightindexedswap.hpp" #include &qu ...

最新文章

  1. 自己制作 SPx N合1 自动安装盘(x86)
  2. 语言 提取列名_学习健明老师发布的R语言练习题的学习笔记(二)
  3. php 地址传递,PHP引用符传递存储地址
  4. Java中PO、DO、TO、DTO、 VO、 BO、POJO 、DAO的概念
  5. MySQL版本升级5.6到5.7版本
  6. 用计算机计算的结构图怎么画,冯·诺依曼计算机结构图解析
  7. 页面加载出现白页是什么原因造成的
  8. python websockets 网络聊天室V1
  9. WPF中资源字典(ResourceDictionary)的使用
  10. 一个如何在bash中使用getopts的例子
  11. java 实现回收站功能,回收站功能在 Linux 中的实现
  12. 根据某一字段值相同合并字符串
  13. 计算机兴趣画图活动记录,电脑绘画活动记录表(教案)
  14. 随机森林模型sklearn_Sklearn_随机森林
  15. 车载对讲机 计算机重启,对讲机常见问题解答
  16. 锐捷链路聚合实验配置
  17. webpack踩坑之路 (2)——图片的路径与打包
  18. contig纠错工具
  19. 驾考宝典携手HMS Core统一扫码服务,构建复杂场景中的流畅扫码体验
  20. 计算机和科学有关系吗,软件测试和计算机科学没有很大关系

热门文章

  1. 分布式系统中的时间和顺序——关于Spanner中的Linearizability
  2. Qt编写物联网管理平台48-特色功能设计
  3. 用matlab 实现向量范数和矩阵范数
  4. 国内首例直升飞机空降大学校园接女…
  5. Filmage Converter 视频转换器,MP4转换
  6. 做视频素材资源(free视频,音频,图片)
  7. rsync同步+inotify实时同步
  8. 「新品速递」AHE100无线温湿度传感器
  9. Android APIs (Class Index - Android SDK)(二)
  10. Shader学习_曲面细分着色器