SAS Documentation
SASĀ® Solution for Stress Testing
Reference manual - version 08.2021
Loading...
Searching...
No Matches
irmst_script_riskagg_linear.sas
1/* ************************************************** *
2 * Risk Linear Aggregation *
3 * ************************************************** */
4
5%let lin_correlation_key = ${params.CORRMATRIX.key};
6${function:ProcessSpreadsheetParameter(params.CORRMAP, "corr_map_Data")}
7
8/*Give a valid path to a temporary folder if you need to save temporary results for debugging purposes.*/
9%let dubug_libname_path=${params.TESTINGDEBUG};
10%let out_libref = work;
11%macro setup_debug_libref;
12 %if %sysevalf(%bquote(&dubug_libname_path.) ne %str(), boolean) %then %do;
13 /*If the debugging folder does not exist, try to create one.*/
14 %if %rsk_dir_exists(DIR=&dubug_libname_path.)=0 %then %do;
15 %put NOTE: Trying to create debug directory &dubug_libname_path.;
16 %rsk_mkdirs(DIR=&dubug_libname_path.);
17 %end;
18 %if %rsk_dir_exists(DIR=&dubug_libname_path.)=0 %then %do;
19 %put ERROR: unable to create the directory &dubug_libname_path.;
20 %end;
21 %else %do;
22 %let out_libref = _debug;
23 libname _debug "&dubug_libname_path.";
24 %end;
25 %end;
26%mend;
27
28%setup_debug_libref;
29
30%macro irmst_riskagg_linear_run;
31 %local _scenario_ids_
32 i_scenario_ids
33 _corrtypes_
34 ;
35
36
37 /*Retrieve the basecase scenario*/
38 %let ticket =;
39 %irm_rest_get_rgf_mrs(host = &rgf_protocol.://&rgf_host.
40 , server = &rgf_service.
41 , solution = &rgf_solution.
42 , port = &rgf_port.
43 , tgt_ticket = &tgt_ticket.
44 , key = &basecase_scenario.
45 , details_flg = Y
46 , outds = &out_libref..basecase_scenario_data
47 , outVarTicket = ticket
48 , outSuccess = httpSuccess
49 , outResponseStatus = responseStatus
50 , restartLUA = Y
51 , clearCache = Y
52 );
53
54 /*Retrieve the adverse scenario*/
55 %let ticket =;
56 %irm_rest_get_rgf_mrs(host = &rgf_protocol.://&rgf_host.
57 , server = &rgf_service.
58 , solution = &rgf_solution.
59 , port = &rgf_port.
60 , tgt_ticket = &tgt_ticket.
61 , key = &adverse_scenario.
62 , details_flg = Y
63 , outds = &out_libref..adverse_scenario_data
64 , outVarTicket = ticket
65 , outSuccess = httpSuccess
66 , outResponseStatus = responseStatus
67 , restartLUA = Y
68 , clearCache = Y
69 );
70
71 proc sql noprint;
72 select min(mrsShortName), min(periodType), forecastTime, count(forecastTime) into :basecase_scenario_name, :basecase_period_type, :basecase_ft_list separated by " ", :cnt_basecase_ft_list
73 from &out_libref..basecase_scenario_data;
74 select min(mrsShortName), min(periodType), forecastTime, count(forecastTime) into :adverse_scenario_name, :adverse_period_type, :adverse_ft_list separated by " ", :cnt_adverse_ft_list
75 from &out_libref..adverse_scenario_data;
76 quit;
77
78 %if &cnt_basecase_ft_list. NE &cnt_adverse_ft_list. %then %do;
79 %put ERROR: The number of forecastTime in the Basecase scenario does not match the number of forecastTime in the Adverse scenario.;
80 %abort cancel;
81 %end;
82
83 %let check=0;
84 %do i_basecase_ft=1 %to &cnt_basecase_ft_list.;
85 %let basecase_element=%scan(&basecase_ft_list.,&i_basecase_ft.,%str( ));
86 %do i_adverse_ft=1 %to &cnt_adverse_ft_list.;
87 %let adverse_element=%scan(&adverse_ft_list.,&i_adverse_ft.,%str( ));
88 %if &basecase_element.=&adverse_element. %then %do;
89 %let check=%eval(&check.+1);
90 %*put &=check;
91 %end;
92 %end;
93 %end;
94
95 %if &check NE &cnt_basecase_ft_list. %then %do;
96 %put ERROR: The list of forecastTime in the Basecase scenario does not match the list of forecastTime in the Adverse scenario.;
97 %abort cancel;
98 %end;
99
100 /*-----------------------------------------------------*/
101 /*Retrieve the configuration for the linear aggregation*/
102 /*-----------------------------------------------------*/
103 data &out_libref..enhanced_corr_map_Data;
104 set corr_map_Data;
105 lossKey = prxchange('s/.+"key":(\d+).*/$1/', 1,ldSumm);
106 run;
107
108 proc sql noprint;
109 select count(lossKey), lossKey, corrVarValue into :cnt_lossKey_list, :lossKey_list separated by " ", :corrVarValue_list separated by " "
110 from &out_libref..enhanced_corr_map_Data(where=(ldSumm ne ""));
111 select count(corrVarValue), corrVarValue into :cnt_miss_corrVarValue, :miss_corrVarValue separated by " "
112 from &out_libref..enhanced_corr_map_Data(where=(ldSumm = ""));
113 quit;
114
115 /*loop over the loss distribution summary table selected in the spreadsheet parameter*/
116 %do i_lossKey=1 %to &cnt_lossKey_list.;
117 %let ld_summ_key = %scan(&lossKey_list.,&i_lossKey.,%str( ));
118 %let httpSuccess = 0;
119 %let responseStatus = ;
120 %irm_rgf_retrieve_analysis_data(key = &ld_summ_key.
121 , libref = &out_libref.
122 , outds = &out_libref..loss_dist_sum_&i_lossKey.
123 , host = &rgf_protocol.://&rgf_host.
124 , server = &rgf_service.
125 , solution = rmc
126 , port = &rgf_port.
127 , outSuccess = httpSuccess
128 , outResponseStatus = responseStatus
129 , restartLUA = Y
130 , clearCache = Y
131 );
132 %if(not &httpSuccess.) %then %do;
133 %put ERROR: Unable to load the loss distribution associated with key &ld_summ_key..;
134 %abort cancel;
135 %end;
136
137 data _NULL_;
138 set &out_libref..loss_dist_sum_&i_lossKey.;
139 retain temp_alpha .;
140 if ((_N_>1) and (temp_alpha NE VALUEATRISK_ALPHA)) then do;
141 put "ERROR: VALUEATRISK_ALPHA must be unique in the loss distribution associated with key &ld_summ_key.";
142 call symput("httpSuccess", 0);
143 end;
144 temp_alpha=VALUEATRISK_ALPHA;
145 if VALUEATRISK_ALPHA=. then do;
146 put "ERROR: VALUEATRISK_ALPHA cannot be missing in the loss distribution associated with key &ld_summ_key.";
147 call symput("httpSuccess", 0);
148 end;
149 if VALUEATRISK=. then do;
150 put "ERROR: VALUEATRISK cannot be missing in the loss distribution associated with key &ld_summ_key.";
151 call symput("httpSuccess", 0);
152 end;
153 if EXPECTEDLOSS=. then do;
154 put "ERROR: EXPECTEDLOSS cannot be missing in the loss distribution associated with key &ld_summ_key.";
155 call symput("httpSuccess", 0);
156 end;
157 run;
158
159 %if(not &httpSuccess.) %then %do;
160 %abort cancel;
161 %end;
162 %end;
163
164 /*combine all the loss distribution summary tables and make necessary modifications. */
165 data &out_libref..RISKAGG_LINEAR_CONFIG;
166 length name $32. RISK_TYPE $32.;
167 %do i_lossKey=1 %to &cnt_lossKey_list.;
168 set &out_libref..loss_dist_sum_&i_lossKey.;
169 name="%scan(&corrVarValue_list.,&i_lossKey.,%str( ))";
170 /*The value of the economic capital can always be derived from the from expected loss and Value at Risk.
171 For this reason, the user does not always havae to specify it. The next 3 lines of code make sure that this value is always reported.*/
172 if EXPECTEDLOSS <0 then ECONOMIC_CAPITAL=VALUEATRISK;
173 else ECONOMIC_CAPITAL=VALUEATRISK-EXPECTEDLOSS ;
174 if ECONOMIC_CAPITAL<0 then ECONOMIC_CAPITAL=0;
175 output;
176 %end;
177 run;
178
179
180 /*It removes the BEP name from the scenario_id*/
181 data &out_libref..RISKAGG_LINEAR_CONFIG;
182 set &out_libref..RISKAGG_LINEAR_CONFIG;
183 REPORTING_DT=input("&base_dt.",yymmdd10.);
184 select;
185 when (find(scenario_id, catx("_","&basecase_scenario_name.","FT"), 1)>0) do;
186 p=find(scenario_id, catx("_","&basecase_scenario_name.","FT"), 1);
187 scenario_id=substr(scenario_id,p);
188 end;
189 when (find(scenario_id, catx("_","&adverse_scenario_name.","FT"), 1)>0) do;
190 p=find(scenario_id, catx("_","&adverse_scenario_name.","FT"), 1);
191 scenario_id=substr(scenario_id,p);
192 end;
193 otherwise;
194 end;
195 run;
196
197 /*--------------------------------------------------------------*/
198 /*Retrieve the correlation matrix for for the linear aggregation*/
199 /*--------------------------------------------------------------*/
200 %let httpSuccess = 0;
201 %let responseStatus = ;
202 %irm_rgf_retrieve_analysis_data(key = &lin_correlation_key.
203 , libref = &out_libref.
204 , outds = &out_libref..RISKAGG_LINEAR_CORR_UNSTRCTD
205 , host = &rgf_protocol.://&rgf_host.
206 , server = &rgf_service.
207 , solution = rmc
208 , port = &rgf_port.
209 , outSuccess = httpSuccess
210 , outResponseStatus = responseStatus
211 , restartLUA = Y
212 , clearCache = Y
213 );
214 %if(not &httpSuccess.) %then %do;
215 %put ERROR: Unable to retrive the correlation matrix associated with key &lin_correlation_key.;
216 %abort cancel;
217 %end;
218
219/*If the user does not map the full correlation matrix, we can still run the aggregation without the unspecified element.*/
220data &out_libref..RISKAGG_LINEAR_CORR_ACTUAL;
221 set &out_libref..RISKAGG_LINEAR_CORR_UNSTRCTD;
222 %do i_miss_corrVarValue=1 %to &cnt_miss_corrVarValue.;
223 if ((_PARM1_ = "%scan(&miss_corrVarValue.,&i_miss_corrVarValue.,%str( ))") or (_PARM2_ = "%scan(&miss_corrVarValue.,&i_miss_corrVarValue.,%str( ))" )) then do;
224 put "WARNING: The partition of the correlation matrix associated with %scan(&miss_corrVarValue.,&i_miss_corrVarValue.,%str( )) has been removed because no loss distribution has been selected";
225 end;
226 else do;
227 output;
228 end;
229 %end;
230run;
231
232 %irmst_riskagg_corr_mat_check(ds_in_corr_mat=&out_libref..RISKAGG_LINEAR_CORR_ACTUAL);
233
234 /*--------------------------------------------------------------*/
235 /*Restructure the correlation matrix. For example
236
237 | Correlation Identifier | Correlation Measurement |
238 |-----------------------------|--------------------------|
239 | Corr(item1,item2) | num1 |
240 | Corr(item1,item3) | num2 |
241 | Corr(item2,item3) | num3 |
242
243 is equivalent to the following 3*3 structured correlation matrix
244
245 | | item1 | item2 | item3 |
246 |-------|-------|-------|-------|
247 | item1 | 1 | num1 | num2 |
248 | item2 | num1 | 1 | num3 |
249 | item3 | num2 | num3 | 1 |
250 /*--------------------------------------------------------------*/
251 %irmc_riskagg_corr_mat_parser( ds_in_corr_matrix = &out_libref..RISKAGG_LINEAR_CORR_ACTUAL
252 , working_libname = &out_libref.
253 , ds_out_matrix = &out_libref..RISKAGG_LINEAR_CORR_ORIG
254 );
255
256 /*remap the scenario id and duplicate the entries for the forecastTime*/
257 data &out_libref..RISKAGG_LINEAR_CORR;
258 set &out_libref..RISKAGG_LINEAR_CORR_ORIG;
259 if upcase(SCENARIO_ID)="ADVERSE" then do;
260 %do i_adverse_ft=1 %to &cnt_adverse_ft_list.;
261 %let adverse_element=%scan(&adverse_ft_list.,&i_adverse_ft.,%str( ));
262 SCENARIO_ID=catx("_","&adverse_scenario_name.","FT&adverse_element.");
263 output;
264 %end;
265 end;
266 if upcase(SCENARIO_ID)="BASECASE" then do;
267 %do i_basecase_ft=1 %to &cnt_basecase_ft_list.;
268 %let basecase_element=%scan(&basecase_ft_list.,&i_basecase_ft.,%str( ));
269 SCENARIO_ID=catx("_","&basecase_scenario_name.","FT&basecase_element.");
270 output;
271 %end;
272 end;
273 run;
274
275 /*this sorting step is probably not needed, but given the relativly small size of a typical correlation matrix
276 this could become useful when debugging.*/
277 proc sort data=&out_libref..RISKAGG_LINEAR_CORR;
278 by SCENARIO_ID;
279 run;
280
281 /*--------------------------------------------------------------*/
282 /* Perform the linear aggregation */
283 /*--------------------------------------------------------------*/
284 %irmst_riskagg_linear( ds_in_configuration_table = &out_libref..RISKAGG_LINEAR_CONFIG
285 , ds_in_correlation_table = &out_libref..RISKAGG_LINEAR_CORR
286 , working_libname = &out_libref.
287 , ds_out_risk_analysis_table = &out_libref..RISKAGG_SUMMARY_RESULTS
288 );
289
290
291 /* Get information from the cycle */
292 %let ticket =;
293 %let httpSuccess = 0;
294 %let responseStatus =;
295 %irm_rest_get_rgf_cycle(key = &cycle_key.
296 , host = &rgf_protocol://&rgf_host.
297 , port = &rgf_port.
298 , tgt_ticket = &tgt_ticket.
299 , outds = cycle_info
300 , outVarTicket = ticket
301 , outSuccess = httpSuccess
302 , outResponseStatus = responseStatus
303 );
304 data _null_;
305 set cycle_info;
306 call symputx("cycle_baseDt", baseDt, "L");
307 call symputx("cycle_entityId", entityId, "L");
308 run;
309
310 data RISKAGG_SUMMARY_RESULTS;
311 length scenario_type $32;
312 set &out_libref..RISKAGG_SUMMARY_RESULTS;
313 %do i_adverse_ft=1 %to &cnt_adverse_ft_list.;
314 %let adverse_element=%scan(&adverse_ft_list.,&i_adverse_ft.,%str( ));
315 if SCENARIO_ID=catx("_",strip("&adverse_scenario_name."),"FT&adverse_element.") then
316 do;
317 SCENARIO_NAME=strip("&adverse_scenario_name.");
318 SCENARIO_TYPE='Adverse';
319 FORECAST_PERIOD="&adverse_period_type.";
320 FORECAST_TIME=&adverse_element.;
321 end;
322 %end;
323 %do i_basecase_ft=1 %to &cnt_basecase_ft_list.;
324 %let basecase_element=%scan(&basecase_ft_list.,&i_basecase_ft.,%str( ));
325 if SCENARIO_ID=catx("_",strip("&basecase_scenario_name."),"FT&basecase_element.") then
326 do;
327 SCENARIO_NAME=strip("&basecase_scenario_name.");
328 SCENARIO_TYPE='Basecase';
329 FORECAST_PERIOD="&basecase_period_type.";
330 FORECAST_TIME=&basecase_element.;
331 end;
332 %end;
333 run;
334
335%mend;
336%irmst_riskagg_linear_run;