21#include <ql/cashflows/fixedratecoupon.hpp>
22#include <ql/instruments/claim.hpp>
23#include <ql/math/interpolations/forwardflatinterpolation.hpp>
24#include <ql/pricingengines/credit/isdacdsengine.hpp>
25#include <ql/termstructures/credit/flathazardrate.hpp>
26#include <ql/termstructures/credit/piecewisedefaultcurve.hpp>
27#include <ql/termstructures/yield/flatforward.hpp>
28#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
29#include <ql/time/calendars/weekendsonly.hpp>
30#include <ql/time/daycounters/actual360.hpp>
31#include <ql/optional.hpp>
39 const ext::optional<bool>& includeSettlementDateFlows,
43 : probability_(
std::move(probability)), recoveryRate_(recoveryRate),
44 discountCurve_(
std::move(discountCurve)),
45 includeSettlementDateFlows_(includeSettlementDateFlows), numericalFix_(numericalFix),
46 accrualBias_(accrualBias), forwardsInCouponPeriod_(forwardsInCouponPeriod) {
55 "numerical fix must be None or Taylor");
57 "accrual bias must be HalfDayBias or NoBias");
60 "forwards in coupon period must be Flat or Piecewise");
75 QL_REQUIRE(!
discountCurve_.empty(),
"no discount term structure set");
76 QL_REQUIRE(!
probability_.empty(),
"no probability term structure set");
78 "yield term structure day counter ("
80 <<
") should be Act/365(Fixed)");
82 "probability term structure day counter ("
86 "yield term structure reference date ("
88 <<
" should be evaluation date (" << evalDate <<
")");
90 "probability term structure reference date ("
92 <<
" should be evaluation date (" << evalDate <<
")");
94 "ISDA engine not compatible with non accrual paying CDS");
96 "ISDA engine not compatible with end period payment");
97 QL_REQUIRE(ext::dynamic_pointer_cast<FaceValueClaim>(
arguments_.
claim) !=
nullptr,
98 "ISDA engine not compatible with non face value claim");
101 Date effectiveProtectionStart =
105 std::vector<Date> yDates, cDates;
114 ext::dynamic_pointer_cast<
116 yDates = castY1->dates();
118 castY2 = ext::dynamic_pointer_cast<
120 yDates = castY2->dates();
122 castY3 = ext::dynamic_pointer_cast<
124 yDates = castY3->dates();
125 }
else if(ext::shared_ptr<FlatForward> castY4 =
129 QL_FAIL(
"Yield curve must be flat forward interpolated");
133 castC1 = ext::dynamic_pointer_cast<
136 cDates = castC1->dates();
139 ext::dynamic_pointer_cast<
141 cDates = castC2->dates();
143 ext::shared_ptr<FlatHazardRate> castC3 =
144 ext::dynamic_pointer_cast<FlatHazardRate>(*
probability_)) {
147 QL_FAIL(
"Credit curve must be flat forward interpolated");
150 std::vector<Date> nodes;
151 std::set_union(yDates.begin(), yDates.end(), cDates.begin(), cDates.end(), std::back_inserter(nodes));
155 nodes.push_back(maturity);
160 Real protectionNpv = 0.0;
162 Date d0 = effectiveProtectionStart-1;
166 std::vector<Date>::const_iterator it =
167 std::upper_bound(nodes.begin(), nodes.end(), effectiveProtectionStart);
169 for(;it != nodes.end(); ++it) {
172 it = nodes.end() - 1;
179 Real fhat = std::log(P0) - std::log(P1);
180 Real hhat = std::log(Q0) - std::log(Q1);
181 Real fhphh = fhat + hhat;
184 Real fhphhq = fhphh * fhphh;
186 P0 * Q0 * hhat * (1.0 - 0.5 * fhphh + 1.0 / 6.0 * fhphhq -
187 1.0 / 24.0 * fhphhq * fhphh +
188 1.0 / 120 * fhphhq * fhphhq);
190 protectionNpv += hhat / (fhphh + nFix) * (P0 * Q0 - P1 * Q1);
203 Real premiumNpv = 0.0, defaultAccrualNpv = 0.0;
205 ext::shared_ptr<FixedRateCoupon> coupon = ext::dynamic_pointer_cast<FixedRateCoupon>(i);
207 QL_REQUIRE(coupon->dayCounter() == dc ||
208 coupon->dayCounter() == dc1 ||
209 coupon->dayCounter() == dc2,
210 "ISDA engine requires a coupon day counter Act/365Fixed "
211 <<
"or Act/360 (" << coupon->dayCounter() <<
")");
225 Date start = std::max<Date>(coupon->accrualStartDate(),
226 effectiveProtectionStart)-1;
227 Date end = coupon->date()-1;
231 std::vector<Date> localNodes;
232 localNodes.push_back(start);
235 std::vector<Date>::const_iterator it0 =
236 std::upper_bound(nodes.begin(), nodes.end(), start);
237 std::vector<Date>::const_iterator it1 =
238 std::lower_bound(nodes.begin(), nodes.end(), end);
239 localNodes.insert(localNodes.end(), it0, it1);
241 localNodes.push_back(end);
243 Real defaultAccrThisNode = 0.;
244 std::vector<Date>::const_iterator node = localNodes.begin();
249 for (++node; node != localNodes.end(); ++node) {
253 Real fhat = std::log(P0) - std::log(P1);
254 Real hhat = std::log(Q0) - std::log(Q1);
255 Real fhphh = fhat + hhat;
260 Real fhphhq = fhphh * fhphh;
261 defaultAccrThisNode +=
264 (1.0 - 0.5 * fhphh + 1.0 / 6.0 * fhphhq -
265 1.0 / 24.0 * fhphhq * fhphh) +
267 (0.5 - 1.0 / 3.0 * fhphh + 1.0 / 8.0 * fhphhq -
268 1.0 / 30.0 * fhphhq * fhphh));
270 defaultAccrThisNode +=
271 (hhat / (fhphh + nFix)) *
272 ((t1 - t0) * ((P0 * Q0 - P1 * Q1) / (fhphh + nFix) -
274 (t0 - tstart) * (P0 * Q0 - P1 * Q1));
282 coupon->rate() * 365. / 360.;
311 Real upfrontSign = 1.0;
323 QL_FAIL(
"unknown protection side");
340 if (upfrontSensitivity != 0.0) {
349 static const Rate basisPoint = 1.0e-4;
Actual/360 day count convention.
Actual/365 (Fixed) day count convention.
ext::shared_ptr< Claim > claim
ext::shared_ptr< SimpleCashFlow > accrualRebate
ext::optional< Rate > upfront
ext::shared_ptr< SimpleCashFlow > upfrontPayment
virtual bool hasOccurred(const Date &refDate=Date(), ext::optional< bool > includeRefDate=ext::nullopt) const
returns true if an event has already occurred before a date
CreditDefaultSwap::results results_
CreditDefaultSwap::arguments arguments_
Shared handle to an observable.
YieldTermStructure based on interpolation of discount factors.
YieldTermStructure based on interpolation of forward rates.
DefaultProbabilityTermStructure based on interpolation of hazard rates.
DefaultProbabilityTermStructure based on interpolation of survival probabilities.
const ext::optional< bool > includeSettlementDateFlows_
Handle< YieldTermStructure > discountCurve_
IsdaCdsEngine(Handle< DefaultProbabilityTermStructure > probability, Real recoveryRate, Handle< YieldTermStructure > discountCurve, const ext::optional< bool > &includeSettlementDateFlows=ext::nullopt, NumericalFix numericalFix=Taylor, AccrualBias accrualBias=HalfDayBias, ForwardsInCouponPeriod forwardsInCouponPeriod=Piecewise)
Handle< DefaultProbabilityTermStructure > probability_
void calculate() const override
const ForwardsInCouponPeriod forwardsInCouponPeriod_
const NumericalFix numericalFix_
const AccrualBias accrualBias_
template class providing a null value for a given type.
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
DateProxy & evaluationDate()
the date at which pricing is to be performed.
static Settings & instance()
access to the unique instance