Documentation

Modeling Correlated Defaults with Copulas

This example explores how to simulate correlated counterparty defaults using a multifactor copula model.

Potential losses are estimated for a portfolio of counterparties, given their exposure at default, default probability, and loss given default information. A creditDefaultCopula object is used to model each obligor's credit worthiness with latent variables. Latent variables are composed of a series of weighted underlying credit factors, as well as, each obligor's idiosyncratic credit factor. The latent variables are mapped to an obligor's default or nondefault state for each scenario based on their probability of default. Portfolio risk measures, risk contributions at a counterparty level, and simulation convergence information are supported in the creditDefaultCopula object.

This example also explores the sensitivity of the risk measures to the type of copula (Gaussian copula versus t copula) used for the simulation.

Load and Examine Portfolio Data

The portfolio contains 100 counterparties and their associated credit exposures at default (EAD), probability of default (PD), and loss given default (LGD). Using a creditDefaultCopula object, you can simulate defaults and losses over some fixed time period (for example, one year). The EAD, PD, and LGD inputs must be specific to a particular time horizon.

In this example, each counterparty is mapped onto two underlying credit factors with a set of weights. The Weights2F variable is a NumCounterparties-by-3 matrix, where each row contains the weights for a single counterparty. The first two columns are the weights for the two credit factors and the last column is the idiosyncratic weights for each counterparty. A correlation matrix for the two underlying factors is also provided in this example (FactorCorr2F).

whos EAD PD LGD Weights2F FactorCorr2F
Name                Size            Bytes  Class     Attributes

EAD               100x1               800  double
FactorCorr2F        2x2                32  double
LGD               100x1               800  double
PD                100x1               800  double
Weights2F         100x3              2400  double

Initialize the creditDefaultCopula object with the portfolio information and the factor correlation.

rng('default');

% Change the VaR level to 99%.
cc.VaRLevel = 0.99;

disp(cc)
creditDefaultCopula with properties:

Portfolio: [100x5 table]
FactorCorrelation: [2x2 double]
VaRLevel: 0.9900
UseParallel: 0
PortfolioLosses: []

cc.Portfolio(1:5,:)
ans =

5x5 table

ID     EAD         PD        LGD           Weights
__    ______    _________    ____    ____________________

1     21.627    0.0050092    0.35    0.35       0    0.65
2     3.2595     0.060185    0.35       0    0.45    0.55
3     20.391      0.11015    0.55    0.15       0    0.85
4     3.7534    0.0020125    0.35    0.25       0    0.75
5     5.7193     0.060185    0.35    0.35       0    0.65

Simulate the Model and Plot Potential Losses

Simulate the multifactor model using the simulate function. By default, a Gaussian copula is used. This function internally maps realized latent variables to default states and computes the corresponding losses. After the simulation, the creditDefaultCopula object populates the PortfolioLosses and CounterpartyLosses properties with the simulation results.

cc = simulate(cc,1e5);
disp(cc)
creditDefaultCopula with properties:

Portfolio: [100x5 table]
FactorCorrelation: [2x2 double]
VaRLevel: 0.9900
UseParallel: 0
PortfolioLosses: [1x100000 double]

The portfolioRisk function returns risk measures for the total portfolio loss distribution, and optionally, their respective confidence intervals. The value-at-risk (VaR) and conditional value-at-risk (CVaR) are reported at the level set in the VaRLevel property for the creditDefaultCopula object.

[pr,pr_ci] = portfolioRisk(cc);

fprintf('Portfolio risk measures:\n');
disp(pr)

fprintf('\n\nConfidence intervals for the risk measures:\n');
disp(pr_ci)
Portfolio risk measures:
EL       Std       VaR       CVaR
______    ______    ______    ______

24.774    23.693    101.57    120.22

Confidence intervals for the risk measures:
EL                 Std                 VaR                CVaR
________________    ________________    ________________    _______________

24.627     24.92    23.589    23.797    100.65    102.82    119.1    121.35

Look at the distribution of portfolio losses. The expected loss (EL), VaR, and CVaR are marked as the vertical lines. The economic capital, given by the difference between the VaR and the EL, is shown as the shaded area between the EL and the VaR.

histogram(cc.PortfolioLosses)
title('Portfolio Losses');
xlabel('Losses (\$)')
ylabel('Frequency')
hold on

% Overlay the risk measures on the histogram.
xlim([0 1.1 * pr.CVaR])
plotline = @(x,color) plot([x x],ylim,'LineWidth',2,'Color',color);
plotline(pr.EL,'b');
plotline(pr.VaR,'r');
cvarline = plotline(pr.CVaR,'m');

% Shade the areas of expected loss and economic capital.
plotband = @(x,color) patch([x fliplr(x)],[0 0 repmat(max(ylim),1,2)],...
color,'FaceAlpha',0.15);
elband = plotband([0 pr.EL],'blue');
ulband = plotband([pr.EL pr.VaR],'red');
legend([elband,ulband,cvarline],...
{'Expected Loss','Economic Capital','CVaR (99%)'},...
'Location','north'); Find Concentration Risk for Counterparties

Find the concentration risk in the portfolio using the riskContribution function. riskContribution returns the contribution of each counterparty to the portfolio EL and CVaR. These additive contributions sum to the corresponding total portfolio risk measure.

rc = riskContribution(cc);

% Risk contributions are reported for EL and CVaR.
rc(1:5,:)
ans =

5x5 table

ID       EL           Std          VaR        CVaR
__    _________    __________    _______    _________

1      0.038604       0.02495    0.10482      0.12868
2      0.067068      0.036472    0.17378      0.24527
3        1.2527       0.62684     2.0384       2.3103
4     0.0023253    0.00073407          0    0.0026274
5       0.11766      0.042185    0.27028      0.26223

Find the riskiest counterparties by their CVaR contributions.

[rc_sorted,idx] = sortrows(rc,'CVaR','descend');
rc_sorted(1:5,:)
ans =

5x5 table

ID      EL        Std       VaR       CVaR
__    _______    ______    ______    ______

89      2.261    2.2158    8.1095    9.2257
22     1.5672    1.8293     6.275    7.4602
66    0.85227    1.4063    6.3827    7.2691
16     1.6236    1.5011    5.8949    7.1083
96     1.3331    1.6339    7.3678    6.9669

Plot the counterparty exposures and CVaR contributions. The counterparties with the highest CVaR contributions are plotted in red and orange.

figure;
pointSize = 50;
colorVector = rc_sorted.CVaR;
pointSize,colorVector,'filled')
colormap('jet')
title('CVaR Contribution vs. Exposure')
xlabel('Exposure')
ylabel('CVaR Contribution')
grid on Investigate Simulation Convergence with Confidence Bands

Use the confidenceBands function to investigate the convergence of the simulation. By default, the CVaR confidence bands are reported, but confidence bands for all risk measures are supported using the optional RiskMeasure argument.

cb = confidenceBands(cc);

% The confidence bands are stored in a table.
cb(1:5,:)
ans =

5x4 table

NumScenarios    Lower      CVaR     Upper
____________    ______    ______    ______

1000        113.92    124.76    135.59
2000        111.02    117.74    124.45
3000        113.58    118.97    124.36
4000        113.06    117.44    121.81
5000        114.38    118.99     123.6

Plot the confidence bands to see how quickly the estimates converge.

figure;
plot(...
cb.NumScenarios,...
cb{:,{'Upper' 'CVaR' 'Lower'}},...
'LineWidth',2);

title('CVaR: 95% Confidence Interval vs. # of Scenarios');
xlabel('# of Scenarios');
ylabel('CVaR + 95% CI')
legend('Upper Band','CVaR','Lower Band');
grid on Find the necessary number of scenarios to achieve a particular width of the confidence bands.

width = (cb.Upper - cb.Lower) ./ cb.CVaR;

figure;
plot(cb.NumScenarios,width * 100,'LineWidth',2);
title('CVaR: 95% Confidence Interval Width vs. # of Scenarios');
xlabel('# of Scenarios');
ylabel('Width of CI as %ile of Value')
grid on

% Find point at which the confidence bands are within 1% (two sided) of the
% CVaR.
thresh = 0.02;

scenIdx = find(width <= thresh,1,'first');
scenValue = cb.NumScenarios(scenIdx);
widthValue = width(scenIdx);
hold on
plot(xlim,100 * [widthValue widthValue],...
[scenValue scenValue], ylim,...
'LineWidth',2);
title('Scenarios Required for Confidence Interval with 2% Width'); Compare Tail Risk for Gaussian and t Copulas

Switching to a t copula increases the default correlation between counterparties. This results in a fatter tail distribution of portfolio losses, and in higher potential losses in stressed scenarios.

Rerun the simulation using a t copula and compute the new portfolio risk measures. The default degrees of freedom (dof) for the t copula is five.

cc_t = simulate(cc,1e5,'Copula','t');
pr_t = portfolioRisk(cc_t);

See how the portfolio risk changes with the t copula.

fprintf('Portfolio risk with Gaussian copula:\n');
disp(pr)

fprintf('\n\nPortfolio risk with t copula (dof = 5):\n');
disp(pr_t)
Portfolio risk with Gaussian copula:
EL       Std       VaR       CVaR
______    ______    ______    ______

24.774    23.693    101.57    120.22

Portfolio risk with t copula (dof = 5):
EL       Std       VaR       CVaR
______    ______    ______    ______

24.924    38.982    186.33    251.38

Compare the tail losses of each model.

% Plot the Gaussian copula tail.
figure;
subplot(2,1,1)
p1 = histogram(cc.PortfolioLosses);
hold on
plotline(pr.VaR,[1 0.5 0.5])
plotline(pr.CVaR,[1 0 0])
xlim([0.8 * pr.VaR  1.2 * pr_t.CVaR]);
ylim([0 1000]);
grid on
legend('Loss Distribution','VaR','CVaR')
title('Portfolio Losses with Gaussian Copula');
xlabel('Losses (\$)');
ylabel('Frequency');

% Plot the t copula tail.
subplot(2,1,2)
p2 = histogram(cc_t.PortfolioLosses);
hold on
plotline(pr_t.VaR,[1 0.5 0.5])
plotline(pr_t.CVaR,[1 0 0])
xlim([0.8 * pr.VaR  1.2 * pr_t.CVaR]);
ylim([0 1000]);
grid on
legend('Loss Distribution','VaR','CVaR');
title('Portfolio Losses with t Copula (dof = 5)');
xlabel('Losses (\$)');
ylabel('Frequency'); The tail risk measures VaR and CVaR are significantly higher using the t copula with five degrees of freedom. The default correlations are higher with t copulas, therefore there are more scenarios where multiple counterparties default. The number of degrees of freedom plays a significant role. For very high degrees of freedom, the results with the t copula are similar to the results with the Gaussian copula. Five is a very low number of degrees of freedom and, consequentially, the results show striking differences. Furthermore, these results highlight that the potential for extreme losses are very sensitive to the choice of copula and the number of degrees of freedom.