31 {
32
33 cpu_timer timer;
34 timer.start();
35
36 Date today = Settings::instance().evaluationDate();
37
42 results_.expectedTrancheLoss.clear();
43
47 const Real inceptionTrancheNotional =
arguments_.basket->trancheNotional();
48
49
50
51
52
53
55
56 Probability nonKnockOut = 1.0;
57
58 Real upfPVO1 = 0.0;
63 }
64
69 }
70
71
72 Real zeroRecovery_e1 = 0, recovery_e1 = 0;
73
74
75
76
77
78
79
80
81
82
83 results_.expectedTrancheLoss.push_back(recovery_e1);
84
85 for (Size i = 0; i <
arguments_.normalizedLeg.size(); i++) {
86 if (
arguments_.normalizedLeg[i]->hasOccurred(today)) {
87 results_.expectedTrancheLoss.push_back(0.);
88 continue;
89 }
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();
94
95 Date defaultDate = startDate + (endDate - startDate) / 2;
96
97 Real zeroRecovery_e2 =
98 arguments_.basket->expectedTrancheLoss(endDate,
true);
99
100 Real recovery_e2 =
101 arguments_.basket->expectedTrancheLoss(endDate,
false);
102
103 results_.expectedTrancheLoss.push_back(recovery_e2);
104 results_.premiumValue += ((inceptionTrancheNotional - zeroRecovery_e2) / inceptionTrancheNotional) *
106
107
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) {
115 } else {
116 QL_FAIL("protectionPaymentTime not handled");
117 }
118 const Real discount =
discountCurve_->discount(protectionPaymentDate);
119
120
121
123 results_.premiumValue += coupon->accruedAmount(defaultDate) * discount *
124 (zeroRecovery_e2 - zeroRecovery_e1) / inceptionTrancheNotional;
125
126 results_.protectionValue += discount * (recovery_e2 - recovery_e1);
127
128
129
130 recovery_e1 = recovery_e2;
131 zeroRecovery_e1 = zeroRecovery_e2;
132 }
133
134
135
136
140 } else {
143 }
146 results_.errorEstimate = Null<Real>();
147
148 Real fairSpread = 0.;
152 }
153
154 timer.stop();
155
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;
169}
const Instrument::results * results_
Swap::arguments * arguments_