20#ifndef quantlib_binomial_loss_model_hpp
21#define quantlib_binomial_loss_model_hpp
82 std::vector<Real> notionals =
basket_->remainingNotionals(date);
83 std::vector<Probability> invProbs =
84 basket_->remainingProbabilities(date);
85 for(
Size iName=0; iName<invProbs.size(); iName++)
87 copula_->inverseCumulativeY(invProbs[iName], iName);
89 return copula_->integratedExpectedValueV(
90 [&](
const std::vector<Real>& v1) {
106 const std::vector<Real>&)
const;
108 const std::vector<Real>& bsktNots,
109 const std::vector<Probability>& uncondDefProbs,
110 const std::vector<Real>&)
const;
113 const std::vector<Real>& mktFactors)
const
115 std::vector<Real> condLgds;
116 const std::vector<Size>& evalDateLives =
basket_->liveList();
117 condLgds.reserve(evalDateLives.size());
118 for (
unsigned long evalDateLive : evalDateLives)
119 condLgds.push_back(1. -
copula_->conditionalRecovery(
d, evalDateLive, mktFactors));
129 const std::vector<Real>& bsktNots,
130 const std::vector<Real>& uncondDefProbInv,
131 const std::vector<Real>& mktFactor)
const;
149 const std::vector<Real>& bsktNots,
150 const std::vector<Real>& uncondDefProbInv,
151 const std::vector<Real>& mktFactors)
const
155 Size bsktSize = basket_->remainingSize();
165 std::vector<Real> fractionalEL = expConditionalLgd(date, mktFactors);
166 std::vector<Real> lgdsLeft;
167 std::transform(fractionalEL.begin(), fractionalEL.end(),
168 bsktNots.begin(), std::back_inserter(lgdsLeft),
169 std::multiplies<>());
171 std::accumulate(lgdsLeft.begin(), lgdsLeft.end(),
Real(0.)) /
174 std::vector<Probability> condDefProb(bsktSize, 0.);
175 for(
Size j=0; j<bsktSize; j++)
177 copula_->conditionalDefaultProbabilityInvP(uncondDefProbInv[j],
181 std::inner_product(condDefProb.begin(),
182 condDefProb.end(), lgdsLeft.begin(),
Real(0.))
183 / (avgLgd * bsktSize);
185 Real m = avgProb * bsktSize;
186 Real floorAveProb = std::min(
Real(bsktSize-1), std::floor(
Real(m)));
187 Real ceilAveProb = floorAveProb + 1.;
189 Real varianceBinom = avgProb * (1. - avgProb)/bsktSize;
191 std::vector<Probability> oneMinusDefProb;
192 std::transform(condDefProb.begin(), condDefProb.end(),
193 std::back_inserter(oneMinusDefProb),
194 [](
Real x) ->
Real { return 1.0-x; });
197 std::transform(condDefProb.begin(), condDefProb.end(),
198 oneMinusDefProb.begin(), condDefProb.begin(),
199 std::multiplies<>());
200 std::transform(lgdsLeft.begin(), lgdsLeft.end(),
201 lgdsLeft.begin(), lgdsLeft.begin(), std::multiplies<>());
203 condDefProb.end(), lgdsLeft.begin(),
Real(0.));
206 variance / (bsktSize * bsktSize * avgLgd * avgLgd );
207 Real sumAves = -std::pow(ceilAveProb-m, 2)
208 - (std::pow(floorAveProb-m, 2) - std::pow(ceilAveProb,2.))
211 / (varianceBinom * bsktSize + sumAves);
214 std::vector<Probability> lossProbDensity(bsktSize+1, 0.);
216 lossProbDensity[bsktSize] = 1.;
218 lossProbDensity[0] = 1.;
227 lossProbDensity[0] = std::pow(1.-avgProb,
228 static_cast<Real>(bsktSize));
229 for(
Size i=1; i<bsktSize+1; i++)
230 lossProbDensity[i] = lossProbDensity[i-1] * probsRatio
233 for(
Size i=0; i<bsktSize+1; i++)
234 lossProbDensity[i] *=
alpha;
236 Real epsilon = (1.-
alpha)*(ceilAveProb-m);
238 lossProbDensity[
static_cast<Size>(floorAveProb)] += epsilon;
239 lossProbDensity[
static_cast<Size>(ceilAveProb)] += epsilonPlus;
241 return lossProbDensity;
249 const std::vector<Real>& reminingNots,
250 const std::vector<Real>& mktFctrs)
const
252 Size bsktSize = basket_->remainingSize();
260 std::vector<Real> fractionalEL = expConditionalLgd(
d, mktFctrs);
261 Real notBskt = std::accumulate(reminingNots.begin(),
262 reminingNots.end(),
Real(0.));
263 std::vector<Real> lgdsLeft;
264 std::transform(fractionalEL.begin(), fractionalEL.end(),
265 reminingNots.begin(), std::back_inserter(lgdsLeft),
266 std::multiplies<>());
267 return std::accumulate(lgdsLeft.begin(), lgdsLeft.end(),
Real(0.))
268 / (bsktSize*notBskt);
274 std::vector<Real> notionals = basket_->remainingNotionals(
d);
276 Real aveLossFrct = copula_->integratedExpectedValue(
277 [&](
const std::vector<Real>& v1) {
278 return averageLoss(
d, notionals, v1);
281 std::vector<Real> data;
282 Size dataSize = basket_->remainingSize() + 1;
283 data.reserve(dataSize);
285 Real outsNot = basket_->remainingNotional(
d);
286 for(
Size i=0; i<dataSize; i++)
287 data.push_back(i * aveLossFrct * outsNot);
294 const std::vector<Real>& lossVals,
295 const std::vector<Real>& bsktNots,
296 const std::vector<Real>& uncondDefProbsInv,
297 const std::vector<Real>& mkf)
const {
299 std::vector<Real> condLProb =
300 lossProbability(
d, bsktNots, uncondDefProbsInv, mkf);
303 for(
Size i=0; i<lossVals.size(); i++) {
304 suma += condLProb[i] *
305 std::min(std::max(lossVals[i]
306 - attachAmount_, 0.), detachAmount_ - attachAmount_);
313 std::vector<Real> lossVals = lossPoints(
d);
314 std::vector<Real> notionals = basket_->remainingNotionals(
d);
315 std::vector<Probability> invProbs =
316 basket_->remainingProbabilities(
d);
317 for(
Size iName=0; iName<invProbs.size(); iName++)
319 copula_->inverseCumulativeY(invProbs[iName], iName);
321 return copula_->integratedExpectedValue(
322 [&](
const std::vector<Real>& v1) {
323 return condTrancheLoss(
d, lossVals, notionals, invProbs, v1);
331 std::map<Real, Probability> distrib;
332 std::vector<Real> lossPts = lossPoints(
d);
333 std::vector<Real> values = expectedDistribution(
d);
335 for(
Size i=0; i<lossPts.size(); i++) {
336 distrib.insert(std::make_pair(lossPts[i],
338 std::min(sum+values[i],1.)
347 std::map<Real, Probability> dist = lossDistribution(
d);
350 (dist.begin()->second >= perc))
return dist.begin()->first;
353 if(dist.size() == 1)
return dist.begin()->first;
355 if(perc == 1.)
return dist.rbegin()->first;
356 if(perc == 0.)
return dist.begin()->first;
357 std::map<Real, Probability>::const_iterator itdist = dist.begin();
358 while (itdist->second <= perc) ++itdist;
359 Real valPlus = itdist->second;
360 Real xPlus = itdist->first;
362 Real valMin = itdist->second;
363 Real xMin = itdist->first;
365 Real portfLoss = xPlus-(xPlus-xMin)*(valPlus-perc)/(valPlus-valMin);
368 std::min(std::max(portfLoss - attachAmount_, 0.),
369 detachAmount_ - attachAmount_);
378 std::map<Real, Probability> distrib = lossDistribution(
d);
380 std::map<Real, Probability>::iterator
381 itNxt, itDist = distrib.begin();
382 for(; itDist != distrib.end(); ++itDist)
383 if(itDist->second >= perctl)
break;
389 if(itNxt != distrib.end()) {
390 Real lossNxt = std::min(std::max(itNxt->first - attachAmount_,
391 0.), detachAmount_ - attachAmount_);
392 Real lossHere = std::min(std::max(itDist->first - attachAmount_,
393 0.), detachAmount_ - attachAmount_);
395 Real val = lossNxt - (itNxt->second - perctl) *
396 (lossNxt - lossHere) / (itNxt->second - itDist->second);
397 Real suma = (itNxt->second - perctl) * (lossNxt + val) * .5;
400 lossNxt = std::min(std::max(itNxt->first - attachAmount_,
401 0.), detachAmount_ - attachAmount_);
402 lossHere = std::min(std::max(itDist->first - attachAmount_,
403 0.), detachAmount_ - attachAmount_);
404 suma += .5 * (lossHere + lossNxt)
405 * (itNxt->second - itDist->second);
407 }
while(itNxt != distrib.end());
408 return suma / (1.-perctl);
410 QL_FAIL(
"Binomial model fails to calculate ESF.");
basket of issuers and related notionals
std::vector< Real > expConditionalLgd(const Date &d, const std::vector< Real > &mktFactors) const
std::vector< Real > expectedDistribution(const Date &date) const
Real percentile(const Date &d, Real percentile) const override
Loss level for this percentile.
std::vector< Real > lossProbability(const Date &date, const std::vector< Real > &bsktNots, const std::vector< Real > &uncondDefProbInv, const std::vector< Real > &mktFactor) const
Loss probability density conditional on the market factor value.
Real averageLoss(const Date &, const std::vector< Real > &reminingNots, const std::vector< Real > &) const
Average loss per credit.
BinomialLossModel(ext::shared_ptr< LLM > copula)
std::vector< Real > lossPoints(const Date &) const
attainable loss points this model provides
void resetModel() override
Concrete models do now any updates/inits they need on basket reset.
Real expectedTrancheLoss(const Date &d) const override
const ext::shared_ptr< LLM > copula_
LLM::copulaType copulaType
Real expectedShortfall(const Date &d, Real percentile) const override
Expected shortfall given a default loss percentile.
std::map< Real, Probability > lossDistribution(const Date &d) const override
Returns the cumulative full loss distribution.
Real condTrancheLoss(const Date &, const std::vector< Real > &lossVals, const std::vector< Real > &bsktNots, const std::vector< Probability > &uncondDefProbs, const std::vector< Real > &) const
RelinkableHandle< Basket > basket_
static Settings & instance()
access to the unique instance
#define QL_FAIL(message)
throw an error (possibly with file and line information)
LinearInterpolation variance
Real Probability
probability
std::size_t Size
size of a container
Globally accessible relinkable pointer.
BinomialLossModel< GaussianConstantLossLM > GaussianBinomialLossModel
BinomialLossModel< TConstantLossLM > TBinomialLossModel