19#include <boost/bind/bind.hpp>
23#include <ql/cashflows/fixedratecoupon.hpp>
24#include <ql/math/solvers1d/brent.hpp>
29 const Size index,
const Size ccy,
const Real recoveryRate,
30 const Handle<YieldTermStructure>& termStructure)
31 :
QuantExt::
CdsOption::engine(), model_(model), index_(index), ccy_(ccy), recoveryRate_(recoveryRate),
32 termStructure_(termStructure) {
34 if (!termStructure.empty())
35 registerWith(termStructure);
40 QL_REQUIRE(
arguments_.swap->protectionPaymentTime() == CreditDefaultSwap::ProtectionPaymentTime::atDefault,
41 "AnalyticLgmCdsOptionEngine: protection payment time must be atDefault");
43 Real w = (
arguments_.side == Protection::Buyer) ? -1.0 : 1.0;
44 Rate swapSpread =
arguments_.swap->runningSpread();
45 const Handle<YieldTermStructure>& yts =
48 Real riskyAnnuity = std::fabs(
arguments_.swap->couponLegNPV() / swapSpread);
49 results_.riskyAnnuity = riskyAnnuity;
53 swapSpread -= w *
arguments_.swap->upfrontNPV() / riskyAnnuity;
56 t_ = Array(n + 1, 0.0);
57 G_ = Array(n + 1, 0.0);
58 Array C(n, 0.0), D(n, 0.0);
60 if (
arguments_.exercise->date(0) <= yts->referenceDate()) {
66 t_[0] = std::max(
tex_, yts->timeFromReference(
arguments_.swap->protectionStartDate()));
68 Real accrualSettlementAmount = 0.0;
69 for (Size i = 0; i < n; ++i) {
70 QuantLib::ext::shared_ptr<FixedRateCoupon> cpn =
71 QuantLib::ext::dynamic_pointer_cast<FixedRateCoupon>(
arguments_.swap->coupons()[i]);
72 QL_REQUIRE(cpn != NULL,
"AnalyticLgmCdsOptionEngine: expected fixed rate coupon");
73 t_[i + 1] = yts->timeFromReference(cpn->date());
74 Real mid = (
t_[i] +
t_[i + 1]) / 2.0;
76 Real accStartTime = i == 0 ? yts->timeFromReference(cpn->accrualStartDate()) :
t_[i];
78 accrualSettlementAmount = mid > accStartTime ? swapSpread * cpn->accrualPeriod() * (mid - accStartTime) /
79 (
t_[i + 1] - accStartTime)
82 C[i] = ((1.0 -
recoveryRate_) - accrualSettlementAmount) * yts->discount(mid) / yts->discount(
tex_);
83 D[i] = swapSpread * cpn->accrualPeriod() * yts->discount(
t_[i + 1]) / yts->discount(
tex_);
86 for (Size i = 0; i < n - 1; ++i) {
87 G_[i + 1] = C[i] + D[i] - C[i + 1];
89 G_[n] = C[n - 1] + D[n - 1];
92 Real frontEndProtection = 0.0;
103 }
catch (
const std::exception& e) {
104 QL_FAIL(
"AnalyticLgmCdsOptionEngine, failed to compute lambdaStar, " << e.what());
108 for (Size i = 1; i <
G_.size(); ++i) {
111 sum +=
G_[i] *
Ei(w, strike, i) * yts->discount(
tex_);
119 Real pS =
model_->crlgm1f(
index_)->termStructure()->survivalProbability(
t_[0]);
120 Real pT =
model_->crlgm1f(
index_)->termStructure()->survivalProbability(
t_[i]);
125 Real dp = (std::log(pT / (strike * pS)) / sigma + 0.5 * sigma);
126 Real dm = dp - sigma;
127 CumulativeNormalDistribution N;
128 return w * (pT * N(w * dp) - pS * strike * N(w * dm));
133 for (Size i = 0; i <
G_.size(); ++i) {
analytic lgm cds option engine
const Instrument::results * results_
void calculate() const override
Real Ei(const Real w, const Real strike, const Size i) const
Real lambdaStarHelper(const Real lambda) const
const QuantLib::ext::shared_ptr< CrossAssetModel > model_
const Handle< YieldTermStructure > termStructure_
AnalyticLgmCdsOptionEngine(const QuantLib::ext::shared_ptr< CrossAssetModel > &model, const Size index, const Size ccy, const Real recoveryRate, const Handle< YieldTermStructure > &termStructure=Handle< YieldTermStructure >())
RandomVariable sqrt(RandomVariable x)
Real sum(const Cash &c, const Cash &d)
Swap::arguments * arguments_