21#ifndef QL_PATCH_SOLARIS
23#include <ql/cashflows/fixedratecoupon.hpp>
24#include <ql/termstructures/yieldtermstructure.hpp>
25#include <boost/timer/timer.hpp>
27using boost::timer::cpu_timer;
36 Date today = Settings::instance().evaluationDate();
42 results_.expectedTrancheLoss.clear();
47 const Real inceptionTrancheNotional =
arguments_.basket->trancheNotional();
56 Probability nonKnockOut = 1.0;
72 Real zeroRecovery_e1 = 0, recovery_e1 = 0;
83 results_.expectedTrancheLoss.push_back(recovery_e1);
85 for (Size i = 0; i <
arguments_.normalizedLeg.size(); i++) {
86 if (
arguments_.normalizedLeg[i]->hasOccurred(today)) {
87 results_.expectedTrancheLoss.push_back(0.);
90 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(
arguments_.normalizedLeg[i]);
91 Date paymentDate = coupon->date();
92 Date startDate = std::max(coupon->accrualStartDate(),
discountCurve_->referenceDate());
93 Date endDate = coupon->accrualEndDate();
95 Date defaultDate = startDate + (endDate - startDate) / 2;
97 Real zeroRecovery_e2 =
98 arguments_.basket->expectedTrancheLoss(endDate,
true);
101 arguments_.basket->expectedTrancheLoss(endDate,
false);
103 results_.expectedTrancheLoss.push_back(recovery_e2);
104 results_.premiumValue += ((inceptionTrancheNotional - zeroRecovery_e2) / inceptionTrancheNotional) *
108 Date protectionPaymentDate;
109 if (
arguments_.protectionPaymentTime == CreditDefaultSwap::ProtectionPaymentTime::atDefault) {
110 protectionPaymentDate = defaultDate;
111 }
else if (
arguments_.protectionPaymentTime == CreditDefaultSwap::ProtectionPaymentTime::atPeriodEnd) {
112 protectionPaymentDate = paymentDate;
113 }
else if (
arguments_.protectionPaymentTime == CreditDefaultSwap::ProtectionPaymentTime::atMaturity) {
116 QL_FAIL(
"protectionPaymentTime not handled");
118 const Real discount =
discountCurve_->discount(protectionPaymentDate);
123 results_.premiumValue += coupon->accruedAmount(defaultDate) * discount *
124 (zeroRecovery_e2 - zeroRecovery_e1) / inceptionTrancheNotional;
126 results_.protectionValue += discount * (recovery_e2 - recovery_e1);
130 recovery_e1 = recovery_e2;
131 zeroRecovery_e1 = zeroRecovery_e2;
146 results_.errorEstimate = Null<Real>();
148 Real fairSpread = 0.;
159 results_.additionalResults[
"fairSpread"] = fairSpread;
161 Real correlation =
arguments_.basket->correlation();
162 if (correlation != Null<Real>())
163 results_.additionalResults[
"correlation"] = correlation;
164 results_.additionalResults[
"upfrontPremiumNPV"] =
results_.upfrontPremiumValue;
166 results_.additionalResults[
"accrualRebateNPV"] =
results_.accrualRebateValue;
168 results_.additionalResults[
"calculationTime"] = timer.elapsed().wall * 1e-9;
const Instrument::results * results_
Handle< YieldTermStructure > discountCurve_
boost::optional< bool > includeSettlementDateFlows_
void calculate() const override
Swap::arguments * arguments_