20#ifndef quantlib_recursive_loss_model_hpp
21#define quantlib_recursive_loss_model_hpp
46 template<
class copulaPolicy>
63 const std::vector<Real>& mktFactor)
const;
65 const std::vector<Real>& mktFactor)
const;
68 const std::vector<Real>& mktFactor)
const;
72 const std::vector<Real>& mktFactor)
const;
75 const std::vector<Real>& mktFactor)
const;
106 const ext::shared_ptr<ConstantLossLatentmodel<copulaPolicy> >
copula_;
110 mutable std::vector<Real>
wk_;
132 const Date& date)
const
154 // calculate inverted unconditional Ps first so we save the inversion:
155 // TO DO : turn to STL algorithm code
156 std::vector<Probability> uncDefProb =
157 basket_->remainingProbabilities(date);
159 return copula_->integratedExpectedValue(
160 [&](const std::vector<Real>& v1) {
161 return expectedConditionalLoss(uncDefProb, v1);
165 std::vector<Probability> uncDefProb =
166 basket_->remainingProbabilities(date);
167 std::vector<Real> invProb;
168 for(
Size i=0; i<uncDefProb.size(); ++i)
169 invProb.push_back(copula_->inverseCumulativeY(uncDefProb[i], i));
171 return copula_->integratedExpectedValue(
172 [&](
const std::vector<Real>& v1) {
173 return expectedConditionalLossInvP(invProb, v1);
180 std::vector<Probability> uncDefProb =
181 basket_->remainingProbabilities(date);
182 return copula_->integratedExpectedValueV(
183 [&](
const std::vector<Real>& v1) {
184 return conditionalLossProb(uncDefProb, v1);
193 notionals_ = basket_->remainingNotionals();
194 notional_ = basket_->remainingNotional();
195 attachAmount_ = basket_->remainingAttachmentAmount();
196 detachAmount_ = basket_->remainingDetachmentAmount();
198 remainingBsktSize_ = notionals_.size();
200 copula_->resetBasket(basket_.currentLink());
202 std::vector<Real> lgdsTmp, lgds;
203 for(
Size i=0; i<remainingBsktSize_; ++i)
204 lgds.push_back(notionals_[i]*(1.-copula_->recoveries()[i]));
207 lgds.erase(std::remove(lgds.begin(), lgds.end(), 0.), lgds.end());
208 lossUnit_ = *(std::min_element(lgds.begin(), lgds.end()))
210 for(
Size i=0; i<remainingBsktSize_; ++i)
211 wk_.push_back(std::floor(lgdsTmp[i]/lossUnit_ + .5));
218 std::map<Real, Probability> distrib;
219 std::vector<Real> values = lossProbability(
d);
221 for(
Size i=0; i<values.size(); ++i) {
222 distrib.insert(std::make_pair<Real, Probability>(i * lossUnit_,
234 Real percentile)
const
236 std::map<Real, Probability> dist = lossDistribution(
d);
238 if(dist.begin()->second >=1.)
return dist.begin()->first;
241 if(dist.size() == 1)
return dist.begin()->first;
243 if(percentile == 1.)
return dist.rbegin()->second;
244 if(percentile == 0.)
return dist.begin()->second;
245 std::map<Real, Probability>::const_iterator itdist = dist.begin();
246 while (itdist->second <= percentile) ++itdist;
247 Real valPlus = itdist->second;
248 Real xPlus = itdist->first;
250 Real valMin = itdist->second;
251 Real xMin = itdist->first;
254 Real portfLoss = xPlus-(xPlus-xMin)*(valPlus-percentile)
257 std::min(std::max(portfLoss - attachAmount_, 0.),
258 detachAmount_ - attachAmount_);
266 std::map<Real, Probability> distrib = lossDistribution(
d);
268 std::map<Real, Probability>::iterator itNxt, itDist =
270 for(; itDist != distrib.end(); ++itDist)
271 if(itDist->second >= perctl)
break;
277 if(itNxt != distrib.end()) {
278 Real lossNxt = std::min(std::max(itNxt->first - attachAmount_,
279 0.), detachAmount_ - attachAmount_);
280 Real lossHere = std::min(std::max(itDist->first - attachAmount_,
281 0.), detachAmount_ - attachAmount_);
283 Real val = lossNxt - (itNxt->second - perctl) *
284 (lossNxt - lossHere) / (itNxt->second - itDist->second);
285 Real suma = (itNxt->second - perctl) * (lossNxt + val) * .5;
288 lossNxt = std::min(std::max(itNxt->first - attachAmount_,
289 0.), detachAmount_ - attachAmount_);
290 lossHere = std::min(std::max(itDist->first - attachAmount_,
291 0.), detachAmount_ - attachAmount_);
292 suma += .5 * (lossHere + lossNxt) * (itNxt->second -
295 }
while(itNxt != distrib.end());
296 return suma / (1.-perctl);
303 const std::vector<Probability>& pDefDate,
305 const std::vector<Real>& mktFactor)
const
309 const std::vector<Probability>& uncDefProb = pDefDate;
311 std::map<Real, Probability> pIndepDistrib;
313 pIndepDistrib.insert(std::make_pair(0., 1.));
314 for(
Size iName=0; iName<remainingBsktSize_; ++iName) {
316 copula_->conditionalDefaultProbability(uncDefProb[iName], iName,
319 std::map<Real, Probability> pDistTemp;
320 auto distIt = pIndepDistrib.begin();
321 while(distIt != pIndepDistrib.end()) {
323 auto matchIt = pDistTemp.find(distIt->first);
324 if (matchIt != pDistTemp.end()) {
325 matchIt->second += distIt->second * (1. - pDef);
327 pDistTemp.insert(std::make_pair(distIt->first,
328 distIt->second * (1.-pDef)));
331 matchIt = pDistTemp.find(distIt->first + wk_[iName]);
332 if(matchIt != pDistTemp.end()) {
333 matchIt->second += distIt->second * pDef;
335 pDistTemp.insert(std::make_pair(
336 distIt->first+wk_[iName], distIt->second * pDef));
341 pIndepDistrib = pDistTemp;
345 return pIndepDistrib;
351 const std::vector<Real>& invpDefDate,
353 const std::vector<Real>& mktFactor)
const
358 std::map<Real, Probability> pIndepDistrib;
360 pIndepDistrib.insert(std::make_pair(0., 1.));
361 for(
Size iName=0; iName<remainingBsktSize_; ++iName) {
363 copula_->conditionalDefaultProbabilityInvP(invpDefDate[iName],
367 std::map<Real, Probability> pDistTemp;
368 auto distIt = pIndepDistrib.begin();
369 while(distIt != pIndepDistrib.end()) {
371 auto matchIt = pDistTemp.find(distIt->first);
372 if(matchIt != pDistTemp.end()) {
373 matchIt->second += distIt->second * (1.-pDef);
375 pDistTemp.insert(std::make_pair(distIt->first,
376 distIt->second * (1.-pDef)));
379 matchIt = pDistTemp.find(distIt->first + wk_[iName]);
380 if(matchIt != pDistTemp.end()) {
381 matchIt->second += distIt->second * pDef;
383 pDistTemp.insert(std::make_pair(
384 distIt->first+wk_[iName], distIt->second * pDef));
389 pIndepDistrib = pDistTemp;
392 return pIndepDistrib;
407 const std::vector<Probability>& pDefDate,
409 const std::vector<Real>& mktFactor)
const
411 std::map<Real, Probability> pIndepDistrib =
412 conditionalLossDistrib(pDefDate, mktFactor);
422 auto distIt = pIndepDistrib.begin();
424 while(distIt != pIndepDistrib.end()) {
425 Real loss = distIt->first * lossUnit_;
427 loss = std::min(std::max(loss - attachAmount_, 0.),
428 detachAmount_ - attachAmount_);
430 expLoss += loss * distIt->second;
439 const std::vector<Real>& invPDefDate,
441 const std::vector<Real>& mktFactor)
const
443 std::map<Real, Probability> pIndepDistrib =
444 conditionalLossDistribInvP(invPDefDate, mktFactor);
454 auto distIt = pIndepDistrib.begin();
456 while(distIt != pIndepDistrib.end()) {
457 Real loss = distIt->first * lossUnit_;
459 loss = std::min(std::max(loss - attachAmount_, 0.),
460 detachAmount_ - attachAmount_);
462 expLoss += loss * distIt->second;
470 const std::vector<Probability>& pDefDate,
472 const std::vector<Real>& mktFactor)
const
474 std::map<Real, Probability> pIndepDistrib =
475 conditionalLossDistrib(pDefDate, mktFactor);
478 auto distIt = pIndepDistrib.begin();
479 while(distIt != pIndepDistrib.end()) {
486 results.push_back(distIt->second);
std::vector< Real > conditionalLossProb(const std::vector< Probability > &pDefDate, const std::vector< Real > &mktFactor) const
std::map< Real, Probability > conditionalLossDistrib(const std::vector< Probability > &pDefDate, const std::vector< Real > &mktFactor) const
Real expectedConditionalLoss(const std::vector< Probability > &pDefDate, const std::vector< Real > &mktFactor) const
Portfolio loss conditional to the market factor value.
Real attachAmount_
name to name factor. In the single factor copula:
Real percentile(const Date &d, Real percentile) const override
Value at Risk given a default loss percentile.
std::map< Real, Probability > conditionalLossDistribInvP(const std::vector< Real > &pDefDate, const std::vector< Real > &mktFactor) const
Real expectedConditionalLossInvP(const std::vector< Real > &pDefDate, const std::vector< Real > &mktFactor) const
Real expectedTrancheLoss(const Date &date) const override
std::vector< Real > notionals_
const ext::shared_ptr< ConstantLossLatentmodel< copulaPolicy > > copula_
RecursiveLossModel(const ext::shared_ptr< ConstantLossLatentmodel< copulaPolicy > > &m, Size nbuckets=1)
std::vector< Real > lossProbability(const Date &date) const
void resetModel() override
Concrete models do now any updates/inits they need on basket reset.
Real expectedShortfall(const Date &d, Real perctl) const override
Expected shortfall given a default loss percentile.
std::map< Real, Probability > lossDistribution(const Date &d) const override
Full loss distribution.
static Settings & instance()
access to the unique instance
Real Probability
probability
std::size_t Size
size of a container
RecursiveLossModel< GaussianCopulaPolicy > RecursiveGaussLossModel