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

#include "optionletstripper.hpp"
#include "utilities.hpp"
#include <ql/termstructures/volatility/optionlet/optionletstripper1.hpp>
#include <ql/termstructures/volatility/optionlet/optionletstripper2.hpp>
#include <ql/termstructures/volatility/optionlet/strippedoptionletadapter.hpp>
#include <ql/termstructures/volatility/capfloor/constantcapfloortermvol.hpp>
#include <ql/termstructures/volatility/capfloor/capfloortermvolcurve.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/termstructures/yield/zerocurve.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/indexes/ibor/euribor.hpp>
#include <ql/pricingengines/capfloor/blackcapfloorengine.hpp>
#include <ql/pricingengines/capfloor/bacheliercapfloorengine.hpp>
#include <ql/instruments/makecapfloor.hpp>
#include <ql/quotes/simplequote.hpp>
#include <algorithm>
#include <iterator>using namespace QuantLib;
using namespace boost::unit_test_framework;namespace optionlet_stripper_test {struct CommonVars {// global dataCalendar calendar;DayCounter dayCounter;RelinkableHandle<YieldTermStructure> yieldTermStructure;RelinkableHandle< YieldTermStructure > discountingYTS;RelinkableHandle< YieldTermStructure > forwardingYTS;std::vector<Rate> strikes;std::vector<Period> optionTenors;Matrix termV;std::vector<Rate> atmTermV;std::vector<Handle<Quote> > atmTermVolHandle;Handle<CapFloorTermVolCurve> capFloorVolCurve;Handle<CapFloorTermVolCurve> flatTermVolCurve;ext::shared_ptr<CapFloorTermVolSurface> capFloorVolSurface;ext::shared_ptr<CapFloorTermVolSurface> flatTermVolSurface;ext::shared_ptr< CapFloorTermVolSurface > capFloorVolRealSurface;Real accuracy;Real tolerance;// cleanupSavedSettings backup;CommonVars() {accuracy = 1.0e-6;tolerance = 2.5e-8;}void setTermStructure() {calendar = TARGET();dayCounter = Actual365Fixed();Rate flatFwdRate = 0.04;yieldTermStructure.linkTo(ext::make_shared<FlatForward>(0,calendar,flatFwdRate,dayCounter));}void setRealTermStructure() {calendar = TARGET();dayCounter = Actual365Fixed();std::vector< int > datesTmp = {42124, 42129, 42143, 42221, 42254, 42282, 42313, 42345,42374, 42405, 42465, 42495, 42587, 42681, 42772, 42860, 43227,43956, 44321, 44686, 45051, 45418, 45782, 46147, 46512, 47609,49436, 51263, 53087, 56739, 60392};std::vector< Date > dates;dates.reserve(datesTmp.size());for (int& it : datesTmp)dates.emplace_back(it);std::vector< Rate > rates = {-0.00292, -0.00292, -0.001441, -0.00117, -0.001204,-0.001212, -0.001223, -0.001236, -0.001221, -0.001238,-0.001262, -0.00125, -0.001256, -0.001233, -0.00118, -0.001108,-0.000619, 0.000833, 0.001617, 0.002414, 0.003183, 0.003883,0.004514, 0.005074, 0.005606, 0.006856, 0.00813, 0.008709,0.009136, 0.009601, 0.009384};discountingYTS.linkTo(ext::make_shared< InterpolatedZeroCurve< Linear > >(dates, rates,dayCounter, calendar));datesTmp.clear();dates.clear();rates.clear();datesTmp = {42124, 42313, 42436, 42556, 42618, 42800, 42830, 42860,43227, 43591, 43956, 44321, 44686, 45051, 45418, 45782, 46147,46512, 46878, 47245, 47609, 47973, 48339, 48704, 49069, 49436,49800, 50165, 50530, 50895, 51263, 51627, 51991, 52356, 52722,53087, 54913, 56739, 60392, 64045};for (int& it : datesTmp)dates.emplace_back(it);rates = {0.000649, 0.000649, 0.000684, 0.000717, 0.000745, 0.000872,0.000905, 0.000954, 0.001532, 0.002319, 0.003147, 0.003949,0.004743, 0.00551, 0.006198, 0.006798, 0.007339, 0.007832,0.008242, 0.008614, 0.008935, 0.009205, 0.009443, 0.009651,0.009818, 0.009952, 0.010054, 0.010146, 0.010206, 0.010266,0.010315, 0.010365, 0.010416, 0.010468, 0.010519, 0.010571,0.010757, 0.010806, 0.010423, 0.010217};forwardingYTS.linkTo(ext::make_shared< InterpolatedZeroCurve< Linear > >(dates, rates, dayCounter, calendar));}void setFlatTermVolCurve() {setTermStructure();optionTenors.resize(10);for (Size i = 0; i < optionTenors.size(); ++i)optionTenors[i] = Period(i + 1, Years);Volatility flatVol = .18;std::vector<Handle<Quote> >  curveVHandle(optionTenors.size());for (Size i=0; i<optionTenors.size(); ++i)curveVHandle[i] = Handle<Quote>(ext::shared_ptr<Quote>(newSimpleQuote(flatVol)));flatTermVolCurve = Handle<CapFloorTermVolCurve>(ext::make_shared<CapFloorTermVolCurve>(0, calendar, Following, optionTenors,curveVHandle, dayCounter));}void setFlatTermVolSurface() {setTermStructure();optionTenors.resize(10);for (Size i = 0; i < optionTenors.size(); ++i)optionTenors[i] = Period(i + 1, Years);strikes.resize(10);for (Size j = 0; j < strikes.size(); ++j)strikes[j] = Real(j + 1) / 100.0;Volatility flatVol = .18;termV = Matrix(optionTenors.size(), strikes.size(), flatVol);flatTermVolSurface = ext::make_shared<CapFloorTermVolSurface>(0, calendar, Following,optionTenors, strikes,termV, dayCounter);}void setCapFloorTermVolCurve() {setTermStructure();//atm cap volatility curveoptionTenors = {{1, Years},{18, Months},{2, Years},{3, Years},{4, Years},{5, Years},{6, Years},{7, Years},{8, Years},{9, Years},{10, Years},{12, Years},{15, Years},{20, Years},{25, Years},{30, Years}};//atm capfloor vols from mkt vol matrix using flat yield curveatmTermV = {0.090304,0.12180,0.13077,0.14832,0.15570,0.15816,0.15932,0.16035,0.15951,0.15855,0.15754,0.15459,0.15163,0.14575,0.14175,0.13889};atmTermVolHandle.resize(optionTenors.size());for (Size i=0; i<optionTenors.size(); ++i) {atmTermVolHandle[i] = Handle<Quote>(ext::shared_ptr<Quote>(newSimpleQuote(atmTermV[i])));}capFloorVolCurve = Handle<CapFloorTermVolCurve>(ext::make_shared<CapFloorTermVolCurve>(0, calendar, Following,optionTenors, atmTermVolHandle,dayCounter));}void setCapFloorTermVolSurface() {setTermStructure();//cap volatility smile matrixoptionTenors = {{1, Years},{18, Months},{2, Years},{3, Years},{4, Years},{5, Years},{6, Years},{7, Years},{8, Years},{9, Years},{10, Years},{12, Years},{15, Years},{20, Years},{25, Years},{30, Years}};strikes = {0.015,0.0175,0.02,0.0225,0.025,0.03,0.035,0.04,0.05,0.06,0.07,0.08,0.1};termV = Matrix(optionTenors.size(), strikes.size());termV[0][0]=0.287;  termV[0][1]=0.274;  termV[0][2]=0.256;  termV[0][3]=0.245;  termV[0][4]=0.227;  termV[0][5]=0.148;  termV[0][6]=0.096;  termV[0][7]=0.09;   termV[0][8]=0.11;   termV[0][9]=0.139;  termV[0][10]=0.166;  termV[0][11]=0.19;   termV[0][12]=0.214;termV[1][0]=0.303;  termV[1][1]=0.258;  termV[1][2]=0.22;   termV[1][3]=0.203;  termV[1][4]=0.19;   termV[1][5]=0.153;  termV[1][6]=0.126;  termV[1][7]=0.118;  termV[1][8]=0.147;  termV[1][9]=0.165;  termV[1][10]=0.18;   termV[1][11]=0.192;  termV[1][12]=0.212;termV[2][0]=0.303;  termV[2][1]=0.257;  termV[2][2]=0.216;  termV[2][3]=0.196;  termV[2][4]=0.182;  termV[2][5]=0.154;  termV[2][6]=0.134;  termV[2][7]=0.127;  termV[2][8]=0.149;  termV[2][9]=0.166;  termV[2][10]=0.18;   termV[2][11]=0.192;  termV[2][12]=0.212;termV[3][0]=0.305;  termV[3][1]=0.266;  termV[3][2]=0.226;  termV[3][3]=0.203;  termV[3][4]=0.19;   termV[3][5]=0.167;  termV[3][6]=0.151;  termV[3][7]=0.144;  termV[3][8]=0.16;   termV[3][9]=0.172;  termV[3][10]=0.183;  termV[3][11]=0.193;  termV[3][12]=0.209;termV[4][0]=0.294;  termV[4][1]=0.261;  termV[4][2]=0.216;  termV[4][3]=0.201;  termV[4][4]=0.19;   termV[4][5]=0.171;  termV[4][6]=0.158;  termV[4][7]=0.151;  termV[4][8]=0.163;  termV[4][9]=0.172;  termV[4][10]=0.181;  termV[4][11]=0.188;  termV[4][12]=0.201;termV[5][0]=0.276;  termV[5][1]=0.248;  termV[5][2]=0.212;  termV[5][3]=0.199;  termV[5][4]=0.189;  termV[5][5]=0.172;  termV[5][6]=0.16;   termV[5][7]=0.155;  termV[5][8]=0.162;  termV[5][9]=0.17;   termV[5][10]=0.177;  termV[5][11]=0.183;  termV[5][12]=0.195;termV[6][0]=0.26;   termV[6][1]=0.237;  termV[6][2]=0.21;   termV[6][3]=0.198;  termV[6][4]=0.188;  termV[6][5]=0.172;  termV[6][6]=0.161;  termV[6][7]=0.156;  termV[6][8]=0.161;  termV[6][9]=0.167;  termV[6][10]=0.173;  termV[6][11]=0.179;  termV[6][12]=0.19;termV[7][0]=0.25;   termV[7][1]=0.231;  termV[7][2]=0.208;  termV[7][3]=0.196;  termV[7][4]=0.187;  termV[7][5]=0.172;  termV[7][6]=0.162;  termV[7][7]=0.156;  termV[7][8]=0.16;   termV[7][9]=0.165;  termV[7][10]=0.17;   termV[7][11]=0.175;  termV[7][12]=0.185;termV[8][0]=0.244;  termV[8][1]=0.226;  termV[8][2]=0.206;  termV[8][3]=0.195;  termV[8][4]=0.186;  termV[8][5]=0.171;  termV[8][6]=0.161;  termV[8][7]=0.156;  termV[8][8]=0.158;  termV[8][9]=0.162;  termV[8][10]=0.166;  termV[8][11]=0.171;  termV[8][12]=0.18;termV[9][0]=0.239;  termV[9][1]=0.222;  termV[9][2]=0.204;  termV[9][3]=0.193;  termV[9][4]=0.185;  termV[9][5]=0.17;   termV[9][6]=0.16;   termV[9][7]=0.155;  termV[9][8]=0.156;  termV[9][9]=0.159;  termV[9][10]=0.163;  termV[9][11]=0.168;  termV[9][12]=0.177;termV[10][0]=0.235; termV[10][1]=0.219; termV[10][2]=0.202; termV[10][3]=0.192; termV[10][4]=0.183; termV[10][5]=0.169; termV[10][6]=0.159; termV[10][7]=0.154; termV[10][8]=0.154; termV[10][9]=0.156; termV[10][10]=0.16;  termV[10][11]=0.164; termV[10][12]=0.173;termV[11][0]=0.227; termV[11][1]=0.212; termV[11][2]=0.197; termV[11][3]=0.187; termV[11][4]=0.179; termV[11][5]=0.166; termV[11][6]=0.156; termV[11][7]=0.151; termV[11][8]=0.149; termV[11][9]=0.15;  termV[11][10]=0.153; termV[11][11]=0.157; termV[11][12]=0.165;termV[12][0]=0.22;  termV[12][1]=0.206; termV[12][2]=0.192; termV[12][3]=0.183; termV[12][4]=0.175; termV[12][5]=0.162; termV[12][6]=0.153; termV[12][7]=0.147; termV[12][8]=0.144; termV[12][9]=0.144; termV[12][10]=0.147; termV[12][11]=0.151; termV[12][12]=0.158;termV[13][0]=0.211; termV[13][1]=0.197; termV[13][2]=0.185; termV[13][3]=0.176; termV[13][4]=0.168; termV[13][5]=0.156; termV[13][6]=0.147; termV[13][7]=0.142; termV[13][8]=0.138; termV[13][9]=0.138; termV[13][10]=0.14;  termV[13][11]=0.144; termV[13][12]=0.151;termV[14][0]=0.204; termV[14][1]=0.192; termV[14][2]=0.18;  termV[14][3]=0.171; termV[14][4]=0.164; termV[14][5]=0.152; termV[14][6]=0.143; termV[14][7]=0.138; termV[14][8]=0.134; termV[14][9]=0.134; termV[14][10]=0.137; termV[14][11]=0.14;  termV[14][12]=0.148;termV[15][0]=0.2;   termV[15][1]=0.187; termV[15][2]=0.176; termV[15][3]=0.167; termV[15][4]=0.16;  termV[15][5]=0.148; termV[15][6]=0.14;  termV[15][7]=0.135; termV[15][8]=0.131; termV[15][9]=0.132; termV[15][10]=0.135; termV[15][11]=0.139; termV[15][12]=0.146;capFloorVolSurface = ext::make_shared<CapFloorTermVolSurface>(0, calendar, Following,optionTenors, strikes,termV, dayCounter);}void setRealCapFloorTermVolSurface() {setRealTermStructure();// cap volatility smile matrixoptionTenors = {{1, Years},{18, Months},{2, Years},{3, Years},{4, Years},{5, Years},{6, Years},{7, Years},{8, Years},{9, Years},{10, Years},{12, Years},{15, Years},{20, Years},{25, Years},{30, Years}};// 16strikes = {-0.005,-0.0025,-0.00125,0.0,0.00125,0.0025,0.005,0.01,0.015,0.02,0.03,0.05,0.1};// 13std::vector< Real > rawVols = {0.49, 0.39, 0.34, 0.31, 0.34, 0.37, 0.50, 0.75, 0.99, 1.21, 1.64, 2.44, 4.29,0.44, 0.36, 0.33, 0.31, 0.33, 0.35,0.45, 0.65, 0.83, 1.00, 1.32, 1.93, 3.30,0.40, 0.35, 0.33,0.31, 0.33, 0.34, 0.41, 0.55, 0.69, 0.82, 1.08, 1.56, 2.68,0.42, 0.39, 0.38, 0.37, 0.38, 0.39, 0.43, 0.54, 0.64, 0.74,0.94, 1.31, 2.18,0.46, 0.43, 0.42, 0.41, 0.42, 0.43, 0.47,0.56, 0.66, 0.75, 0.93, 1.28, 2.07,0.49, 0.47, 0.46, 0.45,0.46, 0.47, 0.51, 0.59, 0.68, 0.76, 0.93, 1.25, 1.99,0.51, 0.49, 0.49, 0.48, 0.49, 0.50, 0.54, 0.62, 0.70, 0.78, 0.94,1.24, 1.94,0.52, 0.51, 0.51, 0.51, 0.52, 0.53, 0.56, 0.63,0.71, 0.79, 0.94, 1.23, 1.89,0.53, 0.52, 0.52, 0.52, 0.53,0.54, 0.57, 0.65, 0.72, 0.79, 0.94, 1.21, 1.83,0.55, 0.54, 0.54, 0.54, 0.55, 0.56, 0.59, 0.66, 0.72, 0.79, 0.91, 1.15,1.71,0.56, 0.56, 0.56, 0.56, 0.57, 0.58, 0.61, 0.67, 0.72,0.78, 0.89, 1.09, 1.59,0.59, 0.58, 0.58, 0.59, 0.59, 0.60,0.63, 0.68, 0.73, 0.78, 0.86, 1.03, 1.45,0.61, 0.61, 0.61,0.61, 0.62, 0.62, 0.64, 0.69, 0.73, 0.77, 0.85, 1.02, 1.44,0.62, 0.62, 0.63, 0.63, 0.64, 0.64, 0.65, 0.69, 0.72, 0.76,0.82, 0.96, 1.32,0.62, 0.63, 0.63, 0.63, 0.65, 0.66, 0.66,0.68, 0.72, 0.74, 0.80, 0.93, 1.25,0.62, 0.62, 0.62, 0.62,0.66, 0.67, 0.67, 0.67, 0.72, 0.72, 0.78, 0.90, 1.25};termV = Matrix(optionTenors.size(), strikes.size());std::copy(rawVols.begin(), rawVols.end(), termV.begin());termV /= 100;capFloorVolRealSurface =ext::make_shared< CapFloorTermVolSurface >(0, calendar, Following,optionTenors, strikes, termV,dayCounter);}
};
}void OptionletStripperTest::testFlatTermVolatilityStripping1() {BOOST_TEST_MESSAGE("Testing forward/forward vol stripping from flat term vol ""surface using OptionletStripper1 class...");using namespace optionlet_stripper_test;CommonVars vars;Settings::instance().evaluationDate() = Date(28, October, 2013);vars.setFlatTermVolSurface();ext::shared_ptr<IborIndex> iborIndex(new Euribor6M(vars.yieldTermStructure));ext::shared_ptr<OptionletStripper> optionletStripper1(newOptionletStripper1(vars.flatTermVolSurface,iborIndex,Null<Rate>(),vars.accuracy));ext::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter(newStrippedOptionletAdapter(optionletStripper1));Handle<OptionletVolatilityStructure> vol(strippedOptionletAdapter);vol->enableExtrapolation();ext::shared_ptr<BlackCapFloorEngine> strippedVolEngine(newBlackCapFloorEngine(vars.yieldTermStructure,vol));ext::shared_ptr<CapFloor> cap;for (Size tenorIndex=0; tenorIndex<vars.optionTenors.size(); ++tenorIndex) {for (Size strikeIndex=0; strikeIndex<vars.strikes.size(); ++strikeIndex) {cap = MakeCapFloor(CapFloor::Cap,vars.optionTenors[tenorIndex],iborIndex,vars.strikes[strikeIndex],0*Days).withPricingEngine(strippedVolEngine);Real priceFromStrippedVolatility = cap->NPV();ext::shared_ptr<PricingEngine> blackCapFloorEngineConstantVolatility(newBlackCapFloorEngine(vars.yieldTermStructure,vars.termV[tenorIndex][strikeIndex]));cap->setPricingEngine(blackCapFloorEngineConstantVolatility);Real priceFromConstantVolatility = cap->NPV();Real error = std::fabs(priceFromStrippedVolatility - priceFromConstantVolatility);if (error>vars.tolerance)BOOST_FAIL("\noption tenor:       " << vars.optionTenors[tenorIndex] <<"\nstrike:             " << io::rate(vars.strikes[strikeIndex]) <<"\nstripped vol price: " << io::rate(priceFromStrippedVolatility) <<"\nconstant vol price: " << io::rate(priceFromConstantVolatility) <<"\nerror:              " << io::rate(error) <<"\ntolerance:          " << io::rate(vars.tolerance));}}
}void OptionletStripperTest::testTermVolatilityStripping1() {BOOST_TEST_MESSAGE("Testing forward/forward vol stripping from non-flat term ""vol surface using OptionletStripper1 class...");using namespace optionlet_stripper_test;CommonVars vars;Settings::instance().evaluationDate() = Date(28, October, 2013);vars.setCapFloorTermVolSurface();ext::shared_ptr<IborIndex> iborIndex(new Euribor6M(vars.yieldTermStructure));ext::shared_ptr<OptionletStripper> optionletStripper1(newOptionletStripper1(vars.capFloorVolSurface,iborIndex,Null<Rate>(),vars.accuracy));ext::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter =ext::make_shared<StrippedOptionletAdapter>(optionletStripper1);Handle<OptionletVolatilityStructure> vol(strippedOptionletAdapter);vol->enableExtrapolation();ext::shared_ptr<BlackCapFloorEngine> strippedVolEngine(newBlackCapFloorEngine(vars.yieldTermStructure,vol));ext::shared_ptr<CapFloor> cap;for (Size tenorIndex=0; tenorIndex<vars.optionTenors.size(); ++tenorIndex) {for (Size strikeIndex=0; strikeIndex<vars.strikes.size(); ++strikeIndex) {cap = MakeCapFloor(CapFloor::Cap,vars.optionTenors[tenorIndex],iborIndex,vars.strikes[strikeIndex],0*Days).withPricingEngine(strippedVolEngine);Real priceFromStrippedVolatility = cap->NPV();ext::shared_ptr<PricingEngine> blackCapFloorEngineConstantVolatility(newBlackCapFloorEngine(vars.yieldTermStructure,vars.termV[tenorIndex][strikeIndex]));cap->setPricingEngine(blackCapFloorEngineConstantVolatility);Real priceFromConstantVolatility = cap->NPV();Real error = std::fabs(priceFromStrippedVolatility - priceFromConstantVolatility);if (error>vars.tolerance)BOOST_FAIL("\noption tenor:       " << vars.optionTenors[tenorIndex] <<"\nstrike:             " << io::rate(vars.strikes[strikeIndex]) <<"\nstripped vol price: " << io::rate(priceFromStrippedVolatility) <<"\nconstant vol price: " << io::rate(priceFromConstantVolatility) <<"\nerror:              " << io::rate(error) <<"\ntolerance:          " << io::rate(vars.tolerance));}}
}void OptionletStripperTest::testTermVolatilityStrippingNormalVol() {BOOST_TEST_MESSAGE("Testing forward/forward vol stripping from non-flat normal vol term ""vol surface for normal vol setup using OptionletStripper1 class...");using namespace optionlet_stripper_test;CommonVars vars;Settings::instance().evaluationDate() = Date(30, April, 2015);vars.setRealCapFloorTermVolSurface();ext::shared_ptr< IborIndex > iborIndex(new Euribor6M(vars.forwardingYTS));ext::shared_ptr< OptionletStripper > optionletStripper1(new OptionletStripper1(vars.capFloorVolRealSurface, iborIndex,Null< Rate >(), vars.accuracy, 100,vars.discountingYTS, Normal));ext::shared_ptr< StrippedOptionletAdapter > strippedOptionletAdapter =ext::make_shared< StrippedOptionletAdapter >(optionletStripper1);Handle< OptionletVolatilityStructure > vol(strippedOptionletAdapter);vol->enableExtrapolation();ext::shared_ptr< BachelierCapFloorEngine > strippedVolEngine(new BachelierCapFloorEngine(vars.discountingYTS, vol));ext::shared_ptr< CapFloor > cap;for (Size tenorIndex = 0; tenorIndex < vars.optionTenors.size();++tenorIndex) {for (Size strikeIndex = 0; strikeIndex < vars.strikes.size();++strikeIndex) {cap = MakeCapFloor(CapFloor::Cap, vars.optionTenors[tenorIndex],iborIndex, vars.strikes[strikeIndex],0 * Days).withPricingEngine(strippedVolEngine);Real priceFromStrippedVolatility = cap->NPV();ext::shared_ptr< PricingEngine >bachelierCapFloorEngineConstantVolatility(new BachelierCapFloorEngine(vars.discountingYTS,vars.termV[tenorIndex][strikeIndex]));cap->setPricingEngine(bachelierCapFloorEngineConstantVolatility);Real priceFromConstantVolatility = cap->NPV();Real error = std::fabs(priceFromStrippedVolatility -priceFromConstantVolatility);if (error > vars.tolerance)BOOST_FAIL("\noption tenor:       "<< vars.optionTenors[tenorIndex] << "\nstrike:             "<< io::rate(vars.strikes[strikeIndex])<< "\nstripped vol price: "<< io::rate(priceFromStrippedVolatility)<< "\nconstant vol price: "<< io::rate(priceFromConstantVolatility)<< "\nerror:              " << io::rate(error)<< "\ntolerance:          " << io::rate(vars.tolerance));}}
}void OptionletStripperTest::testTermVolatilityStrippingShiftedLogNormalVol() {BOOST_TEST_MESSAGE("Testing forward/forward vol stripping from non-flat normal vol term ""vol surface for normal vol setup using OptionletStripper1 class...");using namespace optionlet_stripper_test;CommonVars vars;Real shift = 0.03;Settings::instance().evaluationDate() = Date(30, April, 2015);vars.setRealCapFloorTermVolSurface();ext::shared_ptr< IborIndex > iborIndex(new Euribor6M(vars.forwardingYTS));ext::shared_ptr< OptionletStripper > optionletStripper1(new OptionletStripper1(vars.capFloorVolRealSurface, iborIndex,Null< Rate >(), vars.accuracy, 100,vars.discountingYTS, ShiftedLognormal, shift,true));ext::shared_ptr< StrippedOptionletAdapter > strippedOptionletAdapter =ext::make_shared< StrippedOptionletAdapter >(optionletStripper1);Handle< OptionletVolatilityStructure > vol(strippedOptionletAdapter);vol->enableExtrapolation();ext::shared_ptr< BlackCapFloorEngine > strippedVolEngine(new BlackCapFloorEngine(vars.discountingYTS, vol));ext::shared_ptr< CapFloor > cap;for (Size strikeIndex = 0; strikeIndex < vars.strikes.size();++strikeIndex) {for (Size tenorIndex = 0; tenorIndex < vars.optionTenors.size();++tenorIndex) {cap = MakeCapFloor(CapFloor::Cap, vars.optionTenors[tenorIndex],iborIndex, vars.strikes[strikeIndex],0 * Days).withPricingEngine(strippedVolEngine);Real priceFromStrippedVolatility = cap->NPV();ext::shared_ptr< PricingEngine >blackCapFloorEngineConstantVolatility(new BlackCapFloorEngine(vars.discountingYTS, vars.termV[tenorIndex][strikeIndex],vars.capFloorVolRealSurface->dayCounter(), shift));cap->setPricingEngine(blackCapFloorEngineConstantVolatility);Real priceFromConstantVolatility = cap->NPV();Real error = std::fabs(priceFromStrippedVolatility -priceFromConstantVolatility);if (error > vars.tolerance)BOOST_FAIL("\noption tenor:       "<< vars.optionTenors[tenorIndex] << "\nstrike:             "<< io::rate(vars.strikes[strikeIndex])<< "\nstripped vol price: "<< io::rate(priceFromStrippedVolatility)<< "\nconstant vol price: "<< io::rate(priceFromConstantVolatility)<< "\nerror:              " << io::rate(error)<< "\ntolerance:          " << io::rate(vars.tolerance));}}
}void OptionletStripperTest::testFlatTermVolatilityStripping2() {BOOST_TEST_MESSAGE("Testing forward/forward vol stripping from flat term vol ""surface using OptionletStripper2 class...");using namespace optionlet_stripper_test;CommonVars vars;Settings::instance().evaluationDate() = Date::todaysDate();vars.setFlatTermVolCurve();vars.setFlatTermVolSurface();ext::shared_ptr<IborIndex> iborIndex(new Euribor6M(vars.yieldTermStructure));// optionletstripper1ext::shared_ptr<OptionletStripper1> optionletStripper1(newOptionletStripper1(vars.flatTermVolSurface,iborIndex,Null<Rate>(),vars.accuracy));ext::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter1(newStrippedOptionletAdapter(optionletStripper1));Handle<OptionletVolatilityStructure> vol1(strippedOptionletAdapter1);vol1->enableExtrapolation();// optionletstripper2ext::shared_ptr<OptionletStripper> optionletStripper2(newOptionletStripper2(optionletStripper1, vars.flatTermVolCurve));ext::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter2(newStrippedOptionletAdapter(optionletStripper2));Handle<OptionletVolatilityStructure> vol2(strippedOptionletAdapter2);vol2->enableExtrapolation();// consistency check: diff(stripped vol1-stripped vol2)for (Size strikeIndex=0; strikeIndex<vars.strikes.size(); ++strikeIndex) {for (Size tenorIndex=0; tenorIndex<vars.optionTenors.size(); ++tenorIndex) {Volatility strippedVol1 = vol1->volatility(vars.optionTenors[tenorIndex],vars.strikes[strikeIndex], true);Volatility strippedVol2 = vol2->volatility(vars.optionTenors[tenorIndex],vars.strikes[strikeIndex], true);// vol from flat vol surface (for comparison only)Volatility flatVol = vars.flatTermVolSurface->volatility(vars.optionTenors[tenorIndex],vars.strikes[strikeIndex], true);Real error = std::fabs(strippedVol1-strippedVol2);if (error>vars.tolerance)BOOST_FAIL("\noption tenor:  " << vars.optionTenors[tenorIndex] <<"\nstrike:        " << io::rate(vars.strikes[strikeIndex]) <<"\nstripped vol1: " << io::rate(strippedVol1) <<"\nstripped vol2: " << io::rate(strippedVol2) <<"\nflat vol:      " << io::rate(flatVol) <<"\nerror:         " << io::rate(error) <<"\ntolerance:     " << io::rate(vars.tolerance));}}}void OptionletStripperTest::testTermVolatilityStripping2() {BOOST_TEST_MESSAGE("Testing forward/forward vol stripping from non-flat term vol ""surface using OptionletStripper2 class...");using namespace optionlet_stripper_test;CommonVars vars;Settings::instance().evaluationDate() = Date::todaysDate();vars.setCapFloorTermVolCurve();vars.setCapFloorTermVolSurface();ext::shared_ptr<IborIndex> iborIndex(new Euribor6M(vars.yieldTermStructure));// optionletstripper1ext::shared_ptr<OptionletStripper1> optionletStripper1(newOptionletStripper1(vars.capFloorVolSurface,iborIndex,Null<Rate>(),vars.accuracy));ext::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter1 =ext::make_shared<StrippedOptionletAdapter>(optionletStripper1);Handle<OptionletVolatilityStructure> vol1(strippedOptionletAdapter1);vol1->enableExtrapolation();// optionletstripper2ext::shared_ptr<OptionletStripper> optionletStripper2(newOptionletStripper2(optionletStripper1,vars.capFloorVolCurve));ext::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter2(newStrippedOptionletAdapter(optionletStripper2));Handle<OptionletVolatilityStructure> vol2(strippedOptionletAdapter2);vol2->enableExtrapolation();// consistency check: diff(stripped vol1-stripped vol2)for (Size strikeIndex=0; strikeIndex<vars.strikes.size(); ++strikeIndex) {for (Size tenorIndex=0; tenorIndex<vars.optionTenors.size(); ++tenorIndex) {Volatility strippedVol1 = vol1->volatility(vars.optionTenors[tenorIndex],vars.strikes[strikeIndex], true);Volatility strippedVol2 = vol2->volatility(vars.optionTenors[tenorIndex],vars.strikes[strikeIndex], true);// vol from flat vol surface (for comparison only)Volatility flatVol = vars.capFloorVolSurface->volatility(vars.optionTenors[tenorIndex],vars.strikes[strikeIndex], true);Real error = std::fabs(strippedVol1-strippedVol2);if (error>vars.tolerance)BOOST_FAIL("\noption tenor:  " << vars.optionTenors[tenorIndex] <<"\nstrike:        " << io::rate(vars.strikes[strikeIndex]) <<"\nstripped vol1: " << io::rate(strippedVol1) <<"\nstripped vol2: " << io::rate(strippedVol2) <<"\nflat vol:      " << io::rate(flatVol) <<"\nerror:         " << io::rate(error) <<"\ntolerance:     " << io::rate(vars.tolerance));}}
}void OptionletStripperTest::testSwitchStrike() {BOOST_TEST_MESSAGE("Testing switch strike level and recalibration of level ""in case of curve relinking...");using namespace optionlet_stripper_test;bool usingAtParCoupons  = IborCoupon::Settings::instance().usingAtParCoupons();CommonVars vars;Settings::instance().evaluationDate() = Date(28, October, 2013);vars.setCapFloorTermVolSurface();RelinkableHandle< YieldTermStructure > yieldTermStructure;yieldTermStructure.linkTo(ext::make_shared< FlatForward >(0, vars.calendar, 0.03, vars.dayCounter));ext::shared_ptr< IborIndex > iborIndex(new Euribor6M(yieldTermStructure));ext::shared_ptr< OptionletStripper1 > optionletStripper1(new OptionletStripper1(vars.capFloorVolSurface, iborIndex,Null< Rate >(), vars.accuracy));Real expected = usingAtParCoupons ? 0.02981223 : 0.02981258;Real error = std::fabs(optionletStripper1->switchStrike() - expected);if (error > vars.tolerance)BOOST_FAIL("\nSwitchstrike not correctly computed:  "<< "\nexpected switch strike: " << io::rate(expected)<< "\ncomputed switch strike: "<< io::rate(optionletStripper1->switchStrike())<< "\nerror:         " << io::rate(error)<< "\ntolerance:     " << io::rate(vars.tolerance));yieldTermStructure.linkTo(ext::make_shared< FlatForward >(0, vars.calendar, 0.05, vars.dayCounter));expected = usingAtParCoupons ? 0.0499371 : 0.0499381;error = std::fabs(optionletStripper1->switchStrike() - expected);if (error > vars.tolerance)BOOST_FAIL("\nSwitchstrike not correctly computed:  "<< "\nexpected switch strike: " << io::rate(expected)<< "\ncomputed switch strike: "<< io::rate(optionletStripper1->switchStrike())<< "\nerror:         " << io::rate(error)<< "\ntolerance:     " << io::rate(vars.tolerance));
}test_suite* OptionletStripperTest::suite() {auto* suite = BOOST_TEST_SUITE("OptionletStripper Tests");suite->add(QUANTLIB_TEST_CASE(&OptionletStripperTest::testFlatTermVolatilityStripping1));suite->add(QUANTLIB_TEST_CASE(&OptionletStripperTest::testTermVolatilityStripping1));suite->add(QUANTLIB_TEST_CASE(&OptionletStripperTest::testFlatTermVolatilityStripping2));suite->add(QUANTLIB_TEST_CASE(&OptionletStripperTest::testTermVolatilityStripping2));suite->add(QUANTLIB_TEST_CASE(&OptionletStripperTest::testSwitchStrike));suite->add(QUANTLIB_TEST_CASE(&OptionletStripperTest::testTermVolatilityStrippingNormalVol));suite->add(QUANTLIB_TEST_CASE(&OptionletStripperTest::testTermVolatilityStrippingShiftedLogNormalVol));return suite;
}

该博文为原创文章,未经博主同意不得转。
本文章博客地址:https://cplusplus.blog.csdn.net/article/details/128364958

C++:实现量化OptionletStripper测试实例相关推荐

  1. C++:实现量化BlackDelta测试实例

    C++:实现量化BlackDelta测试实例 #include "blackdeltacalculator.hpp" #include "utilities.hpp&qu ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. leetcode--1:(python)Two Sum
  2. 王维嘉:神经网络的本质是在数据里面提取相关性
  3. GitLab 简易指引(二):GitLab Runner 安装与配置
  4. 公司虚拟化平台VMware vCenter Server无法连接故障排查解决
  5. oracle 半连接 效率,关于oracle中的半连接
  6. CSS之简单的双引号
  7. BeetleX.FastHttpApi之控制器调度设计
  8. js正则表达式详细教程
  9. javascript焦点图
  10. 欧拉函数之和(51nod 1239)
  11. vue php 架构目录,vuex 项目结构目录及一些简单配置介绍
  12. iOS开发 字体适配
  13. excel对比两顺序不同的表格
  14. layui数据表格合并列
  15. vscode超炫敲击特效嘎嘎帅!!!
  16. opencv获取灰度图像的像素值
  17. 软件为什么应该是自由的 Richard Stallman(理查德·斯多尔曼) 著
  18. 最简单直白的Linux入门介绍+VMware虚拟机搭建服务器
  19. mysql 获取倒数第二_MySQL查询倒数第二条记录实现方法
  20. 定制电竞比分网LOL英雄联盟数据API接口调用代码

热门文章

  1. python六角星_在Python中使用龟画出不同边长的六角星。
  2. 线性表的定义与特点及抽象数据类型定义
  3. java集成个推推送V2 uni-push1.0
  4. Python 官方中文教程(简)
  5. 热点舆情监测软件方法,舆情监测软件介绍,舆情软件监测意义?
  6. Cadence 绘制PCB添加泪滴与差分布线与铺铜简单介绍
  7. Office word 此文件正由另一应用程序或用户使用的解决方法
  8. 实例解析导购电商APP快速开启变现,收益提升184%
  9. DS18B20 1-WIRE ROM搜索算法详解
  10. 如何理解高内聚低耦合