I've always been disappointed that PROC EXPAND only does univariate series transformations. That's why in the useful paper mentioned by @KatScott you have to prepare the dataset (e.g. create product X1_2=x1*x2) prior to PROC EXPAND, which of course is followed by a PROC CORR.
It might be a better idea to skip the proc expand, as in:
data need (drop=_:) view=need ;
set have;
if _n_=1 then do;
declare hash h (dataset:'have(obs=0)',ordered:'a');
h.definekey('date');
h.definedata(all:'Y');
h.definedone();
declare hiter hi ('h');
end;
h.add();
_date&winsize=lag&winsize(date);
window_close_date=date ;
format window_close_date date9. ;
if _date&winsize^=. then h.remove(key:_date&winsize);
if _n_>=&winsize then do _rc=hi.first() by 0 until (hi.next()^=0);
output;
end;
run;
proc corr data=need noprint out=correlations;
by window_close_date ;
var x y;
run;
Dataset view NEED simply creates a set of records for each window. In the above instance the window size is 21, and is identified by the variable WINDOW_CLOSE_DATE. Each WINDOW_SIZE_DATE will have 21 records ( and therefore most records will appear in 21 windows) in NEED. For a large windows size, that's a lot of records, but disk activity is kept to a minimum by generating NEED as a data set VIEW, not a data set FILE.