You can use a SQL procedure to get cumulative returns for the specified date range, for each of the specified PERMNO's. Although it could be done in one "CREATE table" step, the two-step process below is much faster. The notes below provide more detailed information.
create table returns as
select permno, date, ret
from crsp.dsf (keep=permno date ret)
where permno in ( 10068 , 12490 )
order by permno, date
create table cum_returns as
select permno , exp(sum(log(1+ret))) - 1 as cum_return
, min(ret) as minret , max(ret) as maxret
, n(ret) as n_periods , nmiss(ret) as n_miss
, sum(ret=.P) as n_dot_p , min(date) as first_date
, max(date) as last_date
where ('01jan1986'd <= date <= '31dec1986'd)
group by permno
If you run a proc print like this on the resulting dataset
proc print data=cum_returns; format first_date last_date yymmdd10.; run;
the listing file should look like this:
Obs PERMNO return minret maxret n_periods n_miss n_dot_p first_date last_date
1 10068 -0.41463 -0.13158 0.058824 187 1 1 1986-02-21 1986-11-17
2 12490 -0.20348 -0.04337 0.029762 253 0 0 1986-01-02 1986-12-31
The "Invalid arguments" note: This came because as shown in the "n_miss" column above, there is an instance in which the RET variable was missing - hence the log could not be taken.
Case Selection: The calculation of cumulative return (CUM_RETURN) uses all the non-missing observations of RET for the selected PERMNO's for periods ending within the specified date range. Even though the date range in this example is a single year, the CUM_RETURN value may not be (and in the case of PERMNO 10068 most certainly is not) an annualized return. This can be due to several reasons: The first holding period may not have begun on the trading date immediately prior to Jan 1, 1986. It could have begun a number of trading days earlier or could have begun within 1986. A similar consequence would hold if the last trading period did not end on the last trading date of 1986.
CUM_RETURN is the cumulative return for the valid case in the date range.
MINRET and MAXRET are the minima and maximum returns observed for a single holding period.
N_PERIODS is the number of holding periods that have non-missing values of RET, which is used to calculate CUM_RETURN. Note that PERMNO 10068 has only 187 trading periods in 1986 - probably indicating the issue either started trading sometime in 1986 or stopped trading before Dec 31, 1986.
N_MISS (number observations with any missing value for RET) and N_DOT_P (Number of instances with RET having the specific missing value .P). If either of these is not 0 you should investigate whether your cumulative return calculation is valid for your purposes. Also, note in the LOG file that SAS mentions at least one instance in which a log could not be taken. This would have come for the observation for PERMNO 10068 with a missing value of .P. It turns out that permno 10068 (ticker=APGI name=American Property Groups Inc, started trading on 2/21/1986 and stopped on 11/17/1986). Examining the CRSP.DLE (Delisting Event) file shows that this company had a DLRET (Delisting Return) of -1 on 11/17/1986, that is, all funds were lost and the cumulative return should actually be a -1.
FIRST_DATE and LAST_DATE are the earliest and latest dates available for the corresponding permno in the date range specified.