@Tom's solution structure is the most appropriate for this problem.
My question is this. You are using variable VWRETD, suggesting to me that you are using CRSP data, in particular value-weighted returns with dividends.
Your stated request is for a rolling 250-period sum of VWRETD, with each rolling window ending at the immediately preceding observation. But instead of the sum, do you actually want the 250-period compounded return? If so, then you really want to add the logs of VWRETD+1 and then take the antilog (and subtract 1) to get the compound return. That would look like the below:
data want (drop=_:);
set have;
retain _roll_sum_log_ret_plus1 0;
rolling_preceding_250_return = exp(_roll_sum_log_ret_plus1)-1;
_roll_sum_log_ret_plus1 = _roll_sum_log_ret_plus1 + log(1+vwretd) -1*sum(0,log(lag250(1+vwretd)));
if _n>250 ;
run;
Note that the sum of the logs is updated after the compound return is calculated. This means the calculated compound return does not include the current observation.
There can be a problem with this technique. This program, like @Tom's, constantly updates a rolling total, which means any numeric precision issues, once encountered, can be preserved in subsequent rolling windows, even non-overlapping windows. Solutions that sum arrays of 250 do not have that property. But this solution is much faster, and I doubt that the CRSP data is so pathological as to cause more than a minor difference in results. You can test this assertion by running the data step on your entire dataset, and then only using the last 251 (at least) observations in the dataset. Compare results for corresponding dates. Note this is NOT a SAS problem - it is a numeric precision problem shared by all digital computers.
Editted note: I forgot that you also want the next 250 observations. I.e. for observation 251, you want the compounded return for obs 1 through 250, and also the compounded return for obs 252 through 501. Here's a program that does so:
data want (drop=_:);
if 0 then set have nobs=nperiods ;
merge have have (firstobs=252 keep=vwretd rename=(vwretd=_wretd));
retain _roll_sum_log_ret_plus1 _roll_nxt_log_ret_plus1 0;
rolling_preceding_250_return = exp(_roll_sum_log_ret_plus1) - 1;
rolling_following_250_return = exp(_roll_nxt_log_ret_plus1) - 1;
_roll_sum_log_ret_plus1 = _roll_sum_log_ret_plus1 + log(1+vwretd) -1*sum(0,log(lag250(1+vwretd)));
_roll_nxt_log_ret_plus1 = _roll_nxt_log_ret_plus1 + log(1+_wretd) -1*sum(0,log(lag250(1+_wretd)));
if 250< _n_ < nperiods-250;
run;
This produces results only for those dates that have both a complete window for the preceding 250 observations (i.e. _N_>250) and a complete window for the following 250 observations (_N_ < nperiods-250).
... View more