23#include <ql/cashflows/coupon.hpp>
24#include <ql/currencies/europe.hpp>
25#include <ql/instruments/bonds/fixedratebond.hpp>
26#include <ql/quotes/simplequote.hpp>
27#include <ql/termstructures/credit/flathazardrate.hpp>
28#include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp>
29#include <ql/termstructures/yield/flatforward.hpp>
30#include <ql/time/calendars/nullcalendar.hpp>
31#include <ql/time/calendars/target.hpp>
32#include <ql/time/daycounters/thirty360.hpp>
36#include <boost/test/unit_test.hpp>
46BOOST_AUTO_TEST_SUITE(FdConvertibleBondEngine)
50 BOOST_TEST_MESSAGE(
"Test vanilla bond pricing in fd defaultable equity jump diffusion convertible engine...");
52 Date today(9, February, 2021);
53 Settings::instance().evaluationDate() = today;
56 Handle<YieldTermStructure> rate(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.01, Actual365Fixed()));
57 Handle<YieldTermStructure> dividend(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.02, Actual365Fixed()));
58 Handle<BlackVolTermStructure> vol(QuantLib::ext::make_shared<BlackConstantVol>(0, NullCalendar(), 0.3, Actual365Fixed()));
60 Handle<YieldTermStructure> bondBenchmark(
61 QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.03, Actual365Fixed()));
62 Handle<DefaultProbabilityTermStructure> creditCurve(
63 QuantLib::ext::make_shared<FlatHazardRate>(0, NullCalendar(), 0.0050, Actual365Fixed()));
64 Handle<Quote> bondRecoveryRate(QuantLib::ext::make_shared<SimpleQuote>(0.25));
65 Handle<Quote> securitySpread(QuantLib::ext::make_shared<SimpleQuote>(0.00));
67 auto equity = QuantLib::ext::make_shared<EquityIndex2>(
"myEqIndex", NullCalendar(), EURCurrency(),
68 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(S0)), rate, dividend);
70 auto bond = QuantLib::ext::make_shared<FixedRateBond>(0, TARGET(), 100000.0, today, today + 5 * Years, 1 * Years,
71 std::vector<Real>(1, 0.05), Thirty360(Thirty360::BondBasis));
75 auto vanillaEngine = QuantLib::ext::make_shared<DiscountingRiskyBondEngine>(bondBenchmark, creditCurve, bondRecoveryRate,
76 securitySpread, 1 * Years);
77 bond->setPricingEngine(vanillaEngine);
78 Real vanillaEngineNpv = bond->NPV();
84 std::vector<Real> stepTimes = {1.0, 2.0, 3.0, 4.0, 5.0};
86 auto modelBuilder = QuantLib::ext::make_shared<DefaultableEquityJumpDiffusionModelBuilder>(
87 stepTimes, equity, vol, creditCurve, p, eta,
false, 24, 400, 1E-5, 1.5, Null<Real>(),
88 DefaultableEquityJumpDiffusionModelBuilder::BootstrapMode::Simultaneously,
true);
89 auto model = modelBuilder->model();
91 auto cpns = bond->cashflows();
93 std::remove_if(cpns.begin(), cpns.end(),
94 [](QuantLib::ext::shared_ptr<CashFlow> c) { return QuantLib::ext::dynamic_pointer_cast<Coupon>(c) == nullptr; }),
98 auto convertibleBond =
99 QuantLib::ext::make_shared<ConvertibleBond2>(bond->settlementDays(), bond->calendar(), bond->issueDate(), cpns);
100 auto convertibleEngine = QuantLib::ext::make_shared<FdDefaultableEquityJumpDiffusionConvertibleBondEngine>(
101 model, bondBenchmark, securitySpread, Handle<DefaultProbabilityTermStructure>(), bondRecoveryRate,
102 Handle<FxIndex>(),
false, 24, 100, 1E-4, 1.5);
103 convertibleBond->setPricingEngine(convertibleEngine);
104 Real convertibleEngineNpv = convertibleBond->NPV();
106 BOOST_TEST_MESSAGE(
"Vanilla Engine Bond NPV = "
107 << std::setprecision(10) << vanillaEngineNpv
108 <<
", Convertible Engine Bond NPV = " << convertibleEngineNpv
109 <<
", error=" << (convertibleEngineNpv - vanillaEngineNpv) / vanillaEngineNpv * 100.0 <<
"%");
111 BOOST_CHECK_CLOSE(vanillaEngineNpv, convertibleEngineNpv, 1E-3);
114BOOST_AUTO_TEST_SUITE_END()
116BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(test_vanilla_bond)
Fixture that can be used at top level.