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

## A More Flexible Ljung-Box Test in SAS

Ljung-Box test is an important diagnostic to check if residuals from the time series model are independently distributed. In SAS / ETS module, it is easy to perform Ljung-Box with ARIMA procedure. However, test outputs are only provided for Lag 6, 12, 18, and so on, which cannot be changed by any option.

```data one;
do i = 1 to 100;
x = uniform(1);
output;
end;
run;

proc arima data = one;
identify var = x whitenoise = ignoremiss;
run;
quit;
/*
Autocorrelation Check for White Noise

To        Chi-             Pr >
Lag      Square     DF     ChiSq    --------------------Autocorrelations--------------------
6        5.49      6    0.4832     0.051    -0.132     0.076    -0.024    -0.146     0.064
12        6.78     12    0.8719     0.050     0.076    -0.046    -0.025    -0.016    -0.018
18       10.43     18    0.9169     0.104    -0.053     0.063     0.038    -0.085    -0.065
24       21.51     24    0.6083     0.007     0.178     0.113    -0.046     0.180     0.079
*/
```

The SAS macro below is a more flexible way to perform Ljung-Box test for any number of lags. As shown in the output, test results for Lag 6 and 12 are identical to the one directly from ARIMA procedure.

```%macro LBtest(data = , var = , lags = 4);
***********************************************************;
* SAS MACRO PERFORMING LJUNG-BOX TEST FOR INDEPENDENCE    *;
* ======================================================= *;
* INPUT PAREMETERS:                                       *;
*  DATA : INPUT SAS DATA TABLE                            *;
*  VAR  : THE TIME SERIES TO TEST FOR INDEPENDENCE        *;
*  LAGS : THE NUMBER OF LAGS BEING TESTED                 *;
* ======================================================= *;
* AUTHOR: WENSUI.LIU@53.COM                               *;
***********************************************************;

%local nlag;

data _1 (keep = &var);
set &data end = eof;
if eof then do;
call execute('%let nlag = '||put(_n_ - 1, 8.)||';');
end;
run;

proc arima data = _last_;
identify var = &var nlag = &nlag outcov = _2 noprint;
run;
quit;

%do i = 1 %to &lags;
data _3;
set _2;
where lag > 0 and lag <= &i;
run;

proc sql noprint;
create table
_4 as
select
sum(corr * corr / n) * (&nlag + 1) * (&nlag + 3) as _chisq,
1 - probchi(calculated _chisq, &i.)              as _p_chisq,
&i                                               as _df
from
_last_;
quit;

%if &i = 1 %then %do;
data _5;
set _4;
run;
%end;
%else %do;
data _5;
set _5 _4;
run;
%end;
%end;

title;
proc report data = _5 spacing = 1 headline nowindows split = "*";
column(" * LJUNG-BOX TEST FOR WHITE NOISE *
* H0: RESIDUALS ARE INDEPENDENTLY DISTRIBUTED UPTO LAG &lags * "
_chisq _df _p_chisq);
define _chisq   / "CHI-SQUARE" width = 20 format = 15.10;
define _df      / "DF"         width = 10 order;
define _p_chisq / "P-VALUE"    width = 20 format = 15.10;
run;

%mend LBtest;

%LBtest(data = one, var = x, lags = 12);

/*
LJUNG-BOX TEST FOR WHITE NOISE
H0: RESIDUALS ARE INDEPENDENTLY DISTRIBUTED UPTO LAG 12

CHI-SQUARE         DF              P-VALUE
------------------------------------------------------
0.2644425904          1         0.6070843322
2.0812769288          2         0.3532290858
2.6839655476          3         0.4429590625
2.7428168168          4         0.6017432831
5.0425834917          5         0.4107053939
5.4851972398          6         0.4832476224
5.7586229652          7         0.5681994829
6.4067856029          8         0.6017645131
6.6410385135          9         0.6744356312
6.7142471241         10         0.7521182318
6.7427585395         11         0.8195164211
6.7783018413         12         0.8719097622
*/
```