184 {
185
186 BOOST_TEST_MESSAGE("Test defaultable equity jump diffusion model calibration with Fokker-Planck bootstrap");
187
188 Real S0 = 100.0;
189 std::vector<Real> stepTimes = {1.0, 2.0, 3.0, 4.0, 5.0};
190
191 Handle<YieldTermStructure> rate(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.01, Actual365Fixed()));
192 Handle<YieldTermStructure> dividend(QuantLib::ext::make_shared<FlatForward>(0, NullCalendar(), 0.02, Actual365Fixed()));
193 Handle<BlackVolTermStructure> vol(QuantLib::ext::make_shared<BlackConstantVol>(0, NullCalendar(), 0.3, Actual365Fixed()));
194 Handle<DefaultProbabilityTermStructure> creditCurve(
195 QuantLib::ext::make_shared<FlatHazardRate>(0, NullCalendar(), 0.0050, Actual365Fixed()));
196
197 auto equity = QuantLib::ext::make_shared<EquityIndex2>("myEqIndex", NullCalendar(), EURCurrency(),
198 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(S0)), rate, dividend);
199
201 for (auto const& t : stepTimes) {
202 Real forward = equity->equitySpot()->value() * equity->equityDividendCurve()->discount(t) /
203 equity->equityForecastCurve()->discount(t);
205 }
206
207
208
209 std::vector<DefaultableEquityJumpDiffusionModelBuilder::BootstrapMode> modes = {
210 DefaultableEquityJumpDiffusionModelBuilder::BootstrapMode::Alternating,
211 DefaultableEquityJumpDiffusionModelBuilder::BootstrapMode::Simultaneously};
212 std::vector<Real> ps = {0.0, 0.5};
213 std::vector<Real> etas = {1.0, 0.9};
214
215 for (auto const& mode : modes) {
216 BOOST_TEST_MESSAGE(
217 "Bootstrap mode = " << (mode == DefaultableEquityJumpDiffusionModelBuilder::BootstrapMode::Alternating
218 ? "Alternating"
219 : "Simultaneously"));
220 for (auto const& p : ps) {
221 for (auto const& eta : etas) {
222
223 std::vector<Real> resultDefaultableBonds, resultEquityOptions;
224 auto modelBuilder = QuantLib::ext::make_shared<DefaultableEquityJumpDiffusionModelBuilder>(
225 stepTimes, equity, vol, creditCurve, p, eta, false, 24, 400, 1E-5, 1.5, Null<Real>(), mode, true);
226 auto model = *modelBuilder->model();
227
228 runMcSimulation(model, 100000, 121, 5 * 24, stepTimes,
strikes, resultDefaultableBonds,
229 resultEquityOptions);
230
231 Real tol = 0.2;
232 BOOST_TEST_MESSAGE(std::right << std::setw(5) << "p" << std::setw(5) << "eta" << std::setw(5) << "t"
233 << std::setw(16) << "h0" << std::setw(16) << "sigma" << std::setw(16)
234 << "bond mc" << std::setw(16) << "bond mkt" << std::setw(16)
235 << "equityCall mc" << std::setw(16) << "equityCall mkt" << std::setw(16)
236 << "bond err %" << std::setw(16) << "eqCall err %");
237 for (Size i = 0; i < stepTimes.size(); ++i) {
238 Real bondMarket = rate->discount(stepTimes[i]) * creditCurve->survivalProbability(stepTimes[i]);
239 Real eqOptionMarket = blackFormula(Option::Call,
strikes[i],
strikes[i],
240 std::sqrt(vol->blackVariance(stepTimes[i],
strikes[i])),
241 rate->discount(stepTimes[i]));
242 BOOST_TEST_MESSAGE(std::right
243 << std::setw(5) << p << std::setw(5) << eta << std::setw(5) << stepTimes[i]
244 << std::setw(16) << model->h0()[i] << std::setw(16) << model->sigma()[i]
245 << std::setw(16) << resultDefaultableBonds[i] << std::setw(16) << bondMarket
246 << std::setw(16) << resultEquityOptions[i] << std::setw(16) << eqOptionMarket
247 << std::setw(16) << 100.0 * (resultDefaultableBonds[i] - bondMarket) / bondMarket
248 << std::setw(16)
249 << 100.0 * (resultEquityOptions[i] - eqOptionMarket) / eqOptionMarket);
250 BOOST_CHECK_CLOSE(resultDefaultableBonds[i], bondMarket, tol);
251 BOOST_CHECK_CLOSE(resultEquityOptions[i], eqOptionMarket, tol);
252 }
253 BOOST_TEST_MESSAGE("done.");
254 }
255 }
256 }
257}