I can calculate the motion of heavenly bodies but not the madness of people. -Isaac Newton

## A SAS Macro Implementing Bi-variate Granger Causality Test

In loss forecasting, it is often of the interest to know: 1) if a time series, e.g. macro-economic variables, is useful to predict another, e.g. portfolio loss; 2) the number of lags to contribute such predictive power. Granger (1969) proposed that A time series X is said to Granger-cause Y if lagged values of X are able to provide statistically significant information to predict the future values of Y.

A SAS macro below is showing how to implement Granger Causality test in a bi-variate sense.

```%macro causal(data = , y = , drivers = , max_lags = );
***********************************************************;
* THIS SAS MACRO IS AN IMPLEMENTATION OF BI-VARIATE       *;
* GRANGER CAUSALITY TEST PROPOSED BY GRANGER (1969)       *;
* ======================================================= *;
* PAMAMETERS:                                             *;
*  DATA     : INPUT SAS DATA TABLE                        *;
*  Y        : A CONTINUOUS TIME SERIES RESPONSE VARIABLE  *;
*  DRIVERS  : A LIST OF TIME SERIES PREDICTORS            *;
*  MAX_LAGS : MAX # OF LAGS TO SEARCH FOR CAUSAL          *;
*             RELATIONSHIPS                               *;
* ======================================================= *;
* CONTACT:                                                *;
*  WENSUI.LIU@53.COM, LOSS FORECASTING & RISK MODELING    *;
***********************************************************;

options nocenter nonumber nodate mprint mlogic symbolgen orientation = landscape
ls = 150 formchar = "|----|+|---+=|-/\<>*";

%macro granger(data = , dep = , indep = , nlag = );

%let lag_dep = ;
%let lag_indep = ;

data _tmp1;
set &data (keep = &dep &indep);

%do i = 1 %to &nlag;
lag&i._&dep = lag&i.(&dep);
lag&i._&indep = lag&i.(&indep);

%let lag_dep = &lag_dep lag&i._&dep;
%let lag_indep = &lag_indep lag&i._&indep;
%end;
run;

proc corr data = _tmp1 noprint outp = _corr1(rename = (&dep = value) where = (_type_ = 'CORR')) nosimple;
var &dep;
with lag&nlag._&indep;
run;

proc corr data = _tmp1 noprint outp = _corr2(rename = (&dep = value) where = (_type_ = 'CORR')) nosimple;
var &dep;
with lag&nlag._&indep;
partial lag&nlag._&dep;
run;

proc reg data = _tmp1 noprint;
model &dep = &lag_dep;
output out = _rest1 r = rest_e;
run;

proc reg data = _tmp1 noprint;
model &dep = &lag_dep &lag_indep;
output out = _full1 r = full_e;
run;

proc sql noprint;
select sum(full_e * full_e) into :full_sse1 from _full1;

select sum(rest_e * rest_e) into :rest_sse1 from _rest1;

select count(*) into :n from _full1;

select value into :cor1 from _corr1;

select value into :cor2 from _corr2;
quit;

data _result;
format dep \$20. ind \$20.;
dep   = "&dep";
ind   = "%upcase(&indep)";
nlag = &nlag;

corr1 = &cor1;
corr2 = &cor2;

f_test1  = ((&rest_sse1 - &full_sse1) / &nlag) / (&full_sse1 / (&n -  2 * &nlag - 1));
p_ftest1 = 1 - probf(f_test1, &nlag, &n -  2 * &nlag - 1);

chisq_test1 = (&n * (&rest_sse1 - &full_sse1)) / &full_sse1;
p_chisq1    = 1 - probchi(chisq_test1, &nlag);

format flag1 \$3.;
if max(p_ftest1, p_chisq1) < 0.01 then flag1 = "***";
else if max(p_ftest1, p_chisq1) < 0.05 then flag1 = " **";
else if max(p_ftest1, p_chisq1) < 0.1 then flag1 = "  *";
else flag1 = "   ";
run;

%mend granger;

data _in1;
set &data (keep = &y &drivers);
run;

%let var_loop = 1;

%do %while (%scan(&drivers, &var_loop) ne %str());

%let driver = %scan(&drivers, &var_loop);

%do lag_loop = 1 %to &max_lags;

%granger(data = _in1, dep = &y, indep = &driver, nlag = &lag_loop);

%if &var_loop = 1 & &lag_loop = 1 %then %do;
data _final;
set _result;
run;
%end;
%else %do;
data _final;
set _final _result;
run;
%end;
%end;

%let var_loop = %eval(&var_loop + 1);
%end;

title;
proc report data  = _last_ box spacing = 1 split = "/" nowd;
column("GRANGER CAUSALITY TEST FOR %UPCASE(&y) UPTO &MAX_LAGS LAGS"
ind nlag corr1 corr2 f_test1 chisq_test1 flag1);

define ind         / "DRIVERS"                width = 20 center group order order = data;
define nlag        / "LAG"                    width = 3  format = 3.   center order order = data;
define corr1       / "PEARSON/CORRELATION"    width = 12 format = 8.4  center;
define corr2       / "PARTIAL/CORRELATION"    width = 12 format = 8.4  center;
define f_test1     / "CAUSAL/F-STAT"          width = 12 format = 10.4 center;
define chisq_test1 / "CAUSAL/CHISQ-STAT"      width = 12 format = 10.4 center;
define flag1       / "CAUSAL/FLAG"            width = 8  right;
run;

%mend causal;

%causal(data = sashelp.citimon, y = RTRR, drivers = CCIUTC LHUR FSPCON, max_lags = 6);
```

Based upon the output shown below, it is tentative to conclude that LHUR (UNEMPLOYMENT RATE) 3 months early might be helpful to predict RTRR (RETAIL SALES).

``` ---------------------------------------------------------------------------------------
|                     GRANGER CAUSALITY TEST FOR RTRR UPTO 6 LAGS                     |
|                           PEARSON      PARTIAL       CAUSAL       CAUSAL      CAUSAL|
|      DRIVERS        LAG CORRELATION  CORRELATION     F-STAT     CHISQ-STAT      FLAG|
|-------------------------------------------------------------------------------------|
|       CCIUTC       |  1|    0.9852  |    0.1374  |     2.7339 |     2.7917 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  2|    0.9842  |    0.1114  |     0.7660 |     1.5867 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  3|    0.9834  |    0.0778  |     0.8186 |     2.5803 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  4|    0.9829  |    0.1047  |     0.7308 |     3.1165 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  5|    0.9825  |    0.0926  |     0.7771 |     4.2043 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  6|    0.9819  |    0.0868  |     0.7085 |     4.6695 |        |
|--------------------+---+------------+------------+------------+------------+--------|
|        LHUR        |  1|   -0.7236  |    0.0011  |     0.0000 |     0.0000 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  2|   -0.7250  |    0.0364  |     1.4136 |     2.9282 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  3|   -0.7268  |    0.0759  |     2.4246 |     7.6428 |       *|
|                    |---+------------+------------+------------+------------+--------|
|                    |  4|   -0.7293  |    0.0751  |     2.1621 |     9.2208 |       *|
|                    |---+------------+------------+------------+------------+--------|
|                    |  5|   -0.7312  |    0.1045  |     2.1148 |    11.4422 |       *|
|                    |---+------------+------------+------------+------------+--------|
|                    |  6|   -0.7326  |    0.1365  |     1.9614 |    12.9277 |       *|
|--------------------+---+------------+------------+------------+------------+--------|
|       FSPCON       |  1|    0.9484  |    0.0431  |     0.2631 |     0.2687 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  2|    0.9481  |    0.0029  |     0.6758 |     1.3998 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  3|    0.9483  |   -0.0266  |     0.4383 |     1.3817 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  4|    0.9484  |   -0.0360  |     0.9219 |     3.9315 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  5|    0.9494  |   -0.0793  |     0.9008 |     4.8739 |        |
|                    |---+------------+------------+------------+------------+--------|
|                    |  6|    0.9492  |   -0.0999  |     0.9167 |     6.0421 |        |
---------------------------------------------------------------------------------------
```