C++:实现量化年环比通胀上限和下限息票测试实例

#include "inflationcapflooredcoupon.hpp"
#include "inflationcapfloor.hpp"
#include "utilities.hpp"
#include <ql/cashflows/cashflows.hpp>
#include <ql/cashflows/cashflowvectors.hpp>
#include <ql/cashflows/inflationcouponpricer.hpp>
#include <ql/cashflows/yoyinflationcoupon.hpp>
#include <ql/indexes/inflation/euhicp.hpp>
#include <ql/indexes/inflation/ukrpi.hpp>
#include <ql/instruments/inflationcapfloor.hpp>
#include <ql/instruments/vanillaswap.hpp>
#include <ql/math/matrix.hpp>
#include <ql/models/marketmodels/correlations/expcorrelations.hpp>
#include <ql/models/marketmodels/models/flatvol.hpp>
#include <ql/pricingengines/blackformula.hpp>
#include <ql/pricingengines/inflation/inflationcapfloorengines.hpp>
#include <ql/pricingengines/swap/discountingswapengine.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/inflation/inflationhelpers.hpp>
#include <ql/termstructures/inflation/piecewiseyoyinflationcurve.hpp>
#include <ql/termstructures/volatility/inflation/yoyinflationoptionletvolatilitystructure.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/unitedkingdom.hpp>
#include <ql/time/daycounters/actual360.hpp>
#include <ql/time/daycounters/actualactual.hpp>
#include <ql/time/daycounters/thirty360.hpp>
#include <ql/time/schedule.hpp>
#include <ql/utilities/dataformatters.hpp>using namespace QuantLib;
using namespace boost::unit_test_framework;using std::fabs;namespace inflation_capfloored_coupon_test {struct Datum {Date date;Rate rate;};template <class T, class U, class I>std::vector<ext::shared_ptr<BootstrapHelper<T> > > makeHelpers(const std::vector<Datum>& iiData,const ext::shared_ptr<I> &ii, const Period &observationLag,const Calendar &calendar,const BusinessDayConvention &bdc,const DayCounter &dc,const Handle<YieldTermStructure>& discountCurve) {std::vector<ext::shared_ptr<BootstrapHelper<T> > > instruments;for (Datum datum : iiData) {Date maturity = datum.date;Handle<Quote> quote(ext::shared_ptr<Quote>(new SimpleQuote(datum.rate/100.0)));ext::shared_ptr<BootstrapHelper<T> > anInstrument(new U(quote, observationLag, maturity,calendar, bdc, dc, ii, discountCurve));instruments.push_back(anInstrument);}return instruments;}struct CommonVars {// common dataSize length;Date startDate;Real volatility;Frequency frequency;std::vector<Real> nominals;Calendar calendar;BusinessDayConvention convention;Natural fixingDays;Date evaluationDate;Natural settlementDays;Date settlement;Period observationLag;DayCounter dc;ext::shared_ptr<YYUKRPIr> iir;RelinkableHandle<YieldTermStructure> nominalTS;ext::shared_ptr<YoYInflationTermStructure> yoyTS;RelinkableHandle<YoYInflationTermStructure> hy;// cleanupSavedSettings backup;// setupCommonVars(): nominals(1,1000000) {// option variablesfrequency = Annual;// usual setupvolatility = 0.01;length = 7;calendar = UnitedKingdom();convention = ModifiedFollowing;Date today(13, August, 2007);evaluationDate = calendar.adjust(today);Settings::instance().evaluationDate() = evaluationDate;settlementDays = 0;fixingDays = 0;settlement = calendar.advance(today,settlementDays,Days);startDate = settlement;dc = Thirty360(Thirty360::BondBasis);// yoy index//      fixing dataDate from(1, January, 2005);Date to(13, August, 2007);Schedule rpiSchedule = MakeSchedule().from(from).to(to).withTenor(1*Months).withCalendar(UnitedKingdom()).withConvention(ModifiedFollowing);Real fixData[] = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0,192.2, 192.2, 192.6, 193.1, 193.3, 193.6,194.1, 193.4, 194.2, 195.0, 196.5, 197.7,198.5, 198.5, 199.2, 200.1, 200.4, 201.1,202.7, 201.6, 203.1, 204.4, 205.4, 206.2,207.3, -999.0, -999 };// link from yoy index to yoy TSbool interp = false;iir = ext::make_shared<YYUKRPIr>(interp, hy);for (Size i=0; i<rpiSchedule.size();i++) {iir->addFixing(rpiSchedule[i], fixData[i]);}ext::shared_ptr<YieldTermStructure> nominalFF(new FlatForward(evaluationDate, 0.05, ActualActual(ActualActual::ISDA)));nominalTS.linkTo(nominalFF);// now build the YoY inflation curvePeriod observationLag = Period(2,Months);std::vector<Datum> yyData = {{ Date(13, August, 2008), 2.95 },{ Date(13, August, 2009), 2.95 },{ Date(13, August, 2010), 2.93 },{ Date(15, August, 2011), 2.955 },{ Date(13, August, 2012), 2.945 },{ Date(13, August, 2013), 2.985 },{ Date(13, August, 2014), 3.01 },{ Date(13, August, 2015), 3.035 },{ Date(13, August, 2016), 3.055 },  // note that{ Date(13, August, 2017), 3.075 },  // some dates will be on{ Date(13, August, 2019), 3.105 },  // holidays but the payment{ Date(15, August, 2022), 3.135 },  // calendar will roll them{ Date(13, August, 2027), 3.155 },{ Date(13, August, 2032), 3.145 },{ Date(13, August, 2037), 3.145 }};// now build the helpers ...std::vector<ext::shared_ptr<BootstrapHelper<YoYInflationTermStructure> > > helpers =makeHelpers<YoYInflationTermStructure,YearOnYearInflationSwapHelper,YoYInflationIndex>(yyData, iir,observationLag,calendar, convention, dc,Handle<YieldTermStructure>(nominalTS));Rate baseYYRate = yyData[0].rate/100.0;ext::shared_ptr<PiecewiseYoYInflationCurve<Linear> > pYYTS(new PiecewiseYoYInflationCurve<Linear>(evaluationDate, calendar, dc, observationLag,iir->frequency(),iir->interpolated(), baseYYRate,helpers));pYYTS->recalculate();yoyTS = ext::dynamic_pointer_cast<YoYInflationTermStructure>(pYYTS);// make sure that the index has the latest yoy term structurehy.linkTo(pYYTS);}// utilitiesLeg makeYoYLeg(const Date& startDate,Integer length,const Rate gearing = 1.0,const Rate spread = 0.0) const {ext::shared_ptr<YoYInflationIndex> ii =ext::dynamic_pointer_cast<YoYInflationIndex>(iir);Date endDate = calendar.advance(startDate,length*Years,Unadjusted);Schedule schedule(startDate, endDate, Period(frequency), calendar,Unadjusted,Unadjusted,// ref periods & acc periodsDateGeneration::Forward, false);std::vector<Rate> gearingVector(length, gearing);std::vector<Spread> spreadVector(length, spread);Leg yoyLeg = yoyInflationLeg(schedule, calendar, ii, observationLag).withNotionals(nominals).withPaymentDayCounter(dc).withGearings(gearingVector).withSpreads(spreadVector).withPaymentAdjustment(convention);return yoyLeg;}Leg makeFixedLeg(const Date& startDate, Integer length) const {Date endDate = calendar.advance(startDate, length, Years,convention);Schedule schedule(startDate, endDate, Period(frequency), calendar,convention, convention,DateGeneration::Forward, false);std::vector<Rate> coupons(length, 0.0);return FixedRateLeg(schedule).withNotionals(nominals).withCouponRates(coupons, dc);}Leg makeYoYCapFlooredLeg(Size which,const Date& startDate,Integer length,const std::vector<Rate>& caps,const std::vector<Rate>& floors,Volatility volatility,const Rate gearing = 1.0,const Rate spread = 0.0) const {Handle<YoYOptionletVolatilitySurface>vol(ext::make_shared<ConstantYoYOptionletVolatility>(volatility,settlementDays,calendar,convention,dc,observationLag,frequency,iir->interpolated()));ext::shared_ptr<YoYInflationCouponPricer> pricer;switch (which) {case 0:pricer = ext::shared_ptr<YoYInflationCouponPricer>(new BlackYoYInflationCouponPricer(vol, nominalTS));break;case 1:pricer = ext::shared_ptr<YoYInflationCouponPricer>(new UnitDisplacedBlackYoYInflationCouponPricer(vol, nominalTS));break;case 2:pricer = ext::shared_ptr<YoYInflationCouponPricer>(new BachelierYoYInflationCouponPricer(vol, nominalTS));break;default:BOOST_FAIL("unknown coupon pricer request: which = "<<which<<"should be 0=Black,1=DD,2=Bachelier");break;}std::vector<Rate> gearingVector(length, gearing);std::vector<Spread> spreadVector(length, spread);ext::shared_ptr<YoYInflationIndex> ii =ext::dynamic_pointer_cast<YoYInflationIndex>(iir);Date endDate = calendar.advance(startDate,length*Years,Unadjusted);Schedule schedule(startDate, endDate, Period(frequency), calendar,Unadjusted,Unadjusted,// ref periods & acc periodsDateGeneration::Forward, false);Leg yoyLeg =  yoyInflationLeg(schedule, calendar, ii, observationLag).withNotionals(nominals).withPaymentDayCounter(dc).withPaymentAdjustment(convention).withGearings(gearingVector).withSpreads(spreadVector).withCaps(caps).withFloors(floors);setCouponPricer(yoyLeg, pricer);return yoyLeg;}ext::shared_ptr<PricingEngine> makeEngine(Volatility volatility, Size which) const {ext::shared_ptr<YoYInflationIndex>yyii = ext::dynamic_pointer_cast<YoYInflationIndex>(iir);Handle<YoYOptionletVolatilitySurface>vol(ext::make_shared<ConstantYoYOptionletVolatility>(volatility,settlementDays,calendar,convention,dc,observationLag,frequency,iir->interpolated()));switch (which) {case 0:return ext::shared_ptr<PricingEngine>(new YoYInflationBlackCapFloorEngine(iir, vol, nominalTS));break;case 1:return ext::shared_ptr<PricingEngine>(new YoYInflationUnitDisplacedBlackCapFloorEngine(iir, vol, nominalTS));break;case 2:return ext::shared_ptr<PricingEngine>(new YoYInflationBachelierCapFloorEngine(iir, vol, nominalTS));break;default:BOOST_FAIL("unknown engine request: which = "<<which<<"should be 0=Black,1=DD,2=Bachelier");break;}// make compiler happyQL_FAIL("never get here - no engine resolution");}ext::shared_ptr<YoYInflationCapFloor> makeYoYCapFloor(YoYInflationCapFloor::Type type,const Leg& leg,Rate strike,Volatility volatility,Size which) const {ext::shared_ptr<YoYInflationCapFloor> result;switch (type) {case YoYInflationCapFloor::Cap:result = ext::shared_ptr<YoYInflationCapFloor>(new YoYInflationCap(leg, std::vector<Rate>(1, strike)));break;case YoYInflationCapFloor::Floor:result = ext::shared_ptr<YoYInflationCapFloor>(new YoYInflationFloor(leg, std::vector<Rate>(1, strike)));break;default:QL_FAIL("unknown YoYInflation cap/floor type");}result->setPricingEngine(makeEngine(volatility, which));return result;}};}void InflationCapFlooredCouponTest::testDecomposition() {BOOST_TEST_MESSAGE("Testing collared coupon against its decomposition...");using namespace inflation_capfloored_coupon_test;CommonVars vars;Real tolerance = 1e-10;Real npvVanilla,npvCappedLeg,npvFlooredLeg,npvCollaredLeg,npvCap,npvFloor,npvCollar;Real error;Rate floorstrike = 0.05;Rate capstrike = 0.10;std::vector<Rate> caps(vars.length,capstrike);std::vector<Rate> caps0 = std::vector<Rate>();std::vector<Rate> floors(vars.length,floorstrike);std::vector<Rate> floors0 = std::vector<Rate>();Rate gearing_p = Rate(0.5);auto spread_p = Spread(0.002);Rate gearing_n = Rate(-1.5);auto spread_n = Spread(0.12);// fixed leg with zero rateLeg fixedLeg  =vars.makeFixedLeg(vars.startDate,vars.length);// floating leg with gearing=1 and spread=0Leg floatLeg  =vars.makeYoYLeg(vars.startDate,vars.length);// floating leg with positive gearing (gearing_p) and spread<>0Leg floatLeg_p =vars.makeYoYLeg(vars.startDate,vars.length,gearing_p,spread_p);// floating leg with negative gearing (gearing_n) and spread<>0Leg floatLeg_n =vars.makeYoYLeg(vars.startDate,vars.length,gearing_n,spread_n);// Swap with null fixed leg and floating leg with gearing=1 and spread=0Swap vanillaLeg(fixedLeg,floatLeg);// Swap with null fixed leg and floating leg with positive gearing and spread<>0Swap vanillaLeg_p(fixedLeg,floatLeg_p);// Swap with null fixed leg and floating leg with negative gearing and spread<>0Swap vanillaLeg_n(fixedLeg,floatLeg_n);ext::shared_ptr<PricingEngine> engine(new DiscountingSwapEngine(vars.nominalTS));vanillaLeg.setPricingEngine(engine);    // here use the autoset featurevanillaLeg_p.setPricingEngine(engine);vanillaLeg_n.setPricingEngine(engine);// CAPPED coupon - Decomposition of payoff// Payoff = Nom * Min(rate,strike) * accrualperiod =// = Nom * [rate + Min(0,strike-rate)] * accrualperiod =// = Nom * rate * accrualperiod - Nom * Max(rate-strike,0) * accrualperiod =// = VanillaFloatingLeg - Call//Size whichPricer = 0;// Case gearing = 1 and spread = 0Leg cappedLeg =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps,floors0,vars.volatility);Swap capLeg(fixedLeg,cappedLeg);capLeg.setPricingEngine(engine);YoYInflationCap cap(floatLeg, std::vector<Rate>(1, capstrike));cap.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvVanilla = vanillaLeg.NPV();npvCappedLeg = capLeg.NPV();npvCap = cap.NPV();error = std::abs(npvCappedLeg - (npvVanilla-npvCap));if (error>tolerance) {BOOST_ERROR("\nYoY Capped Leg: gearing=1, spread=0%, strike=" << capstrike*100 <<"%\n" <<"  Capped Floating Leg NPV: " << npvCappedLeg << "\n" <<"  Floating Leg NPV - Cap NPV: " << npvVanilla - npvCap << "\n" <<"  Diff: " << error );}// gearing = 1 and spread = 0// FLOORED coupon - Decomposition of payoff// Payoff = Nom * Max(rate,strike) * accrualperiod =// = Nom * [rate + Max(0,strike-rate)] * accrualperiod =// = Nom * rate * accrualperiod + Nom * Max(strike-rate,0) * accrualperiod =// = VanillaFloatingLeg + Put//Leg flooredLeg =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps0,floors,vars.volatility);Swap floorLeg(fixedLeg,flooredLeg);floorLeg.setPricingEngine(engine);YoYInflationFloor floor(floatLeg, std::vector<Rate>(1, floorstrike));floor.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvFlooredLeg = floorLeg.NPV();npvFloor = floor.NPV();error = std::abs(npvFlooredLeg-(npvVanilla + npvFloor));if (error>tolerance) {BOOST_ERROR("YoY Floored Leg: gearing=1, spread=0%, strike=" << floorstrike *100 <<"%\n" <<"  Floored Floating Leg NPV: " << npvFlooredLeg << "\n" <<"  Floating Leg NPV + Floor NPV: " << npvVanilla + npvFloor << "\n" <<"  Diff: " << error );}// gearing = 1 and spread = 0// COLLARED coupon - Decomposition of payoff// Payoff = Nom * Min(strikem,Max(rate,strikeM)) * accrualperiod =// = VanillaFloatingLeg - Collar//Leg collaredLeg =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps,floors,vars.volatility);Swap collarLeg(fixedLeg,collaredLeg);collarLeg.setPricingEngine(engine);YoYInflationCollar collar(floatLeg,std::vector<Rate>(1, capstrike),std::vector<Rate>(1, floorstrike));collar.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvCollaredLeg = collarLeg.NPV();npvCollar = collar.NPV();error = std::abs(npvCollaredLeg -(npvVanilla - npvCollar));if (error>tolerance) {BOOST_ERROR("\nYoY Collared Leg: gearing=1, spread=0%, strike=" <<floorstrike*100 << "% and " << capstrike*100 << "%\n" <<"  Collared Floating Leg NPV: " << npvCollaredLeg << "\n" <<"  Floating Leg NPV - Collar NPV: " << npvVanilla - npvCollar << "\n" <<"  Diff: " << error );}// gearing = a and spread = b// CAPPED coupon - Decomposition of payoff// Payoff// = Nom * Min(a*rate+b,strike) * accrualperiod =// = Nom * [a*rate+b + Min(0,strike-a*rate-b)] * accrualperiod =// = Nom * a*rate+b * accrualperiod + Nom * Min(strike-b-a*rate,0) * accrualperiod// --> If a>0 (assuming positive effective strike):// Payoff = VanillaFloatingLeg - Call(a*rate+b,strike)// --> If a<0 (assuming positive effective strike):// Payoff = VanillaFloatingLeg + Nom * Min(strike-b+|a|*rate+,0) * accrualperiod =// = VanillaFloatingLeg + Put(|a|*rate+b,strike)//// Positive gearingLeg cappedLeg_p =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps,floors0,vars.volatility,gearing_p,spread_p);Swap capLeg_p(fixedLeg,cappedLeg_p);capLeg_p.setPricingEngine(engine);YoYInflationCap cap_p(floatLeg_p,std::vector<Rate>(1,capstrike));cap_p.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvVanilla = vanillaLeg_p.NPV();npvCappedLeg = capLeg_p.NPV();npvCap = cap_p.NPV();error = std::abs(npvCappedLeg - (npvVanilla-npvCap));if (error>tolerance) {BOOST_ERROR("\nYoY Capped Leg: gearing=" << gearing_p << ", " <<"spread= " << spread_p *100 <<"%, strike=" << capstrike*100  << "%, " <<"effective strike= " << (capstrike-spread_p)/gearing_p*100 <<"%\n" <<"  Capped Floating Leg NPV: " << npvCappedLeg << "\n" <<"  Vanilla Leg NPV: " << npvVanilla << "\n" <<"  Cap NPV: " << npvCap << "\n" <<"  Floating Leg NPV - Cap NPV: " << npvVanilla - npvCap << "\n" <<"  Diff: " << error );}// Negative gearingLeg cappedLeg_n =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps,floors0,vars.volatility,gearing_n,spread_n);Swap capLeg_n(fixedLeg,cappedLeg_n);capLeg_n.setPricingEngine(engine);YoYInflationFloor floor_n(floatLeg,std::vector<Rate>(1,(capstrike-spread_n)/gearing_n));floor_n.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvVanilla = vanillaLeg_n.NPV();npvCappedLeg = capLeg_n.NPV();npvFloor = floor_n.NPV();error = std::abs(npvCappedLeg - (npvVanilla+ gearing_n*npvFloor));if (error>tolerance) {BOOST_ERROR("\nYoY Capped Leg: gearing=" << gearing_n << ", " <<"spread= " << spread_n *100 <<"%, strike=" << capstrike*100  << "%, " <<"effective strike= " << (capstrike-spread_n)/gearing_n*100 <<"%\n" <<"  Capped Floating Leg NPV: " << npvCappedLeg << "\n" <<"  npv Vanilla: " << npvVanilla << "\n" <<"  npvFloor: " << npvFloor << "\n" <<"  Floating Leg NPV - Cap NPV: " << npvVanilla + gearing_n*npvFloor << "\n" <<"  Diff: " << error );}// gearing = a and spread = b// FLOORED coupon - Decomposition of payoff// Payoff// = Nom * Max(a*rate+b,strike) * accrualperiod =// = Nom * [a*rate+b + Max(0,strike-a*rate-b)] * accrualperiod =// = Nom * a*rate+b * accrualperiod + Nom * Max(strike-b-a*rate,0) * accrualperiod// --> If a>0 (assuming positive effective strike):// Payoff = VanillaFloatingLeg + Put(a*rate+b,strike)// --> If a<0 (assuming positive effective strike):// Payoff = VanillaFloatingLeg + Nom * Max(strike-b+|a|*rate+,0) * accrualperiod =// = VanillaFloatingLeg - Call(|a|*rate+b,strike)//// Positive gearingLeg flooredLeg_p1 =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps0,floors,vars.volatility,gearing_p,spread_p);Swap floorLeg_p1(fixedLeg,flooredLeg_p1);floorLeg_p1.setPricingEngine(engine);YoYInflationFloor floor_p1(floatLeg_p,std::vector<Rate>(1,floorstrike));floor_p1.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvVanilla = vanillaLeg_p.NPV();npvFlooredLeg = floorLeg_p1.NPV();npvFloor = floor_p1.NPV();error = std::abs(npvFlooredLeg - (npvVanilla+npvFloor));if (error>tolerance) {BOOST_ERROR("\nYoY Floored Leg: gearing=" << gearing_p << ", "<< "spread= " << spread_p *100<< "%, strike=" << floorstrike *100 << "%, "<< "effective strike= " << (floorstrike-spread_p)/gearing_p*100<< "%\n" <<"  Floored Floating Leg NPV: "    << npvFlooredLeg<< "\n" <<"  Floating Leg NPV + Floor NPV: " << npvVanilla + npvFloor<< "\n" <<"  Diff: " << error );}// Negative gearingLeg flooredLeg_n =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps0,floors,vars.volatility,gearing_n,spread_n);Swap floorLeg_n(fixedLeg,flooredLeg_n);floorLeg_n.setPricingEngine(engine);YoYInflationCap cap_n(floatLeg,std::vector<Rate>(1,(floorstrike-spread_n)/gearing_n));cap_n.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvVanilla = vanillaLeg_n.NPV();npvFlooredLeg = floorLeg_n.NPV();npvCap = cap_n.NPV();error = std::abs(npvFlooredLeg - (npvVanilla - gearing_n*npvCap));if (error>tolerance) {BOOST_ERROR("\nYoY Capped Leg: gearing=" << gearing_n << ", " <<"spread= " << spread_n *100 <<"%, strike=" << floorstrike*100  << "%, " <<"effective strike= " << (floorstrike-spread_n)/gearing_n*100 <<"%\n" <<"  Capped Floating Leg NPV: " << npvFlooredLeg << "\n" <<"  Floating Leg NPV - Cap NPV: " << npvVanilla - gearing_n*npvCap << "\n" <<"  Diff: " << error );}// gearing = a and spread = b// COLLARED coupon - Decomposition of payoff// Payoff = Nom * Min(caprate,Max(a*rate+b,floorrate)) * accrualperiod// --> If a>0 (assuming positive effective strike):// Payoff = VanillaFloatingLeg - Collar(a*rate+b, floorrate, caprate)// --> If a<0 (assuming positive effective strike):// Payoff = VanillaFloatingLeg + Collar(|a|*rate+b, caprate, floorrate)//// Positive gearingLeg collaredLeg_p =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps,floors,vars.volatility,gearing_p,spread_p);Swap collarLeg_p1(fixedLeg,collaredLeg_p);collarLeg_p1.setPricingEngine(engine);YoYInflationCollar collar_p(floatLeg_p,std::vector<Rate>(1,capstrike),std::vector<Rate>(1,floorstrike));collar_p.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvVanilla = vanillaLeg_p.NPV();npvCollaredLeg = collarLeg_p1.NPV();npvCollar = collar_p.NPV();error = std::abs(npvCollaredLeg - (npvVanilla - npvCollar));if (error>tolerance) {BOOST_ERROR("\nYoY Collared Leg: gearing=" << gearing_p << ", "<< "spread= " << spread_p*100 << "%, strike="<< floorstrike*100 << "% and " << capstrike*100<< "%, "<< "effective strike=" << (floorstrike-spread_p)/gearing_p*100<<  "% and " << (capstrike-spread_p)/gearing_p*100<< "%\n" <<"  Collared Floating Leg NPV: "    << npvCollaredLeg<< "\n" <<"  Floating Leg NPV - Collar NPV: " << npvVanilla - npvCollar<< "\n" <<"  Diff: " << error );}// Negative gearingLeg collaredLeg_n =vars.makeYoYCapFlooredLeg(whichPricer,vars.startDate,vars.length,caps,floors,vars.volatility,gearing_n,spread_n);Swap collarLeg_n1(fixedLeg,collaredLeg_n);collarLeg_n1.setPricingEngine(engine);YoYInflationCollar collar_n(floatLeg,std::vector<Rate>(1,(floorstrike-spread_n)/gearing_n),std::vector<Rate>(1,(capstrike-spread_n)/gearing_n));collar_n.setPricingEngine(vars.makeEngine(vars.volatility,whichPricer));npvVanilla = vanillaLeg_n.NPV();npvCollaredLeg = collarLeg_n1.NPV();npvCollar = collar_n.NPV();error = std::abs(npvCollaredLeg - (npvVanilla - gearing_n*npvCollar));if (error>tolerance) {BOOST_ERROR("\nYoY Collared Leg: gearing=" << gearing_n << ", "<< "spread= " << spread_n*100 << "%, strike="<< floorstrike*100 << "% and " << capstrike*100<< "%, "<< "effective strike=" << (floorstrike-spread_n)/gearing_n*100<<  "% and " << (capstrike-spread_n)/gearing_n*100<< "%\n" <<"  Collared Floating Leg NPV: "    << npvCollaredLeg<< "\n" <<"  Floating Leg NPV - Collar NPV: " << npvVanilla - gearing_n*npvCollar<< "\n" <<"  Diff: " << error );}// remove circular referncevars.hy.linkTo(ext::shared_ptr<YoYInflationTermStructure>());
}void InflationCapFlooredCouponTest::testInstrumentEquality() {BOOST_TEST_MESSAGE("Testing inflation capped/floored coupon against"" inflation capfloor instrument...");using namespace inflation_capfloored_coupon_test;CommonVars vars;Integer lengths[] = { 1, 2, 3, 5, 7, 10, 15, 20 };// vol is low ...Rate strikes[] = { 0.01, 0.025, 0.029, 0.03, 0.031, 0.035, 0.07 };// yoy inflation vol is generally very lowVolatility vols[] = { 0.001, 0.005, 0.010, 0.015, 0.020 };// this is model independent// capped coupon = fwd - cap, and fwd = swap(0)// floored coupon = fwd + floorfor (Size whichPricer = 0; whichPricer < 3; whichPricer++) {for (int& length : lengths) {for (Real& strike : strikes) {for (Real vol : vols) {Leg leg = vars.makeYoYLeg(vars.evaluationDate, length);ext::shared_ptr<Instrument> cap = vars.makeYoYCapFloor(YoYInflationCapFloor::Cap, leg, strike, vol, whichPricer);ext::shared_ptr<Instrument> floor = vars.makeYoYCapFloor(YoYInflationCapFloor::Floor, leg, strike, vol, whichPricer);Date from = vars.nominalTS->referenceDate();Date to = from + length * Years;Schedule yoySchedule = MakeSchedule().from(from).to(to).withTenor(1*Years).withCalendar(UnitedKingdom()).withConvention(Unadjusted).backwards();YearOnYearInflationSwap swap(Swap::Payer,1000000.0,yoySchedule,//fixed schedule, but same as yoy0.0,//strikes[j],vars.dc,yoySchedule,vars.iir,vars.observationLag,0.0,        //spread on indexvars.dc,UnitedKingdom());Handle<YieldTermStructure> hTS(vars.nominalTS);ext::shared_ptr<PricingEngine> sppe(new DiscountingSwapEngine(hTS));swap.setPricingEngine(sppe);Leg leg2 = vars.makeYoYCapFlooredLeg(whichPricer, from, length,std::vector<Rate>(length, strike), // capstd::vector<Rate>(),               // floorvol,1.0,  // gearing0.0); // spreadLeg leg3 = vars.makeYoYCapFlooredLeg(whichPricer, from, length,std::vector<Rate>(),               // capstd::vector<Rate>(length, strike), // floorvol,1.0,  // gearing0.0); // spread// N.B. nominals are 10e6Real capped = CashFlows::npv(leg2,(**vars.nominalTS),false);if ( fabs(capped - (swap.NPV() - cap->NPV())) > 1.0e-6) {BOOST_FAIL("capped coupon != swap(0) - cap:\n"<< "    length:      " << length << " years\n"<< "    volatility:  " << io::volatility(vol) << "\n"<< "    strike:      " << io::rate(strike) << "\n"<< "    cap value:   " << cap->NPV() << "\n"<< "    swap value:  " << swap.NPV() << "\n"<< "   capped coupon " << capped);}// N.B. nominals are 10e6Real floored = CashFlows::npv(leg3,(**vars.nominalTS),false);if ( fabs(floored - (swap.NPV() + floor->NPV())) > 1.0e-6) {BOOST_FAIL("floored coupon != swap(0) + floor :\n"<< "    length:      " << length << " years\n"<< "    volatility:  " << io::volatility(vol) << "\n"<< "    strike:      " << io::rate(strike) << "\n"<< "    floor value: " << floor->NPV() << "\n"<< "    swap value:  " << swap.NPV() << "\n"<< "  floored coupon " << floored);}}}}}// remove circular referncevars.hy.linkTo(ext::shared_ptr<YoYInflationTermStructure>());
}test_suite* InflationCapFlooredCouponTest::suite() {auto* suite = BOOST_TEST_SUITE("YoY inflation capped and floored coupon tests");suite->add(QUANTLIB_TEST_CASE(&InflationCapFlooredCouponTest::testDecomposition));suite->add(QUANTLIB_TEST_CASE(&InflationCapFlooredCouponTest::testInstrumentEquality));return suite;
}

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

C++:实现量化年环比通胀上限和下限息票测试实例相关推荐

  1. WInform中实现设置ZedGraph中曲线的X轴与Y轴的上限与下限

    场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  2. boost::mpi模块围绕环传递数据的通信器的测试

    boost::mpi模块围绕环传递数据的通信器的测试 实现功能 C++实现代码 实现功能 boost::mpi模块围绕环传递数据的通信器的测试 C++实现代码 #include <boost/m ...

  3. 期权价格的上限和下限

    期权按照买方权利性质分为:看涨期权和看跌期权 1.首先,看涨期权的上限和下限 看涨期权价格上限为其标的资产价格. 看涨期权是给予买方一个在未来买入标的资产的权利,如果该权利的价格高于标的资产的价格,那 ...

  4. java中泛型上限,下限应用

    v 一.程序中无形之中用到的泛型 import java.util.*; class Person implements Comparable<Person>{String name;in ...

  5. java 泛型的上限与下限、泛型通配符、泛型上下限

    java 泛型的上限与下限 设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类: 声明对象:类名<? extends 类> 对象名 定义类:类名<泛型标签 ...

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

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

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

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

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

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

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

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

最新文章

  1. Python中*args和**kwargs的区别
  2. python知道答案_Python程序设计基础知道章节测试答案
  3. 跟alex学python_跟着Alex学习python
  4. 特殊时期,对数据中心运营有哪些影响?
  5. python爬虫beautifulsoup_python爬虫beautifulsoup解析html方法
  6. pycharm在创建py文件时如何自动注释
  7. 计算机专业简历中技能特长怎么写,简历上特长技能应该怎么填写
  8. jQuery mobile button 禁用和启用
  9. 管理SourceForge项目的方法
  10. 世界上最有能量的语言,一定要经常说!
  11. 树莓派设置静态ip地址
  12. C语言 哲学家就餐问题
  13. 有三个桶,两个大的可装8斤的水,一个小的可装3斤的水,现在有16斤水装满了两大桶就是8斤的桶,小桶空着,如何把这16斤水分给4个人,每人4斤。没有其他任何工具,4人自备容器,分出去的水不可再要回来。
  14. 七公江湖烤翅防骗子—常见网络骗子骗术防御要点
  15. C++,OpenCV 中template(模板)的简单理解
  16. 单基因gsea_零代码5分+的单基因综合分析
  17. toLocaleString也太好用了吧!(超方便转千分位,中文数字等)
  18. PHP教程:PHP开发快速入门_v20200418
  19. 暗黑2符文之语大全_暗黑破坏神2符文之语一览,附符文镶嵌顺序和底材
  20. 电动车充电软件测试,电动车充电分为哪几个过程

热门文章

  1. vnc viewer是什么,vnc viewer是什么,怎么用
  2. OPENCV图像处理基础(五)鼠标事件画个框
  3. 一、Conflux 网页钱包创建
  4. java 3d 配置_Java 3D简介及安装运行
  5. 如何定义公众号做的好
  6. JS中用一个button按钮实现开关灯效果
  7. 走进“开源SDR实验室” 一起玩转GNU Radio:滤波器
  8. 电子接插件选型,你选对了吗?
  9. 如何转发微信5.0的语音
  10. 选择1KG轻簿的笔记本