SAS Macros

A collection of SAS Macros that I frequently use and occasionally update.

The full repo can be found at http://github.com/edwinhu/sas

CRSP

COMPUSTAT

COMP_EAD

Gets quarterly earnings announcement dates from COMPUSTAT and fetches CRSP PERMNOs. Makes a file comp_ead_events.

  • comp_vars: list of COMPUSTAT variables to fetch
  • filter: filters to place on COMPUSTAT quarterly
%INCLUDE "~/git/sas/COMP_EAD.sas";
%COMP_EAD(comp_vars=gvkey fyearq fqtr conm datadate rdq
    epsfxq epspxq
    prccq ajexq
    spiq cshoq cshprq cshfdq
    saleq atq
    fyr datafqtr,
    filter=not missing(saleq) or atq>0
    );

Utilities

FF93_FACTORS

Replicates Fama-French (1993) SMB & HML Factors. Currently obtaining correlations of 99.5% (SMB) 97.8% (HML) for sample period 1975 to 2019.

Also useful in case you want to get the breakpoints or portfolio compositions.

EVENT_MACROS

A collection of event study macros adapted from WRDS.

%EVENT_SETUP sets the global variables, including the start and end dates of the estimation and event windows. It also sets the formula to use for the abnormal returns.

%EVENT_EXPAND does the bulk of the merging of datasets, creating the actual windows and ultimately the output file &prefix._expand.

%EVENT_STATS computes abnormal returns, and then the summary statistics. The output file &prefix._car contains the event-window data with abnormal returns.

%INCLUDE "~/git/sas/EVENT_MACROS.sas";
%EVENT_SETUP(pref=,
    crsp_lib=crspm,
    frequency=d,
    date_var=event_date,
    id_var=permno,
    model=ffm,
    ret_var=retx,
    est_per=252, gap_win=30,
    beg_win=-30, end_win=120
    );
%EVENT_EXPAND(lib=user, debug = n);
%EVENT_STATS(prefix = ,
    dsetin = ,
    group = ,
    filter = and shrcd in (10,11) and exchcd in (1,2,3),
    debug= = n
    );

MERGE_ASOF

Does an as-of or “window” merge, e.g., COMPUSTAT yearly with CRSP monthly, or TAQ quotes with TAQ trades.

See, e.g., pandas, rolling joins with R data.table, or kdb+ asof.

  • a: dataset a
  • b: dataset b
  • merged: output merged dataset
  • idvar: firm identifier (permno)
  • datevar: date variable to use (date)
  • sort_statement: defaults to idvar datevar but can be customized
  • num_vars: numeric variables from b to merge in
  • char_vars: character variables from b to merge in
%INCLUDE "~/git/sas/MERGE_ASOF.sas";
%MERGE_ASOF(a=,b=,
    merged=,
    num_vars=);

PARFOR

A parallel FOR loop SAS Macro.

If you have huge files it is often better to use Split-Apply-Combine processing. For example processing daily trades by year can be done by splitting the dataset into yearly datasets and doing the processing in a parallel FOR loop.

This Macro spawns multiple SAS processes in the background to make parallel processing easy. The Macro waits until all processes are complete before returning control to the user.

WARNING: There is no built-in resource control (RAM/CPU) so make sure to test your code on one group at a time before spawning too many concurrent processes!

%INCLUDE "~/git/sas/PARFOR";
%LET FUNC = %STR(
    proc print data=perf_&yyyy.(obs=25);
    var exret: ret:;
    run;
);
%PARFOR(FUNC=&FUNC.);

RESAMPLE

Resample and forward-fill data from low to high frequency Commonly used to sample low frequency COMPUSTAT data before merging with higher frequency CRSP data. It is more efficient to use MERGE_ASOF for this specific task.

  • lib: input dataset library
  • dsetin: input dataset
  • dsetout: output (resampled) dataset
  • datevar: date variable to resample
  • idvar: group by id variable
  • infreq: input frequency
  • outfreq: output (higher) frequency
  • alignment: date alignment (E,S,B)
  • debug: keep or delete temporary datasets
%INCLUDE "~/git/sas/RESAMPLE.sas";
%RESAMPLE(lib=sashelp, dsetin=citiyr, outfreq=monthly, idvar=, datevar=date);

ROLL_REG

Runs rolling regressions in a computationally efficient way, taking advantage of SAS SSCP matrices.

  • dsetin: input dataset
  • id: id variable
  • date: date variable
  • y: dependent variable
  • x: independent variable
  • ws: window size
  • debug: debug mode (n)
%INCLUDE "~/git/sas/ROLL_REG.sas";
%ROLL_REG(dsetin=,
          id=permno,
          date=date,
          y=exret,
          x=mktrf,
          ws=60,
          debug=n);