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

## Calculating ACF with Data Step Only

In SAS/ETS, it is trivial to calculate ACF of a time series with ARIMA procedure. However, the downside is that, in addition to ACF, you will get more outputs than necessary without knowing the underlying mechanism. The SAS macro below is a clean routine written with simple data steps showing each step how to calculate ACF and generating nothing but a table with ACF and the related lag without using SAS/ETS module at all. It is easy to write a wrapper around this macro for any further analysis.

```%macro acf(data = , var = , out = acf);
***********************************************************;
* SAS MACRO CALCULATING AUTOCORRELATION FUNCTION WITH     *;
* DATA STEP ONLY                                          *;
* ======================================================= *;
* INPUT PAREMETERS:                                       *;
*  DATA : INPUT SAS DATA TABLE                            *;
*  VAR  : THE TIME SERIES TO TEST FOR INDEPENDENCE        *;
* ======================================================= *;
* OUTPUT:                                                 *;
*  OUT : A OUTPUT SAS DATA TABLE WITH ACF AND LAG         *;
* ======================================================= *;
* AUTHOR: WENSUI.LIU@53.COM                               *;
***********************************************************;

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

proc sql noprint;
select mean(&var) into :mean_x from _last_;
quit;

%do i = 1 %to %eval(&nobs - 1);

data _2(keep = _:);
set _1;
_x = &var;
_lag = lag&i.(_x);
run;

proc sql ;
create table
_3 as
select
(_x - &mean_x) ** 2               as _den,
(_x - &mean_x) * (_lag - &mean_x) as _num
from
_last_;

create table
_4 as
select
&i                    as lag,
sum(_num) / sum(_den) as acf
from
_last_;

%if &i = 1 %then %do;
create table
&out as
select
*
from
_4;
%end;
%else %do;
insert into &out
select
*
from
_4;
%end;

drop table _2, _3, _4;
quit;
%end;

%mend acf;
```