C++:实现量化数字优惠券测试实例

C++:实现量化数字优惠券测试实例

#include "digitalcoupon.hpp"
#include "utilities.hpp"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include using namespace QuantLib;
using namespace boost::unit_test_framework;namespace digital_coupon_test {struct CommonVars {// global dataDate today, settlement;Real nominal;Calendar calendar;ext::shared_ptr<IborIndex> index;Natural fixingDays;RelinkableHandle<YieldTermStructure> termStructure;Real optionTolerance;Real blackTolerance;// cleanupSavedSettings backup;// setupCommonVars() {fixingDays = 2;nominal = 1000000.0;index = ext::shared_ptr<IborIndex>(new Euribor6M(termStructure));calendar = index->fixingCalendar();today = calendar.adjust(Settings::instance().evaluationDate());Settings::instance().evaluationDate() = today;settlement = calendar.advance(today,fixingDays,Days);termStructure.linkTo(flatRate(settlement,0.05,Actual365Fixed()));optionTolerance = 1.e-04;blackTolerance = 1e-10;}};}void DigitalCouponTest::testAssetOrNothing() {BOOST_TEST_MESSAGE("Testing European asset-or-nothing digital coupon...");using namespace digital_coupon_test;/*  Call Payoff = (aL+b)Heaviside(aL+b-X) =  a Max[L-X'] + (b+aX')Heaviside(L-X')Value Call = aF N(d1') + bN(d2')Put Payoff =  (aL+b)Heaviside(X-aL-b) = -a Max[X-L'] + (b+aX')Heaviside(X'-L)Value Put = aF N(-d1') + bN(-d2')where:d1' = ln(F/X')/stdDev + 0.5*stdDev;*/CommonVars vars;Volatility vols[] = { 0.05, 0.15, 0.30 };Rate strikes[] = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07 };Real gearings[] = { 1.0, 2.8 };Rate spreads[] = { 0.0, 0.005 };Real gap = 1e-7; /* low, in order to compare digital option valuewith black formula result */ext::shared_ptr<DigitalReplication>replication(new DigitalReplication(Replication::Central, gap));for (Real capletVol : vols) {RelinkableHandle<OptionletVolatilityStructure> vol;vol.linkTo(ext::shared_ptr<OptionletVolatilityStructure>(new ConstantOptionletVolatility(vars.today, vars.calendar, Following, capletVol, Actual360())));for (Real strike : strikes) {for (Size k = 9; k < 10; k++) {Date startDate = vars.calendar.advance(vars.settlement,(k+1)*Years);Date endDate = vars.calendar.advance(vars.settlement,(k+2)*Years);Rate nullstrike = Null<Rate>();Date paymentDate = endDate;for (Size h=0; h<LENGTH(gearings); h++) {Real gearing = gearings[h];Rate spread = spreads[h];ext::shared_ptr<FloatingRateCoupon> underlying(newIborCoupon(paymentDate, vars.nominal,startDate, endDate,vars.fixingDays, vars.index,gearing, spread));// Floating Rate Coupon - Call Digital optionDigitalCoupon digitalCappedCoupon(underlying,strike, Position::Short, false, nullstrike,nullstrike, Position::Short, false, nullstrike,replication);ext::shared_ptr<IborCouponPricer> pricer(newBlackIborCouponPricer(vol));digitalCappedCoupon.setPricer(pricer);// Check digital option price vs N(d1) priceTime accrualPeriod = underlying->accrualPeriod();Real discount = vars.termStructure->discount(endDate);Date exerciseDate = underlying->fixingDate();Rate forward = underlying->rate();Rate effFwd = (forward-spread)/gearing;Rate effStrike = (strike-spread)/gearing;Real stdDev = std::sqrt(vol->blackVariance(exerciseDate, effStrike));CumulativeNormalDistribution phi;Real d1 = std::log(effFwd/effStrike)/stdDev + 0.5*stdDev;Real d2 = d1 - stdDev;Real N_d1 = phi(d1);Real N_d2 = phi(d2);Real nd1Price = (gearing * effFwd * N_d1 + spread * N_d2)* vars.nominal * accrualPeriod * discount;Real optionPrice = digitalCappedCoupon.callOptionRate() *vars.nominal * accrualPeriod * discount;Real error = std::abs(nd1Price - optionPrice);if (error>vars.optionTolerance)BOOST_ERROR("\nDigital Call Option:" <<"\nVolatility = " << io::rate(capletVol) <<"\nStrike = " << io::rate(strike) <<"\nExercise = " << k+1 << " years" <<"\nOption price by replication = "  << optionPrice <<"\nOption price by Cox-Rubinstein formula = " << nd1Price <<"\nError " << error);// Check digital option price vs N(d1) price using Vanilla Option classif (spread==0.0) {ext::shared_ptr<Exercise>exercise(new EuropeanExercise(exerciseDate));Real discountAtFixing = vars.termStructure->discount(exerciseDate);ext::shared_ptr<SimpleQuote>fwd(new SimpleQuote(effFwd*discountAtFixing));ext::shared_ptr<SimpleQuote> qRate(new SimpleQuote(0.0));ext::shared_ptr<YieldTermStructure>qTS = flatRate(vars.today, qRate, Actual360());ext::shared_ptr<SimpleQuote> vol(new SimpleQuote(0.0));ext::shared_ptr<BlackVolTermStructure>volTS = flatVol(vars.today, capletVol, Actual360());ext::shared_ptr<StrikedTypePayoff>callPayoff(new AssetOrNothingPayoff(Option::Call,effStrike));ext::shared_ptr<BlackScholesMertonProcess> stochProcess(newBlackScholesMertonProcess(Handle<Quote>(fwd),Handle<YieldTermStructure>(qTS),Handle<YieldTermStructure>(vars.termStructure),Handle<BlackVolTermStructure>(volTS)));ext::shared_ptr<PricingEngine>engine(new AnalyticEuropeanEngine(stochProcess));VanillaOption callOpt(callPayoff, exercise);callOpt.setPricingEngine(engine);Real callVO = vars.nominal * gearing* accrualPeriod * callOpt.NPV()* discount / discountAtFixing* forward / effFwd;error = std::abs(nd1Price - callVO);if (error>vars.blackTolerance)BOOST_ERROR("\nDigital Call Option:" <<"\nVolatility = " << io::rate(capletVol) <<"\nStrike = " << io::rate(strike) <<"\nExercise = " << k+1 << " years" <<"\nOption price by Black asset-ot-nothing payoff = " << callVO <<"\nOption price by Cox-Rubinstein = " << nd1Price <<"\nError " << error );}// Floating Rate Coupon + Put Digital optionDigitalCoupon digitalFlooredCoupon(underlying,nullstrike, Position::Long, false, nullstrike,strike, Position::Long, false, nullstrike,replication);digitalFlooredCoupon.setPricer(pricer);// Check digital option price vs N(d1) priceN_d1 = phi(-d1);N_d2 = phi(-d2);nd1Price = (gearing * effFwd * N_d1 + spread * N_d2)* vars.nominal * accrualPeriod * discount;optionPrice = digitalFlooredCoupon.putOptionRate() *vars.nominal * accrualPeriod * discount;error = std::abs(nd1Price - optionPrice);if (error>vars.optionTolerance)BOOST_ERROR("\nDigital Put Option:" <<"\nVolatility = " << io::rate(capletVol) <<"\nStrike = " << io::rate(strike) <<"\nExercise = " << k+1 << " years" <<"\nOption price by replication = "  << optionPrice <<"\nOption price by Cox-Rubinstein = " << nd1Price <<"\nError " << error );// Check digital option price vs N(d1) price using Vanilla Option classif (spread==0.0) {ext::shared_ptr<Exercise>exercise(new EuropeanExercise(exerciseDate));Real discountAtFixing = vars.termStructure->discount(exerciseDate);ext::shared_ptr<SimpleQuote>fwd(new SimpleQuote(effFwd*discountAtFixing));ext::shared_ptr<SimpleQuote> qRate(new SimpleQuote(0.0));ext::shared_ptr<YieldTermStructure>qTS = flatRate(vars.today, qRate, Actual360());ext::shared_ptr<SimpleQuote> vol(new SimpleQuote(0.0));ext::shared_ptr<BlackVolTermStructure>volTS = flatVol(vars.today, capletVol, Actual360());ext::shared_ptr<BlackScholesMertonProcess> stochProcess(newBlackScholesMertonProcess(Handle<Quote>(fwd),Handle<YieldTermStructure>(qTS),Handle<YieldTermStructure>(vars.termStructure),Handle<BlackVolTermStructure>(volTS)));ext::shared_ptr<StrikedTypePayoff>putPayoff(new AssetOrNothingPayoff(Option::Put, effStrike));ext::shared_ptr<PricingEngine> engine(new AnalyticEuropeanEngine(stochProcess


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部