Class FrtbDrcSecuritisation
Plain idea. A tranche's loss on default is already priced in its banking-book risk weight, so the jump-to-default amount is simply the tranche's market value. Longs and shorts net only within exactly the same tranche of the same pool (or index series). Inside a bucket the risk-weighted shorts offset the longs only to the extent of the hedge benefit ratio, as for non-securitisations. Non-CTP buckets are summed with no diversification. CTP buckets (one per index) may go negative and are aggregated with a second 50% haircut on net-short buckets.
Formal statement.
gross JTD = market value (signed) MAR22.27, MAR22.36, MAR22.37
nth-to-default: A = (N-1)/names, D = N/names MAR22.38
net JTD = Σ JTD_i·min(max(M_i, 0.25), 1) within one tranche MAR22.29, 22.30, 22.39
non-CTP: DRC_b = max(Σ RW·long − HBR_b·Σ RW·|short|, 0); DRC = Σ_b DRC_b MAR22.33, 22.35
CTP: DRC_b = Σ RW·long − HBR_ctp·Σ RW·|short| (no floor) MAR22.44
DRC_ctp = max(Σ_b (max(DRC_b,0) + 0.5·min(DRC_b,0)), 0) MAR22.45
Risk weights. MAR22.34(1) and MAR22.42 take the banking-book
securitisation risk weight with the maturity component set to zero, ie a
one-year tranche maturity. This class implements SEC-SA (CRE41.1 to
CRE41.22) and the one-year columns of SEC-ERBA (CRE42.2 to CRE42.14).
SEC-IRBA (CRE44) needs the bank's own K_IRB for the pool, so a weight
from it is taken as caller input in FrtbDrcSecuritisation.NetJtd.riskWeight(). The
banking-book weight is a multiple of exposure that includes the 8%
capital ratio (1250% means a deduction). Turning it into a DRC weight
per unit of JTD is done here by multiplying by 8% (drcRiskWeight(double)).
Evidence class: library reading. MAR22.34 and MAR22.42 (checked
against the consolidated Basel Framework text on disk) do not print the
factor. The reading rests on three printed rules: RBC20.1(3) sets total
capital at 8.0% of RWA, so a banking-book weight is RWA per unit of
exposure; MAR20.1 turns market-risk capital into RWA by x12.5, the
inverse of 8%, so DRC weights are capital per unit of JTD; and CRE41.4
footnote 211 converts a risk weight to capital as "risk weight times
8%" inside K_SA. It is also the only factor that makes the 1250%
weight a charge equal to the full market value, which matches the
fair-value cap of MAR22.34(3).
Non-tranched CTP products use the non-securitisation weights of
MAR22.24 (FrtbDrc.CreditQuality), MAR22.43.
Worked example (published reference, MAR22.45): CTP index buckets of +100 (CDX North America IG) and −100 (Major Sovereign) give a total of 100 − 0.5·100 = 50.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumThe 11 asset classes of MAR22.31(2)(a), plus the corporates bucket of MAR22.31(1).static enumLong-term rating grades of SEC-ERBA Tables 2 and 4 (CRE42.4, CRE42.13).static enumShort-term rating grades of SEC-ERBA Tables 1 and 3 (CRE42.2, CRE42.12).static final recordA net JTD of one tranche (signed, positive long) and its DRC risk weight per unit of JTD.static final recordA non-CTP bucket (MAR22.31, MAR22.32).static final recordA net tranche JTD tagged with its bucket key (aFrtbDrcSecuritisation.NonCtpBucket, or an index name for the CTP).static enumThe four regions of MAR22.31(2)(b). -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final doubleLargest pool share, by EAD, with unknown delinquency status that still allows SEC-SA (CRE41.9, CRE41.10).static final doubleThe 1250% banking-book risk weight (deduction), as a multiple. -
Method Summary
Modifier and TypeMethodDescriptionstatic <K> Map<K, List<FrtbDrcSecuritisation.NetJtd>> byBucket(List<FrtbDrcSecuritisation.Position<K>> positions) Groups positions by bucket key in first-seen order.static double[]checkSingleNameDecomposition(double securitisationValue, double[] singleNameEquivalents, boolean exotic, double tolerance) Checks a valuation-model decomposition into single-name equivalents (MAR22.39(2)): allowed for vanilla securitisations only (exotics such as CDO-squared are prohibited) and the single-name amounts must be consistent with the undecomposed value.static doublectpAggregate(List<Double> bucketCharges) CTP aggregation max(Σ_b (max(DRC_b, 0) + 0.5·min(DRC_b, 0)), 0) (MAR22.45).static doublectpBucketCharge(List<FrtbDrcSecuritisation.NetJtd> bucket, double hbrCtp) CTP index-bucket charge with the portfolio-wide HBR_ctp and no floor (MAR22.44): Σ RW·long − HBR_ctp·Σ RW·|short|; may be negative.static <K> doublectpTotal(List<FrtbDrcSecuritisation.Position<K>> positions) Total CTP DRC: one bucket per index, bespokes in the bucket of their index (MAR22.40, MAR22.41); HBR_ctp from all CTP positions together (MAR22.44(1)); aggregated by MAR22.45.static double[]decomposeIndex(double jtd, double[] attach, double[] detach) Decomposes a non-tranched index position (or a basket of its names) into replicating tranches that span the whole structure, for offsetting against tranche positions (MAR22.28 non-CTP; MAR22.39(3) CTP).static doubledrcRiskWeight(double bankingBookRiskWeight) Converts a banking-book securitisation risk weight (a multiple, 12.5 = 1250%) to a DRC weight: ×8% (see class note).static doubleerbaRiskWeight(FrtbDrcSecuritisation.ErbaRating rating, boolean senior, double thickness, boolean stc) SEC-ERBA banking-book risk weight as a multiple, one-year tranche maturity (MAR22.34(1), so the maturity interpolation of CRE42.5(1) is not needed).static doublegrossJtd(double signedMarketValue) Gross JTD of a securitisation position or of a CTP single-name or index hedge: its signed market value, no LGD applied (MAR22.27, MAR22.36, MAR22.37).static doublehedgeBenefitRatio(List<FrtbDrcSecuritisation.NetJtd> positions) HBR = Σ long / (Σ long + Σ |short|), unweighted (MAR22.23); 0 for an empty set.static doublejuniorUnratedFloor(double secSaRiskWeight, double nextSeniorRatedRiskWeight) Second sentence of CRE41.15: an unrated junior tranche in a deal whose more senior tranches are rated, where no rating can be inferred for the junior one, takes no less than the weight of the next more senior rated tranche.static doublekA(double kSa, double w) K_A = (1 − W)·K_SA + 0.5·W (CRE41.8).static doublekAPartlyUnknownW(double kAKnown, double eadKnown, double eadUnknown) K_A when W is unknown for part of the pool (CRE41.9): K_A = (EAD_known / EAD_total) * K_A^known + EAD_unknown / EAD_total, so the unknown subpool is charged at 100%.static doublekSsfa(double kA, double attach, double detach, double p) K_SSFA = (e^{a·u} − e^{a·l}) / (a·(u − l)) with a = −1/(p·K_A), u = D − K_A, l = max(A − K_A, 0) (CRE41.11).static doublenetTranche(double[] grossJtd, double[] maturityYears) Net JTD of one specific tranche (same pool or index series and the same attachment and detachment points) across maturities, with the one-year scaling and three-month floor of MAR22.15 to MAR22.18 (MAR22.30, MAR22.39).static doubleNon-CTP bucket charge, max(Σ RW·long − HBR_b·Σ RW·|short|, 0) (MAR22.33).static <K> doublenonCtpTotal(List<FrtbDrcSecuritisation.Position<K>> positions) Non-CTP total: simple sum of bucket charges (MAR22.35).static doublenthToDefaultAttachment(int n, int totalNames) Attachment point (N − 1) / names of an nth-to-default product (MAR22.38(1)).static doublenthToDefaultDetachment(int n, int totalNames) Detachment point N / names of an nth-to-default product (MAR22.38(2)).static double[]offsetByReplication(double attach, double detach, double jtd, double[] pieceAttach, double[] pieceDetach, double[] pieceJtd) Offset by replication within one index series or pool (MAR22.30(1), MAR22.39(3)).static booleansecSaPermittedWithUnknownW(double eadKnown, double eadUnknown) Whether SEC-SA may be used when the delinquency status is unknown for part of the pool: true when unknown EAD / total EAD is at most 5% (CRE41.9).static doublesecSaRiskWeight(double kA, double attach, double detach, boolean resecuritisation, boolean stc, boolean senior) SEC-SA banking-book risk weight as a multiple (CRE41.11 to CRE41.22). p = 1 (CRE41.12), 1.5 for a resecuritisation (CRE41.16(3)), 0.5 for STC (CRE41.21).
-
Field Details
-
RW_1250
public static final double RW_1250The 1250% banking-book risk weight (deduction), as a multiple.- See Also:
-
MAX_UNKNOWN_W_SHARE
public static final double MAX_UNKNOWN_W_SHARELargest pool share, by EAD, with unknown delinquency status that still allows SEC-SA (CRE41.9, CRE41.10).- See Also:
-
-
Method Details
-
grossJtd
public static double grossJtd(double signedMarketValue) Gross JTD of a securitisation position or of a CTP single-name or index hedge: its signed market value, no LGD applied (MAR22.27, MAR22.36, MAR22.37). -
nthToDefaultAttachment
public static double nthToDefaultAttachment(int n, int totalNames) Attachment point (N − 1) / names of an nth-to-default product (MAR22.38(1)). -
nthToDefaultDetachment
public static double nthToDefaultDetachment(int n, int totalNames) Detachment point N / names of an nth-to-default product (MAR22.38(2)). -
netTranche
public static double netTranche(double[] grossJtd, double[] maturityYears) Net JTD of one specific tranche (same pool or index series and the same attachment and detachment points) across maturities, with the one-year scaling and three-month floor of MAR22.15 to MAR22.18 (MAR22.30, MAR22.39). Different tranches, pools, series or index families must not be passed together (MAR22.29, MAR22.39(4)); a replication by decomposition goes throughdecomposeIndex(double, double[], double[]),offsetByReplication(double, double, double, double[], double[], double[])orcheckSingleNameDecomposition(double, double[], boolean, double)first (MAR22.28, MAR22.30(1)-(3), MAR22.39(2)-(3)). -
decomposeIndex
public static double[] decomposeIndex(double jtd, double[] attach, double[] detach) Decomposes a non-tranched index position (or a basket of its names) into replicating tranches that span the whole structure, for offsetting against tranche positions (MAR22.28 non-CTP; MAR22.39(3) CTP). Tranche i gets jtd * (D_i - A_i). The split by thickness is a library reading of "decomposed proportionately": a full capital structure loses exactly what the index loses, and a notional share equal to thickness is the split under which the tranches sum back to the index. Names treated this way must be taken out of the non-securitisation DRC (MAR22.28, last sentence); that is the caller's job.- Parameters:
jtd- signed JTD of the index position, finiteattach- attachment points, ascending, first 0detach- detachment points, detach[i] = attach[i + 1], last 1- Returns:
- one replicating JTD per tranche, same order
-
offsetByReplication
public static double[] offsetByReplication(double attach, double detach, double jtd, double[] pieceAttach, double[] pieceDetach, double[] pieceJtd) Offset by replication within one index series or pool (MAR22.30(1), MAR22.39(3)). A tranche [A, D] with JTDjtdis split over the sub-tranches that tile it exactly, in proportion to thickness, and added to the JTD already held in each. A perfect replication leaves zeros. The text's example (MAR22.39(3)) is a long 10-15% tranche against shorts in 10-12% and 12-15%. The ordinary netting ofnetTranche(double[], double[])then applies per sub-tranche (MAR22.30(3)).- Parameters:
attach- A of the tranche being replicateddetach- D of the tranche being replicatedjtd- signed JTD of that tranche, finitepieceAttach- sub-tranche attachments, ascending, first = ApieceDetach- sub-tranche detachments, contiguous, last = DpieceJtd- signed JTD already held in each sub-tranche- Returns:
- residual signed JTD per sub-tranche
-
checkSingleNameDecomposition
public static double[] checkSingleNameDecomposition(double securitisationValue, double[] singleNameEquivalents, boolean exotic, double tolerance) Checks a valuation-model decomposition into single-name equivalents (MAR22.39(2)): allowed for vanilla securitisations only (exotics such as CDO-squared are prohibited) and the single-name amounts must be consistent with the undecomposed value. The text gives no number for "consistent", so the tolerance is a caller input.- Parameters:
securitisationValue- undecomposed value of the securitisationsingleNameEquivalents- unconditional minus conditional-on-default value per nameexotic- true for CDO-squared and other exotic structurestolerance- allowed absolute gap between the sum and the value, at least 0- Returns:
- a copy of the single-name equivalents
- Throws:
IllegalArgumentException- if exotic or the sum misses by more thantolerance
-
drcRiskWeight
public static double drcRiskWeight(double bankingBookRiskWeight) Converts a banking-book securitisation risk weight (a multiple, 12.5 = 1250%) to a DRC weight: ×8% (see class note). -
kA
public static double kA(double kSa, double w) K_A = (1 − W)·K_SA + 0.5·W (CRE41.8). -
secSaPermittedWithUnknownW
public static boolean secSaPermittedWithUnknownW(double eadKnown, double eadUnknown) Whether SEC-SA may be used when the delinquency status is unknown for part of the pool: true when unknown EAD / total EAD is at most 5% (CRE41.9). When false the exposure takes 1250% (CRE41.10).- Parameters:
eadKnown- EAD of subpool 1 (W known), at least 0eadUnknown- EAD of subpool 2 (W unknown), at least 0; not both 0- Returns:
- true if SEC-SA is still available
-
kAPartlyUnknownW
public static double kAPartlyUnknownW(double kAKnown, double eadKnown, double eadUnknown) K_A when W is unknown for part of the pool (CRE41.9): K_A = (EAD_known / EAD_total) * K_A^known + EAD_unknown / EAD_total, so the unknown subpool is charged at 100%. K_A^known iskA(double, double)computed on subpool 1 alone.- Parameters:
kAKnown- K_A of subpool 1, in [0, 1]eadKnown- EAD of subpool 1, at least 0eadUnknown- EAD of subpool 2, at least 0; not both 0- Returns:
- the adjusted K_A
- Throws:
IllegalArgumentException- if the unknown share exceeds 5%; CRE41.10 then requires 1250%, which the caller applies
-
juniorUnratedFloor
public static double juniorUnratedFloor(double secSaRiskWeight, double nextSeniorRatedRiskWeight) Second sentence of CRE41.15: an unrated junior tranche in a deal whose more senior tranches are rated, where no rating can be inferred for the junior one, takes no less than the weight of the next more senior rated tranche.- Parameters:
secSaRiskWeight- the junior tranche's SEC-SA weight, a multiplenextSeniorRatedRiskWeight- weight of the next more senior rated tranche, a multiple- Returns:
- max of the two
-
kSsfa
public static double kSsfa(double kA, double attach, double detach, double p) K_SSFA = (e^{a·u} − e^{a·l}) / (a·(u − l)) with a = −1/(p·K_A), u = D − K_A, l = max(A − K_A, 0) (CRE41.11). -
secSaRiskWeight
public static double secSaRiskWeight(double kA, double attach, double detach, boolean resecuritisation, boolean stc, boolean senior) SEC-SA banking-book risk weight as a multiple (CRE41.11 to CRE41.22). p = 1 (CRE41.12), 1.5 for a resecuritisation (CRE41.16(3)), 0.5 for STC (CRE41.21). D ≤ K_A gives 1250% (CRE41.13(1)); A ≥ K_A gives 12.5·K_SSFA (CRE41.13(2)); otherwise the weighted average of CRE41.13(3). Floors: 15% (CRE41.15), 100% for a resecuritisation (CRE41.18), STC 10% senior and 15% non-senior (CRE41.22). For the unknown-W case pass K_A fromkAPartlyUnknownW(double, double, double)(CRE41.9); for an unrated junior tranche applyjuniorUnratedFloor(double, double)(CRE41.15).- Parameters:
kA- K_A fromkA(double, double)attach- A in [0, 1)detach- D in (A, 1]
-
erbaRiskWeight
public static double erbaRiskWeight(FrtbDrcSecuritisation.ErbaRating rating, boolean senior, double thickness, boolean stc) SEC-ERBA banking-book risk weight as a multiple, one-year tranche maturity (MAR22.34(1), so the maturity interpolation of CRE42.5(1) is not needed). Non-senior tranches: table weight × (1 − min(T, 50%)) with T = D − A (CRE42.5(2)), then, outside STC, floored at the senior weight of the same rating (CRE42.7). Floors 15%, or STC 10% senior and 15% non-senior (CRE42.7, CRE42.14).- Parameters:
thickness- T = D − A, ignored for senior tranches
-
byBucket
public static <K> Map<K, List<FrtbDrcSecuritisation.NetJtd>> byBucket(List<FrtbDrcSecuritisation.Position<K>> positions) Groups positions by bucket key in first-seen order. -
hedgeBenefitRatio
HBR = Σ long / (Σ long + Σ |short|), unweighted (MAR22.23); 0 for an empty set. -
nonCtpBucketCharge
Non-CTP bucket charge, max(Σ RW·long − HBR_b·Σ RW·|short|, 0) (MAR22.33). -
nonCtpTotal
Non-CTP total: simple sum of bucket charges (MAR22.35). -
ctpBucketCharge
CTP index-bucket charge with the portfolio-wide HBR_ctp and no floor (MAR22.44): Σ RW·long − HBR_ctp·Σ RW·|short|; may be negative. -
ctpAggregate
-
ctpTotal
Total CTP DRC: one bucket per index, bespokes in the bucket of their index (MAR22.40, MAR22.41); HBR_ctp from all CTP positions together (MAR22.44(1)); aggregated by MAR22.45.
-