Test A-IRB approach for credit rating
Basel II or Basel III framework would allow qualified financial institutions to apply their own rating systems for credit risks, such as advanced internal ratings-based approach (A-IRB). The equations of required capital play a big role in it. With full-fledging facility of SAS, an automatic selection system can be built by its’ macros, SQL syntax and function complier. I just ran a simple experiment based on a standard seven-level grading system, toward a data set with a varying PD and the fixed EAD, LGD and maturity.
First 1000 rating structures were simulated. SAS’s seeds are used to memorize the structures (Liang has an interesting post regarding the “seed trap” question.).
%macro structgen(data = , var = , out = ); proc sql noprint; create table &out(y num, seed num, step num); quit; %do i = 1 %to 1000; data _tmp1; set &data; retain y 0; y = y + ranuni(&i)*(&var-y); seed = &i; step = _n_ ; run; proc sql noprint; insert into &out select y, seed, step from _tmp1; quit; %end; %mend; %structgen(data = maxbound, var = maxvalue, out = final); proc sgplot data = final; series x = step y = y / group = seed; yaxis label = 'Percentage'; xaxis grid; run;
Second, for each of the rating structure, GINI and required capital were calculated. The min value of required capital turned out to be 0.069, while the max value of GINI is 0.749.
%macro grdselect(lgd = 0.45, ead = 100, m = 2.5, out = want); proc sql noprint; select mean(pd)/100 into: avgpd from pd ; select count(pd) into: nobs from pd ; create table &out(structure char(50), gini num, cr num) ; quit; %do i = 1 %to 1000; data bound; set final; lowbound = y / 100; where seed = &i; run; data _myfmt; merge bound(rename=(lowbound=start)) bound(rename=(lowbound=end) firstobs=2); fmtname = 'range'; type = 'n'; label = _n_; if end = . then end = 1; run; proc format cntlin = _myfmt; run; data _1; set pd; pd = pd / 100; grade = put(pd, range.); cr = reqcap(pd, &lgd, &m); run; proc sql noprint; select lowbound format=percent8.2 into: structure separated by '-' from bound ; create table _2 as select grade, count(grade) / &nobs as ps 'share of portfolio', mean(pd) as gpd 'grade pd', calculated ps * calculated gpd / &avgpd as esod 'expected share of default', reqcap(calculated gpd, &lgd, &m) as gcr 'grade cr' from _1 group by grade ; quit; proc sort data = _2; by descending grade; run; data _3; set _2; retain _y 0; _y + esod; _x = _y - esod; label egc = 'Expected GINI values'; egc = ps * (_x + esod/2); run; proc sql noprint; select (sum(egc)-0.5) / ((&avgpd/2+(1-&avgpd))-0.5) into: gini from _3 ; select sum(&ead*gcr)/sum(ead) into: cr from (select a.*, b.gcr from _1 as a left join _3 as b on a.grade = b.grade) ; insert into &out values ("&structure", &gini, &cr) ; quit; %end; %mend; %grdselect; proc sgplot data = want; series x = seed y = cr; series x = seed y = gini / y2axis; run;
1. The optimal rating structure depends on multiple factors, including accuracy ratio and required capital which I used in this test. Business decision would make significant difference, while an integrated evaluation index may need more modeling work.
2. To save time from the high I/O operations involved with lots of loops, such as simulation, back testing, stress testing, etc., try to decrease the steps to write data to the hard disk. Memory-intensive PROC SQL or PROC IML sometimes is a more efficient way than the DATA step. Also avoid %IF-%THEN statement inside of a macro loop (some interesting discussions similar to this topic: Rick’s post here and my post here).