MATLAB Examples

Calculating Regulatory Capital with the ASRF Model

This example shows how to calculate capital requirements and value-at-risk (VaR) for a credit sensitive portfolio of exposures using the asymptotic single risk factor (ASRF) model. This example also shows how to compute Basel capital requirements using an ASRF model.

Contents

The ASRF Model

The ASRF model defines capital as the credit value at risk (VaR) in excess of the expected loss (EL).

$capital = VaR - EL$

where the EL for a given counterparty is the exposure at default (EAD) multiplied by the probability of default (PD).

$EL = EAD * PD * LGD$

To compute the credit VaR, the ASRF model assumes that obligor credit quality is modeled with a latent variable (A) using a one factor model where the single common factor (Z) represents systemic credit risk in the market.

$A_i = w_i \cdot Z + \sqrt{1 - w^2_i} \cdot \epsilon$

Under this model, default losses for a particular scenario are calculated as:

$L = EAD \cdot I \cdot LGD$

where I is the default indicator, and has a value of 1 if $A_i < \Phi^{-1}_A(PD_i)$ (meaning the latent variable has fallen below the threshold for default), and a value of 0 otherwise. The expected value of the default indicator conditional on the common factor is given by:

$E(I_i|Z) = \Phi_{\epsilon}(\frac{\Phi^{-1}_V(PD_i) - w_i Z}{\sqrt{1 - w^2_i}})$

For well diversified and perfectly granular portfolios, the expected loss conditional on a value of the common factor is:

$L|Z = \sum_{i} EAD_i \cdot LGD_i \cdot \Phi_{\epsilon}(\frac{\Phi^{-1}_V(PD_i) - w_i Z}{\sqrt{1 - w^2_i}})$

We can then directly compute particular percentiles of the distribution of losses using the cumulative distribution function of the common factor. This is the credit VaR, which we compute at the $\alpha$ confidence level:

$creditVaR(\alpha) = \sum_{i} EAD_i \cdot LGD_i \cdot \Phi_{\epsilon}(\frac{\Phi^{-1}_V(PD_i) - w_i \Phi^{-1}_Z(1 - \alpha)}{\sqrt{1 - w^2_i}})$

It follows that the capital for a given level of confidence, $\alpha$, is:

$capital(\alpha) = \sum_{i} EAD_i \cdot LGD_i \cdot [\Phi_{\epsilon}(\frac{\Phi^{-1}_V(PD_i) - w_i \Phi^{-1}_Z(1 - \alpha)}{\sqrt{1 - w^2_i}}) - PD_i]$

Basic ASRF

The portfolio contains 100 credit sensitive contracts and information about their exposure. This is simulated data.

load asrfPortfolio.mat

disp(portfolio(1:5,:))
    ID       EAD           PD        LGD     AssetClass    Sales          Maturity      
    __    __________    _________    ____    __________    _____    ____________________

    1      2.945e+05     0.013644     0.5    "Bank"        NaN      02-Jun-2023 00:00:00
    2     1.3349e+05    0.0017519     0.5    "Bank"        NaN      05-Jul-2021 00:00:00
    3     3.1723e+05      0.01694     0.4    "Bank"        NaN      07-Oct-2018 00:00:00
    4     2.8719e+05     0.013624    0.35    "Bank"        NaN      27-Apr-2022 00:00:00
    5     2.9965e+05     0.013191    0.45    "Bank"        NaN      07-Dec-2022 00:00:00

The weights (w) in the ASRF model define the correlation between the counterparty's latent variable (A) and the systemic credit factor (Z). Weights can be calibrated by observing correlations in the market or from historical default data. The weights can also be determined using regulatory guidelines (see Basel Capital Requirements section).

Because the ASRF model is a fast, analytical formula, it is convenient to perform sensitivity analysis for a counterparty by varying the exposure parameters and observing how the capital and VaR change.

The following plot shows the sensitivity to PD and Weights (correlation). The LGD and EAD parameters are scaling factors in the ASRF formula so the sensitivity is straightforward.

% Counterparty ID
id = 1;

% Set default weight (correlation) to 0.2 as baseline
W = 0.2;

% Compute baseline capital and VaR
[capital0, var0] = asrf(portfolio.PD(id),portfolio.LGD(id),W,'EAD',portfolio.EAD(id));
% Stressed PD by 50%
[capital1, var1] = asrf(portfolio.PD(id) * 1.5,portfolio.LGD(id),W,'EAD',portfolio.EAD(id));
% Stressed Weight/Correlation by 50%
[capital2, var2] = asrf(portfolio.PD(id),portfolio.LGD(id),W * 1.5,'EAD',portfolio.EAD(id));

c = categorical({'ASRF Capital','VaR'});
bar(c,[capital0 capital1 capital2; var0 var1 var2]);
legend({'baseline','stressed PD','stressed Weight'},'Location','northwest')
title(sprintf('ID: %d, Baseline vs. Stressed Scenarios',id));
ylabel('USD ($)');

Basel Capital Requirements

When computing regulatory capital, the Basel documents have additional model specifications on top of the basic ASRF model. In particular, Basel II defines specific formulas for computing the weights for exposures in various assets classes as a function of the default probability.

To set up the vector of weights according to the definitions established in Basel II/III:

Weights = zeros(height(portfolio),1);

% Compute weights for corporate, sovereign, and bank exposures
idx = portfolio.AssetClass == "Corporate" |...
    portfolio.AssetClass == "Sovereign" |...
    portfolio.AssetClass == "Bank";

Weights(idx) = 0.12 * (1-exp(-50*portfolio.PD(idx))) / (1-exp(-50)) +...
    0.24 * (1 - (1-exp(-50*portfolio.PD(idx))) / (1-exp(-50)));

% Compute weights for small and medium entities
idx = portfolio.AssetClass == "Small Entity" |...
    portfolio.AssetClass == "Medium Entity";

Weights(idx) = 0.12 * (1-exp(-50*portfolio.PD(idx))) / (1-exp(-50)) +...
    0.24 * (1 - (1-exp(-50*portfolio.PD(idx))) / (1-exp(-50))) -...
    0.04 * (1 - (portfolio.Sales(idx)/1e6 - 5) / 45);

% Compute weights for unregulated finantial institutions with assets
% greater than $100B.
idx = portfolio.AssetClass == "Unregulated Financial";

Weights(idx) = 1.25 * 0.12 * (1-exp(-50*portfolio.PD(idx))) / (1-exp(-50)) +...
    0.24 * (1 - (1-exp(-50*portfolio.PD(idx))) / (1-exp(-50)));

Find the basic ASRF capital using the Basel-defined weights. The default value for the VaR level is 99.9%.

asrfCapital = asrf(portfolio.PD,portfolio.LGD,Weights,'EAD',portfolio.EAD);

Additionally, the Basel documents specify a maturity adjustment to be added to each capital calculation. Here we compute the maturity adjustment and update the capital requirements.

maturityYears = years(portfolio.Maturity - settle);

b = (0.11852 - 0.05478 * log(portfolio.PD)).^2;
maturityAdj = (1 + (maturityYears - 2.5) .* b)  ./ (1 - 1.5 .* b);

regulatoryCapital = asrfCapital .* maturityAdj;

fprintf('Portfolio Regulatory Capital : $%.2f\n',sum(regulatoryCapital));
Portfolio Regulatory Capital : $515452.71

Risk weighted assets (RWA) are calculated as capital * 12.5.

RWA = regulatoryCapital * 12.5;

results = table(portfolio.ID,portfolio.AssetClass,RWA,regulatoryCapital,'VariableNames',...
    {'ID','AssetClass','RWA','Capital'});

% Results table
disp(results(1:5,:))
    ID    AssetClass       RWA        Capital
    __    __________    __________    _______

    1     "Bank"        1.0698e+05    8558.8 
    2     "Bank"             16116    1289.3 
    3     "Bank"             59246    4739.7 
    4     "Bank"             65957    5276.6 
    5     "Bank"             92962      7437 

Aggregate the regulatory capital by asset class.

assetClasses = unique(results.AssetClass);
assetClassCapital = zeros(numel(assetClasses),1);
for i = 1:numel(assetClasses)
    assetClassCapital(i) = sum(results.Capital(results.AssetClass == assetClasses(i)));
end
pie(assetClassCapital,cellstr(assetClasses))
title('Regulatory Capital by Asset Class');

capitalTable = table(assetClasses, assetClassCapital,'VariableNames',{'AssetClass','Capital'});
disp(capitalTable);
          AssetClass            Capital  
    _______________________    __________

    "Bank"                          82309
    "Corporate"                     79512
    "Medium Entity"                 67399
    "Small Entity"                  35938
    "Sovereign"                1.5342e+05
    "Unregulated Financial"         96875