20#ifndef quantlib_saddle_point_lossmodel_hpp
21#define quantlib_saddle_point_lossmodel_hpp
113 const std::vector<Real>& invUncondProbs,
115 const std::vector<Real>& mktFactor)
const;
127 const std::vector<Real>& invUncondProbs,
129 const std::vector<Real>& mktFactor)
const;
140 const std::vector<Real>& invUncondProbs,
142 const std::vector<Real>& mktFactor)
const;
144 const std::vector<Real>& invUncondProbs,
146 const std::vector<Real>& mktFactor)
const;
148 const std::vector<Real>& invUncondProbs,
150 const std::vector<Real>& mktFactor)
const ;
156 const std::vector<Real>& invUncondProbs,
158 const std::vector<Real>& mktFactor)
const;
160 const std::vector<Real>& invUncondProbs,
162 const std::vector<Real>& mktFactor)
const;
186 const std::vector<Real>& invUncondProbs,
187 const std::vector<Real>& mktFactor
219 const std::vector<Real>& invUncondProbs,
221 const std::vector<Real>& mktFactor,
222 Real accuracy = 1.0e-3,
256 const std::vector<Real>& invUncondProbs,
257 Real trancheLossFract,
258 const std::vector<Real>& mktFactor)
const;
260 const std::vector<Real>& invUncondProbs,
262 const std::vector<Real>& mktFactor)
const;
281 const std::vector<Real>& invUncondProbs,
283 const std::vector<Real>& mktFactor)
const;
296 Real loss,
const std::vector<Real>& mktFactor)
const;
301 const std::vector<Real>& invUncondProbs,
302 Real loss, std::vector<Real> mktFactor)
const;
304 const std::vector<Real>& invUncondProbs,
305 Real lossPerc,
const std::vector<Real>& mktFactor)
const;
307 const std::vector<Real>& invUncondProbs,
309 const std::vector<Real>& mktFactor)
const;
311 const std::vector<Real>& invUncondProbs,
312 Real lossPerc,
const std::vector<Real>& mktFactor)
const;
332 const std::vector<Real>& invUncondProbs,
333 const std::vector<Real>& mktFactor)
const;
335 const std::vector<Real>& invUncondProbs,
336 const std::vector<Real>& mktFactor)
const;
342 /
basket_->remainingNotional(), 1.);
344 /
basket_->remainingNotional(), 1.);
348 const ext::shared_ptr<ConstantLossLatentmodel<CP> >
copula_;
390 std::vector<Real> invUncondProbs =
391 basket_->remainingProbabilities(date);
392 for(
Size i=0; i<invUncondProbs.size(); i++)
394 copula_->inverseCumulativeY(invUncondProbs[i], i);
396 return copula_->integratedExpectedValue(
397 [&](
const std::vector<Real>& v1) {
398 return CumulantGeneratingCond(invUncondProbs,
s, v1);
406 std::vector<Real> invUncondProbs =
407 basket_->remainingProbabilities(date);
408 for(
Size i=0; i<invUncondProbs.size(); i++)
410 copula_->inverseCumulativeY(invUncondProbs[i], i);
412 return copula_->integratedExpectedValue(
413 [&](
const std::vector<Real>& v1) {
414 return CumGen1stDerivativeCond(invUncondProbs,
s, v1);
422 std::vector<Real> invUncondProbs =
423 basket_->remainingProbabilities(date);
424 for(
Size i=0; i<invUncondProbs.size(); i++)
426 copula_->inverseCumulativeY(invUncondProbs[i], i);
428 return copula_->integratedExpectedValue(
429 [&](
const std::vector<Real>& v1) {
430 return CumGen2ndDerivativeCond(invUncondProbs,
s, v1);
438 std::vector<Real> invUncondProbs =
439 basket_->remainingProbabilities(date);
440 for(
Size i=0; i<invUncondProbs.size(); i++)
442 copula_->inverseCumulativeY(invUncondProbs[i], i);
444 return copula_->integratedExpectedValue(
445 [&](
const std::vector<Real>& v1) {
446 return CumGen3rdDerivativeCond(invUncondProbs,
s, v1);
454 std::vector<Real> invUncondProbs =
455 basket_->remainingProbabilities(date);
456 for(
Size i=0; i<invUncondProbs.size(); i++)
458 copula_->inverseCumulativeY(invUncondProbs[i], i);
460 return copula_->integratedExpectedValue(
461 [&](
const std::vector<Real>& v1) {
462 return CumGen4thDerivativeCond(invUncondProbs,
s, v1);
468 const Date&
d,
Real trancheLossFract)
const
471 if (trancheLossFract >=
473 basket_->detachmentAmount())
return 0.;
475 std::vector<Real> invUncondProbs =
476 basket_->remainingProbabilities(
d);
477 for(
Size i=0; i<invUncondProbs.size(); i++)
479 copula_->inverseCumulativeY(invUncondProbs[i], i);
481 return copula_->integratedExpectedValue(
482 [&](
const std::vector<Real>& v1) {
483 return probOverLossCond(invUncondProbs, trancheLossFract, v1);
491 std::vector<Probability> invUncondProbs =
492 basket_->remainingProbabilities(
d);
493 for(
Size i=0; i<invUncondProbs.size(); i++)
495 copula_->inverseCumulativeY(invUncondProbs[i], i);
497 return copula_->integratedExpectedValue(
498 [&](
const std::vector<Real>& v1) {
499 return probOverLossPortfCond(invUncondProbs, loss, v1);
507 std::vector<Real> invUncondProbs =
508 basket_->remainingProbabilities(
d);
509 for(
Size i=0; i<invUncondProbs.size(); i++)
511 copula_->inverseCumulativeY(invUncondProbs[i], i);
513 return copula_->integratedExpectedValue(
514 [&](
const std::vector<Real>& v1) {
515 return conditionalExpectedTrancheLoss(invUncondProbs, v1);
523 std::vector<Real> invUncondProbs =
524 basket_->remainingProbabilities(
d);
525 for(
Size i=0; i<invUncondProbs.size(); i++)
527 copula_->inverseCumulativeY(invUncondProbs[i], i);
529 return copula_->integratedExpectedValue(
530 [&](
const std::vector<Real>& v1) {
531 return probDensityCond(invUncondProbs, loss, v1);
538 std::vector<Real> invUncondProbs =
539 basket_->remainingProbabilities(date);
540 for(
Size i=0; i<invUncondProbs.size(); i++)
542 copula_->inverseCumulativeY(invUncondProbs[i], i);
544 return copula_->integratedExpectedValueV(
545 [&](
const std::vector<Real>& v1) {
546 return splitLossCond(invUncondProbs,
s, v1);
567 const std::vector<Real>& invUncondProbs,
569 const std::vector<Real>& mktFactor)
const
571 const Size nNames = remainingNotionals_.size();
574 for(
Size iName=0; iName < nNames; iName++) {
576 copula_->conditionalDefaultProbabilityInvP(
577 invUncondProbs[iName], iName, mktFactor);
578 sum += std::log(1. - pBuffer +
579 pBuffer * std::exp(remainingNotionals_[iName] *
580 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
581 iName, mktFactor)) * lossFraction / remainingNotional_));
588 const std::vector<Real>& invUncondProbs,
590 const std::vector<Real>& mktFactor)
const
592 const Size nNames = remainingNotionals_.size();
595 for(
Size iName=0; iName < nNames; iName++) {
597 copula_->conditionalDefaultProbabilityInvP(
598 invUncondProbs[iName], iName, mktFactor);
600 Real lossInDef = remainingNotionals_[iName] *
601 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
602 iName, mktFactor)) / remainingNotional_;
603 Real midFactor = pBuffer * std::exp(lossInDef * saddle);
604 sum += lossInDef * midFactor / (1.-pBuffer + midFactor);
611 const std::vector<Real>& invUncondProbs,
613 const std::vector<Real>& mktFactor)
const
615 const Size nNames = remainingNotionals_.size();
618 for(
Size iName=0; iName < nNames; iName++) {
620 copula_->conditionalDefaultProbabilityInvP(
621 invUncondProbs[iName], iName, mktFactor);
623 Real lossInDef = remainingNotionals_[iName] *
624 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
625 iName, mktFactor)) / remainingNotional_;
626 Real midFactor = pBuffer * std::exp(lossInDef * saddle);
627 Real denominator = 1.-pBuffer + midFactor;
628 sum += lossInDef * lossInDef * midFactor / denominator -
629 std::pow(lossInDef * midFactor / denominator , 2.);
636 const std::vector<Real>& invUncondProbs,
638 const std::vector<Real>& mktFactor)
const
640 const Size nNames = remainingNotionals_.size();
643 for(
Size iName=0; iName < nNames; iName++) {
645 copula_->conditionalDefaultProbabilityInvP(
646 invUncondProbs[iName], iName, mktFactor);
647 Real lossInDef = remainingNotionals_[iName] *
648 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
649 iName, mktFactor)) / remainingNotional_;
651 const Real midFactor = pBuffer * std::exp(lossInDef * saddle);
652 const Real denominator = 1.-pBuffer + midFactor;
654 const Real& suma0 = denominator;
655 const Real suma1 = lossInDef * midFactor;
656 const Real suma2 = lossInDef * suma1;
657 const Real suma3 = lossInDef * suma2;
659 sum += (suma3 + (2.*std::pow(suma1, 3.)/suma0 -
660 3.*suma1*suma2)/suma0)/suma0;
667 const std::vector<Real>& invUncondProbs,
669 const std::vector<Real>& mktFactor)
const
671 const Size nNames = remainingNotionals_.size();
674 for(
Size iName=0; iName < nNames; iName++) {
676 copula_->conditionalDefaultProbabilityInvP(
677 invUncondProbs[iName], iName, mktFactor);
678 Real lossInDef = remainingNotionals_[iName] *
679 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
680 iName, mktFactor)) / remainingNotional_;
682 Real midFactor = pBuffer * std::exp(lossInDef * saddle);
683 Real denominator = 1.-pBuffer + midFactor;
685 const Real& suma0 = denominator;
686 const Real suma1 = lossInDef * midFactor;
687 const Real suma2 = lossInDef * suma1;
688 const Real suma3 = lossInDef * suma2;
689 const Real suma4 = lossInDef * suma3;
691 sum += (suma4 + (-4.*suma1*suma3 - 3.*suma2*suma2 +
692 (12.*suma1*suma1*suma2 -
693 6.*std::pow(suma1,4.)/suma0)/suma0)/suma0)/suma0;
700 const std::vector<Real>& invUncondProbs,
702 const std::vector<Real>& mktFactor)
const
704 const Size nNames = remainingNotionals_.size();
710 for(
Size iName=0; iName < nNames; iName++) {
712 copula_->conditionalDefaultProbabilityInvP(
713 invUncondProbs[iName], iName, mktFactor);
714 Real lossInDef = remainingNotionals_[iName] *
715 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
716 iName, mktFactor)) / remainingNotional_;
718 Real midFactor = pBuffer * std::exp(lossInDef * saddle);
719 Real denominator = 1.-pBuffer + midFactor;
721 const Real& suma0 = denominator;
722 const Real suma1 = lossInDef * midFactor;
723 const Real suma2 = lossInDef * suma1;
724 const Real suma3 = lossInDef * suma2;
725 const Real suma4 = lossInDef * suma3;
728 deriv0 += std::log(suma0);
730 deriv2 += suma2 / suma0 - std::pow(suma1 / suma0 , 2.);
731 deriv3 += (suma3 + (2.*std::pow(suma1, 3.)/suma0 -
732 3.*suma1*suma2)/suma0)/suma0;
733 deriv4 += (suma4 + (-4.*suma1*suma3 - 3.*suma2*suma2 +
734 (12.*suma1*suma1*suma2 -
735 6.*std::pow(suma1,4.)/suma0)/suma0)/suma0)/suma0;
737 return {deriv0, deriv2, deriv3, deriv4};
742 const std::vector<Real>& invUncondProbs,
744 const std::vector<Real>& mktFactor)
const
746 const Size nNames = remainingNotionals_.size();
750 for(
Size iName=0; iName < nNames; iName++) {
752 copula_->conditionalDefaultProbabilityInvP(
753 invUncondProbs[iName], iName, mktFactor);
754 Real lossInDef = remainingNotionals_[iName] *
755 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
756 iName, mktFactor)) / remainingNotional_;
758 Real midFactor = pBuffer * std::exp(lossInDef * saddle);
759 Real denominator = 1.-pBuffer + midFactor;
761 const Real& suma0 = denominator;
762 const Real suma1 = lossInDef * midFactor;
763 const Real suma2 = lossInDef * suma1;
766 deriv0 += std::log(suma0);
768 deriv2 += suma2 / suma0 - std::pow(suma1 / suma0 , 2.);
770 return {deriv0, deriv2};
777 const std::vector<Real>& invUncondPs,
779 const std::vector<Real>& mktFactor,
789 Size nNames = remainingNotionals_.size();
790 std::vector<Real> lgds;
791 for(
Size iName=0; iName<nNames; iName++)
792 lgds.push_back(remainingNotionals_[iName] *
793 (1.-copula_->conditionalRecoveryInvP(invUncondPs[iName], iName,
799 Size iNamMax = std::distance(lgds.begin(),
800 std::max_element(lgds.begin(), lgds.end()) );
803 static const Real deltaMin = 1.e-5;
805 Probability pMaxName = copula_->conditionalDefaultProbabilityInvP(
806 invUncondPs[iNamMax], iNamMax, mktFactor);
810 Real saddleMin = 1./(lgds[iNamMax]/remainingNotional_) *
811 std::log(deltaMin*(1.-pMaxName)/
812 (pMaxName*lgds[iNamMax]/remainingNotional_-pMaxName*deltaMin));
816 CumGen1stDerivativeCond(invUncondPs, saddleMin, mktFactor);
821 if(lossLevel < minLoss)
return saddleMin;
823 Real saddleMax = 1./(lgds[iNamMax]/remainingNotional_) *
824 std::log((lgds[iNamMax]/remainingNotional_
825 -deltaMin)*(1.-pMaxName)/(pMaxName*deltaMin));
827 CumGen1stDerivativeCond(invUncondPs, saddleMax, mktFactor);
828 if(lossLevel > maxLoss)
return saddleMax;
831 Real guess = (saddleMin+saddleMax)/2.;
839 return solverBrent.
solve(
f, accuracy, guess, saddleMin, saddleMax);
851 QL_REQUIRE(percentile >=0. && percentile <=1.,
852 "Incorrect percentile value.");
860 if(percentile <= 1.-probOverLoss(
d, 0.))
return 0.;
861 if(percentile >= 1.-probOverLoss(
d, 1.))
862 return basket_->remainingTrancheNotional();
872 Real solut = solver.
solve(
f, 1.e-4, guess, minVal, maxVal);
873 return basket_->remainingTrancheNotional() * solut;
878 const std::vector<Real>& invUncondPs,
879 Real trancheLossFract,
880 const std::vector<Real>& mktFactor)
const {
881 Real portfFract = attachRatio_ + trancheLossFract *
882 (detachRatio_-attachRatio_);
889 probOverLossPortfCond(invUncondPs,
891 portfFract * basket_->basketNotional(),
897 std::map<Real, Probability> distrib;
898 static constexpr double numPts = 500.;
899 for(
Real lossFraction=1./numPts; lossFraction<0.45;
900 lossFraction+= 1./numPts)
901 distrib.insert(std::make_pair<Real, Probability>(
902 lossFraction * remainingNotional_ ,
903 1.-probOverPortfLoss(
d, lossFraction* remainingNotional_ )));
920 const std::vector<Real>& invUncondProbs,
922 const std::vector<Real>& mktFactor)
const
932 Real relativeLoss = loss / remainingNotional_;
935 const Size nNames = remainingNotionals_.size();
937 Real averageRecovery_ = 0.;
938 for(
Size iName=0; iName < nNames; iName++)
939 averageRecovery_ += copula_->conditionalRecoveryInvP(
940 invUncondProbs[iName], iName, mktFactor);
941 averageRecovery_ = averageRecovery_ / nNames;
943 Real maxAttLossFract = 1.-averageRecovery_;
944 if(relativeLoss > maxAttLossFract)
return 0.;
946 Real saddlePt = findSaddle(invUncondProbs,
947 relativeLoss, mktFactor);
949 ext::tuple<Real, Real, Real, Real> cumulants =
950 CumGen0234DerivCond(invUncondProbs,
951 saddlePt, mktFactor);
952 Real baseVal = ext::get<0>(cumulants);
953 Real secondVal = ext::get<1>(cumulants);
954 Real K3Saddle = ext::get<2>(cumulants);
955 Real K4Saddle = ext::get<3>(cumulants);
957 Real saddleTo2 = saddlePt * saddlePt;
958 Real saddleTo3 = saddleTo2 * saddlePt;
959 Real saddleTo4 = saddleTo3 * saddlePt;
960 Real saddleTo6 = saddleTo4 * saddleTo2;
961 Real K3SaddleTo2 = K3Saddle*K3Saddle;
964 Real exponent = baseVal - relativeLoss * saddlePt +
965 .5 * saddleTo2 * secondVal;
966 if( std::abs(exponent) > 700.)
return 0.;
970 std::sqrt(secondVal))
973 * (1. - saddleTo3*K3Saddle/6. + saddleTo4*K4Saddle/24. +
974 saddleTo6*K3SaddleTo2/72.)
985 }
else if(saddlePt==0.){
988 Real exponent = baseVal - relativeLoss * saddlePt +
989 .5 * saddleTo2 * secondVal;
990 if( std::abs(exponent) > 700.)
return 0.;
995 * std::sqrt(secondVal))
998 * (1. - saddleTo3*K3Saddle/6. + saddleTo4*K4Saddle/24. +
999 saddleTo6*K3SaddleTo2/72.)
1014 const std::vector<Real>& invUncondPs,
1016 const std::vector<Real>& mktFactor)
const
1019 const Size nNames = remainingNotionals_.size();
1021 Real relativeLoss = loss / remainingNotional_;
1025 Real averageRecovery_ = 0.;
1026 for(
Size iName=0; iName < nNames; iName++)
1028 copula_->conditionalRecoveryInvP(invUncondPs[iName], iName,
1030 averageRecovery_ = averageRecovery_ / nNames;
1032 Real maxAttLossFract = 1.-averageRecovery_;
1033 if(relativeLoss > maxAttLossFract)
return 0.;
1035 Real saddlePt = findSaddle(invUncondPs,
1036 relativeLoss, mktFactor);
1038 ext::tuple<Real, Real> cumulants =
1039 CumGen02DerivCond(invUncondPs,
1040 saddlePt, mktFactor);
1041 Real baseVal = ext::get<0>(cumulants);
1042 Real secondVal = ext::get<1>(cumulants);
1044 Real saddleTo2 = saddlePt * saddlePt;
1047 Real exponent = baseVal - relativeLoss * saddlePt +
1048 .5 * saddleTo2 * secondVal;
1049 if( std::abs(exponent) > 700.)
return 0.;
1056 std::sqrt(secondVal));
1057 }
else if(saddlePt==0.){
1060 Real exponent = baseVal - relativeLoss * saddlePt +
1061 .5 * saddleTo2 * secondVal;
1062 if( std::abs(exponent) > 700.)
return 0.;
1070 std::sqrt(secondVal));
1083 const std::vector<Real>& invUncondPs,
1085 const std::vector<Real>& mktFactor)
const
1089 Real relativeLoss = loss / remainingNotional_;
1090 Real saddlePt = findSaddle(invUncondPs,
1091 relativeLoss, mktFactor);
1093 ext::tuple<Real, Real, Real, Real> cumulants =
1094 CumGen0234DerivCond(invUncondPs,
1095 saddlePt, mktFactor);
1097 Real K0Saddle = ext::get<0>(cumulants);
1098 Real K2Saddle = ext::get<1>(cumulants);
1099 Real K3Saddle = ext::get<2>(cumulants);
1100 Real K4Saddle = ext::get<3>(cumulants);
1108 /(8.*std::pow(K2Saddle, 2.))
1109 - 5.*std::pow(K3Saddle,2.)
1110 /(24.*std::pow(K2Saddle, 3.))
1111 ) * std::exp(K0Saddle - saddlePt * relativeLoss)
1112 / (std::sqrt(2. *
M_PI * K2Saddle));
1128 const std::vector<Real>& invUncondProbs,
1130 std::vector<Real> mktFactor)
const
1132 const Size nNames = remainingNotionals_.size();
1133 std::vector<Real> condContrib(nNames, 0.);
1136 Real saddlePt = findSaddle(invUncondProbs, loss / remainingNotional_,
1139 for(
Size iName=0; iName<nNames; iName++) {
1141 copula_->conditionalDefaultProbabilityInvP(
1142 invUncondProbs[iName], iName, mktFactor);
1143 Real lossInDef = remainingNotionals_[iName] *
1144 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
1146 Real midFactor = pBuffer *
1147 std::exp(lossInDef * saddlePt/ remainingNotional_);
1148 Real denominator = 1.-pBuffer + midFactor;
1150 condContrib[iName] = lossInDef * midFactor / denominator;
1157 const std::vector<Real>& invUncondProbs,
1158 const std::vector<Real>& mktFactor)
const
1160 const Size nNames = remainingNotionals_.size();
1163 for(
Size iName=0; iName < nNames; iName++) {
1164 Probability pBuffer = copula_->conditionalDefaultProbabilityInvP(
1165 invUncondProbs[iName], iName, mktFactor);
1166 eloss += pBuffer * remainingNotionals_[iName] *
1167 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
1175 const std::vector<Real>& invUncondProbs,
1176 const std::vector<Real>& mktFactor)
const
1178 const Size nNames = remainingNotionals_.size();
1181 for(
Size iName=0; iName < nNames; iName++) {
1182 Probability pBuffer = copula_->conditionalDefaultProbabilityInvP(
1183 invUncondProbs[iName], iName, mktFactor);
1185 pBuffer * remainingNotionals_[iName] *
1186 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
1190 std::max(eloss - attachRatio_ * remainingNotional_, 0.),
1191 (detachRatio_ - attachRatio_) * remainingNotional_);
1196 const std::vector<Real>& invUncondProbs,
1197 Real lossPerc,
const std::vector<Real>& mktFactor)
const
1199 const Size nNames = remainingNotionals_.size();
1200 std::vector<Real> lgds;
1201 for(
Size iName=0; iName<nNames; iName++)
1202 lgds.push_back(remainingNotionals_[iName] *
1203 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
1204 iName, mktFactor)));
1205 std::vector<Real> vola(nNames, 0.), mu(nNames, 0.);
1206 Real volaTot = 0., muTot = 0.;
1207 for(
Size iName=0; iName < nNames; iName++) {
1208 Probability pBuffer = copula_->conditionalDefaultProbabilityInvP(
1209 invUncondProbs[iName], iName, mktFactor);
1210 mu[iName] = lgds[iName] * pBuffer / remainingNotionals_[iName];
1211 muTot += lgds[iName] * pBuffer;
1212 vola[iName] = lgds[iName] * lgds[iName] * pBuffer * (1.-pBuffer)
1213 / remainingNotionals_[iName];
1214 volaTot += lgds[iName] * lgds[iName] * pBuffer * (1.-pBuffer) ;
1216 for (
Size iName=0; iName < nNames; iName++)
1217 vola[iName] = vola[iName] / volaTot;
1219 std::vector<Real> esfPartition(nNames, 0.);
1220 for(
Size iName=0; iName < nNames; iName++) {
1221 Real uEdisp = (lossPerc-muTot)/std::sqrt(volaTot);
1222 esfPartition[iName] = mu[iName]
1226 return esfPartition;
1231 const std::vector<Real>& invUncondProbs,
1234 const std::vector<Real>& mktFactor)
const
1241 Real correctionTerm = 0.;
1242 Real probLOver = probOverLossPortfCond(invUncondProbs,
1243 basket_->detachmentAmount(), mktFactor);
1244 if(basket_->attachmentAmount() >
QL_EPSILON) {
1245 if(lossPerc < basket_->attachmentAmount()) {
1246 correctionTerm = ( (basket_->detachmentAmount()
1247 - 2.*basket_->attachmentAmount())*
1248 probOverLossPortfCond(invUncondProbs, lossPerc,
1250 + basket_->attachmentAmount() * probLOver )/(1.-percentile);
1252 correctionTerm = ( (percentile-1)*basket_->attachmentAmount()
1253 + basket_->detachmentAmount() * probLOver
1258 return expectedShortfallFullPortfolioCond(invUncondProbs,
1259 std::max(lossPerc, basket_->attachmentAmount()), mktFactor)
1260 + expectedShortfallFullPortfolioCond(invUncondProbs,
1261 basket_->detachmentAmount(), mktFactor)
1267 const std::vector<Real>& invUncondProbs,
1269 const std::vector<Real>& mktFactor)
const
1276 Real lossPercRatio = lossPerc /remainingNotional_;
1278 const Size nNames = remainingNotionals_.size();
1281 for(
Size iName=0; iName < nNames; iName++) {
1282 Probability pBuffer = copula_->conditionalDefaultProbabilityInvP(
1283 invUncondProbs[iName], iName, mktFactor);
1284 elCond += pBuffer * remainingNotionals_[iName] *
1285 (1.-copula_->conditionalRecoveryInvP(invUncondProbs[iName],
1288 Real saddlePt = findSaddle(invUncondProbs, lossPercRatio, mktFactor);
1292 elCond * probOverLossPortfCond(invUncondProbs, lossPerc, mktFactor)
1293 + (lossPerc - elCond) * probDensityCond(invUncondProbs, lossPerc,
1294 mktFactor) /saddlePt;
1333 Real lossPerc = percentile(
d, percProb);
1337 Real trancheAmount = basket_->trancheNotional() *
1338 (detachRatio_-attachRatio_);
1340 if(lossPerc >= trancheAmount)
return trancheAmount;
1342 std::vector<Real> invUncondProbs =
1343 basket_->remainingProbabilities(
d);
1344 for(
Size i=0; i<invUncondProbs.size(); i++)
1346 copula_->inverseCumulativeY(invUncondProbs[i], i);
1349 return copula_->integratedExpectedValue(
1350 [&](
const std::vector<Real>& v1) {
1351 return expectedShortfallFullPortfolioCond(invUncondProbs, lossPerc, v1);
basket of issuers and related notionals
Cumulative normal distribution function.
RelinkableHandle< Basket > basket_
Normal distribution function.
const std::vector< Real > & invUncondProbs_
Real derivative(Real x) const
SaddleObjectiveFunction(const SaddlePointLossModel &me, const Real target, const std::vector< Real > &invUncondProbs, const std::vector< Real > &mktFactor)
The passed target is in fractional loss units.
const std::vector< Real > & mktFactor_
const SaddlePointLossModel & me_
Real operator()(const Real x) const
SaddlePercObjFunction(const SaddlePointLossModel &me, const Real target, const Date &date)
const SaddlePointLossModel & me_
Real operator()(const Real x) const
Saddle point portfolio credit default loss model.
SaddlePointLossModel(const ext::shared_ptr< ConstantLossLatentmodel< CP > > &m)
Real CumulantGenerating(const Date &date, Real s) const
Probability probDensityCond(const std::vector< Real > &invUncondProbs, Real loss, const std::vector< Real > &mktFactor) const
Probability probOverLossCond(const std::vector< Real > &invUncondProbs, Real trancheLossFract, const std::vector< Real > &mktFactor) const
Real CumGen1stDerivative(const Date &date, Real s) const
std::vector< Real > remainingNotionals_
Real CumGen3rdDerivative(const Date &date, Real s) const
Real conditionalExpectedLoss(const std::vector< Real > &invUncondProbs, const std::vector< Real > &mktFactor) const
ext::tuple< Real, Real > CumGen02DerivCond(const std::vector< Real > &invUncondProbs, Real saddle, const std::vector< Real > &mktFactor) const
Probability probOverPortfLoss(const Date &d, Real loss) const
Real expectedShortfallTrancheCond(const std::vector< Real > &invUncondProbs, Real lossPerc, Probability percentile, const std::vector< Real > &mktFactor) const
Real expectedShortfallFullPortfolioCond(const std::vector< Real > &invUncondProbs, Real lossPerc, const std::vector< Real > &mktFactor) const
Real CumulantGeneratingCond(const std::vector< Real > &invUncondProbs, Real lossFraction, const std::vector< Real > &mktFactor) const
Real CumGen1stDerivativeCond(const std::vector< Real > &invUncondProbs, Real saddle, const std::vector< Real > &mktFactor) const
Real CumGen3rdDerivativeCond(const std::vector< Real > &invUncondProbs, Real saddle, const std::vector< Real > &mktFactor) const
std::vector< Real > splitVaRLevel(const Date &date, Real loss) const override
Probability probOverLossPortfCond1stOrder(const std::vector< Real > &invUncondProbs, Real loss, const std::vector< Real > &mktFactor) const
Real CumGen4thDerivative(const Date &date, Real s) const
std::vector< Real > splitLossCond(const std::vector< Real > &invUncondProbs, Real loss, std::vector< Real > mktFactor) const
Real CumGen2ndDerivative(const Date &date, Real s) const
Probability probOverLossPortfCond(const std::vector< Real > &invUncondProbs, Real loss, const std::vector< Real > &mktFactor) const
void resetModel() override
Concrete models do now any updates/inits they need on basket reset.
Real percentile(const Date &d, Probability percentile) const override
Real expectedShortfall(const Date &d, Probability percentile) const override
Expected shortfall given a default loss percentile.
Real CumGen2ndDerivativeCond(const std::vector< Real > &invUncondProbs, Real saddle, const std::vector< Real > &mktFactor) const
const ext::shared_ptr< ConstantLossLatentmodel< CP > > copula_
Real expectedTrancheLoss(const Date &d) const override
ext::tuple< Real, Real, Real, Real > CumGen0234DerivCond(const std::vector< Real > &invUncondProbs, Real saddle, const std::vector< Real > &mktFactor) const
Probability probDensity(const Date &d, Real loss) const
Real findSaddle(const std::vector< Real > &invUncondProbs, Real lossLevel, const std::vector< Real > &mktFactor, Real accuracy=1.0e-3, Natural maxEvaluations=50) const
Real conditionalExpectedTrancheLoss(const std::vector< Real > &invUncondProbs, const std::vector< Real > &mktFactor) const
Probability probOverLoss(const Date &d, Real trancheLossFract) const override
std::map< Real, Probability > lossDistribution(const Date &d) const override
Full loss distribution.
Real CumGen4thDerivativeCond(const std::vector< Real > &invUncondProbs, Real saddle, const std::vector< Real > &mktFactor) const
std::vector< Real > expectedShortfallSplitCond(const std::vector< Real > &invUncondProbs, Real lossPerc, const std::vector< Real > &mktFactor) const
static Settings & instance()
access to the unique instance
void setMaxEvaluations(Size evaluations)
Real solve(const F &f, Real accuracy, Real guess, Real step) const
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
unsigned QL_INTEGER Natural
positive integer
Real Probability
probability
std::size_t Size
size of a container
Maps tuple to either the boost or std implementation.