GARCH (generalized autoregressive conditional heteroscedasticity) models are widely used in market risk industry to estimate and forecast the volatility of returns. GARCH, including many variants like A-GARCH, GJR-GARCH and E-GARCH, is especially suitable for predicting short and medium term volatility forecasts, since it is based on sound economic model and capable of capturing volatility clustering [Ref. 1].

Matlab and R dominate the skies of market risk [Ref. 2], while SAS is frequently mentioned in the area of credit risk. For univariate volatility modeling of market risk, I personally feel that SAS’s AUTOREG procedure performs better than either the fGarch package in R or the garchset() function in Matlab [Ref. 3], because in my experience it is more robust and code-efficient. The pitfall for SAS to analyze volatility is that it does not have functionality to download financial market data. Fortunately the tseries package from R provides a get.hist.quote() function which obtains data from YAHOO or OANDA [Ref. 4]. In the example below, I embedded the corresponding modules of R into a SAS’s macro getr(), and therefore downloaded and transformed the historical data of S&P 500 adjusted close prices. Then I implemented a GARCH(4,1) model in another univol() macro to estimate and forecast the volatilities until the end of this year. The results suggest that the combination of SAS, R and Excel would be useful to generate and diagnose the desired GARCH model for volatility.

1. Carol Alexander. ‘Market Risk Analysis, Practical Financial Econometrics’. Wiley.
2. Jon Danielsson. ‘Financial Risk Forecasting: The Theory and Practice of Forecasting Market Risk with Implementation in R and Matlab’. Wiley.
3. The AUTOREG procedure. ‘SAS/ETS 9.2 User's Guide’.
4. The get.hist.quote() function.

/*******************READ ME*********************************************
* - Automate univariate volatility modeling by macros -
* SAS VERSION: 9.2.2
* R VERSION: 2.13.0 (library: 'tseries', 'foreign')
* DATE: 08jun2011
* AUTHOR: [email protected]
****************END OF READ ME******************************************/

****************(1) MODULE-BUILDING STEP*******************************;
%macro getr(startday = '01jan2005'd, squote =, filepath =, rpath =);
* MACRO: getr()
* GOAL: download adjusted close prices for specified quote
* and convert them into returns
* PARAMETERS: startday = start day of data to be downloaded
* squote = quote symbol to be downloaded
* filepath = file path for data exchange
* rpath = installation path for R
options mprint mlogic;
data _null_;
day = &startday;
call symput('startdate', %str(put(&startday,yymmdd10.)));
call symput('enddate', %str(put(today(),yymmdd10.)));

proc sql;
create table _tmp0 (string char(800));
insert into _tmp0
values("start='start_date',end='end_date',quote ='AdjClose',quiet=T)")

data _tmp1;
set _tmp0;
string = tranwrd(string, "start_date", "&startdate");
string = tranwrd(string, "end_date", "&enddate");
string = tranwrd(string, "quote_choose", lowcase("&squote"));
string = tranwrd(string, "sas_path", translate("&filepath", "/", "\"));
string = tranwrd(string, "find_result", "&squote");
data _null_;
set _tmp1;
file "&filepath\sas_r.r";
put string;

options xsync xwait;
x "cd &rpath";
x "R.exe CMD BATCH --vanilla --slave &filepath\sas_r.r";
%mend getr;

%macro univol(predday = '31dec2011'd, q = 1, p = 0, filepath =);
* MACRO: univol()
* GOAL: estimate or forcast volatilities by garch(q, p)
* and plot diagnosis
* PARAMETERS: predday = end day for volatility prediction
* q = the subset of ARCH terms to be fitted
* p = the subset of GARCH terms to be fitted
* filepath = file path to exchange data
options mprint mlogic;
data _tmp01;
infile "&filepath\result.csv" delimiter = ',' missover dsd
lrecl=32767 firstobs=2 end = eof;
format date yymmdd10.; informat date yymmdd10.;
format r best32.; informat r best32.;
input date $ r;
if eof then call symput('maxdaygot', date);

data _null_;
format date yymmdd10.;
date = &maxdaygot;
dayinterval = intck('day', date, &predday);
call symput('dayinterval', dayinterval);

%if %eval(&dayinterval) gt 0 %then %do;
data _tmp02(drop=i);
format date yymmdd10.;
date = &maxdaygot;
do i = 1 to &dayinterval;
r = .;
date + 1;
data _tmp01;
set _tmp01 _tmp02;

ods html file = "&filepath\output.xls" gpath = "&filepath\" style = harvest;
title; footnote;
ods graphics on;
ods select standardresidualplot fitplot qqplot residualhistogram acfplot;
proc autoreg data=_tmp01 all plots(unpack);
model r = / noint garch=(q=&q, p=&p);
output out=_tmp02 cev=v;
ods graphics off;
data _tmp03;
set _tmp02;
length type $ 8.;
if r ne . then do;
type = 'estimate'; output; end;
else do;
type = 'forecast'; output; end;

proc print data = _tmp03 noobs;
proc sgplot data=_tmp01;
series y=r x=date /lineattrs=(color=blue);
refline 0/ axis = y lineattrs = (pattern=shortdash);
proc sgplot data=_tmp03;
series x=date y=v/group=type;
refline &maxdaygot/ axis = x lineattrs = (pattern=shortdash);
ods html close;
%mend univol;

****************(2) TESTING STEP****************************************;
%getr(startday = '01jan2005'd, squote = ^gspc, filepath = c:\tmp,
rpath = c:\Program Files\R\R-2.13.0\bin);
%univol(predday = '31dec2011'd, q = 4, p = 1, filepath = c:\tmp);

****************END OF ALL CODING***************************************;