Search code examples
eventssaswindow

SAS: Event study window with condition


I am conducting an event study and need the average value of return to generate abnormal returns. My benchmark window is [-60,-11] and my event window is [-5,-1] with 0 as announcement date. However, I have several announcements which could contaminate the benchmark and event window. Still, I want to keep the 50 days of benchmark window intact, thus, if there is an announcement in the benchmark window, delete this day and extend the window by 1.

Right now I generate averages with proc expand:

proc expand; by stock;
convert logreturn = avg_logreturn / METHOD = none   TRANSFORMOUT = (movave 60 lag 11); 

run;

And then deduct the average from the actual returns.

My data set looks like this (10 years of data):

Stock   Date      Return    Announcement
AAA    01/01/10    0.05
AAA    02/01/10    0.04
AAA    03/01/10   -0.02      03/01/10     this one should be deleted as is spoils the coming announcement but still be counted as an announcement
AAA    04/01/10    0.01
AAA    05/01/10   -0.03       
AAA    06/01/10    0.05
AAA    07/01/10    0.04
AAA    08/01/10   -0.02      08/01/10  
AAA    09/01/10    0.01
AAA    10/01/10   -0.03
AAB    01/01/10    0.01

etc

Basically, each announcement needs a window of -60 to -11 where I calculate the average of. The length should remain the same but always if there is anther announcement in this window, the return should not be counted in that average.

The idea is simple but the realization seems compliacted...


Solution

  • Pre process the data to be expanded.

    • Find the stock/dates that need to be culled
    • Create a view that excludes culled dates
    • Proc EXPAND

    Sample code:

    data have;
      attrib 
        stock length=$3
        date  length=4 format=date9. informat=mmddyy8. 
        return length=8 format=6.2 
        announcement length=4 format=date9. informat=mmddyy8. 
      ;
      infile cards missover;
      input stock date return announcement;
    datalines;
    AAA    01/01/10    0.05
    AAA    02/01/10    0.04
    AAA    03/01/10   -0.02      03/01/10     this one should be deleted as is spoils the coming announcement but still be counted as an announcement
    AAA    04/01/10    0.01
    AAA    05/01/10   -0.03
    AAA    06/01/10    0.05
    AAA    07/01/10    0.04
    AAA    08/01/10   -0.02      08/01/10  
    AAA    09/01/10    0.01
    AAA    10/01/10   -0.03
    AAB    01/01/10    0.01
    run;
    
    %let CULL_GAP_LE_CRITERIA = 5 ;
    
    data cull(keep=stock cull_date);
      set have;
      by stock date;
    
      retain cull_date;
    
      if first.stock then cull_date = .;
    
      if announcement then do;
        if cull_date then do;
          gap = intck('month', cull_date, announcement);
          if gap <= &CULL_GAP_LE_CRITERIA then
            OUTPUT;
        end;
    
        cull_date = announcement; * setup for culling this announcement as well;
        put cull_date=;
      end;
    run;
    
    data DATA_FOR_EXPAND / view=DATA_FOR_EXPAND;
      merge 
        have 
        cull(rename=cull_date=date in=culled)
      ; 
      by stock date;
      if not culled;
    run;
    

    if not culled will remove the culled row. I think this is correct for you because you said the window was to increase by 1.

    If you want the culled date to be used in rolling windows prior to itself you have a bit of a pickle.