30 The SAS System 15:11 Tuesday, June 30, 2020
189 ods listing close;ods html5 (id=saspy_internal) file=_tomods1 options(bitmap_mode='inline') device=svg style=HTMLBlue;
189 ! ods graphics on / outputfmt=png;
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: _TOMODS1
190
191 rsubmit;
31 The SAS System 15:11 Tuesday, June 30, 2020
NOTE: Remote submit to WRDS commencing.
191 ! /* ***************************************************************************** */
1 /*
1 ! ***************************************************************************
1 ! ** */
2 /* ********* W R D S R E S E A R C H A P P L I C A T I O N S
2 ! *************** */
3 /*
3 ! ***************************************************************************
3 ! ** */
4 /* Program : EVTSTUDY.SAS
4 ! */
5 /* Summary : Provides a sample methodology for calculating Cumulative
5 ! */
6 /* Abnormal Returns(CARs)& Buy-Hold Abnormal Returns(BHARs)
6 ! */
7 /* with various t-statistics (CS test, Standardized CS
7 ! test&Patell Z) */
8 /* in an event study setting. Displays the dynamics of mean CARs
8 ! and */
9 /* BHARs in the event window specified by the user
9 ! */
10 /*
10 ! */
11 /* Date : Sep 2011
11 ! */
12 /* Author : Denys Glushkov, WRDS
12 ! */
13 /* Modified by Eunji Oh, June 2020
14 /*
14 ! ***************************************************************************
14 ! * */
15
16 %macro EVTSTUDY(input_data
16 ! ,crsp_type='crsp',estper_num=150,start_win=-10,end_win=10,gap_num=15,minest
16 ! _num=120);
17
18 /* STEP 1A: Speficify the parameters necessary to run the event study such
18 ! as */
19 /* the length of estimation period and event window, gap b/w estimation &
19 ! event */
20 /* window, etc
20 ! */
21 %let crsp=&crsp_type; /*CRSP libary to be used (CRSPQ - quarterly,
21 ! CRSP-annual update */
22 %let estper=&estper_num; /*Length of the estimation period in trading days
22 ! over which */
23 /*the risk model is estimated
23 ! */
24
25 %let start=&start_win; /*Beginning of the event window (wtr to the event
25 ! date,e.g. -2) */
26 %let end=&end_win; /*End of the event window (relative to the event
26 ! date, e.g., +1) */
27 %let gap=&gap_num; /*Length of pre-event window,i.e., number of trading
27 ! days b/w */
28 /*the end of estimation period and the start of the event
28 ! window */
29
30 %let minest=&minest_num; /*Minimum of non-missing returns required for
30 ! estimation */
31 %let evtwin=%eval(&end-&start+1); /*length of event window in trading
31 ! days */
32
33 /* STEP 1B: As an example, create the input table containing Permno-event
33 ! dates */
34 /* corresponding to the stock additions to and deletions from S&P 500 index
34 ! */
35
36 /* input_data should have permno and edate (event date) in sas date format
36 ! only */
37 proc sql;
38 create table input
39 as select distinct permno, edate format date9.
40 from &input_data where not missing(edate);
41 quit;
42
43
44 /* STEP 2. Creating Trading Calendar that accounts for the presence of */
45 /* weekends, holidays and other non-trading days in the estimation */
46 /* and event windows */
47 data caldates;
48 merge &crsp..dsi(keep=date rename=(date=estper_beg))
49 &crsp..dsi(keep=date firstobs=&estper rename=(date=estper_end))
50 &crsp..dsi(keep=date firstobs=%eval(&estper+&gap+1)
50 ! rename=(date=evtwin_beg))
51 &crsp..dsi(keep=date firstobs=%eval(&estper+&gap-&start+1)
51 ! rename=(date=evtdate))
52 &crsp..dsi(keep=date firstobs=%eval(&estper+&gap+&evtwin)
52 ! rename=(date=evtwin_end));
53 format estper_beg estper_end evtwin_beg evtdate evtwin_end date9.;
54 label estper_beg='Start of the Estimation Window'
55 estper_end='End of the Estimation Window'
56 evtwin_beg='Start of the Event Window'
57 evtwin_end='End of the Event Window'
58 evtdate='Event Date';
59 index+1;
60 if nmiss(estper_beg,estper_end,evtwin_beg,evtwin_end,evtdate)=0;
61 run;
62
63 /*STEP 3: If event date is a non-trading day, select the closest trading
63 ! day that*/
64 /* follows the event day
64 ! */
65 proc sql; create table temp
66 as select a.permno, b.*
67 from input a left join caldates b
68 on b.evtdate-a.edate>=0
69 group by a.edate
70 having (b.evtdate-a.edate)=min(b.evtdate-a.edate);
71
72 /*Returns for sample securities around the event dates */
73 create table evtrets_temp
74 as select a.permno, a.date format date9., a.ret as ret1,
75 b.evtdate, b.estper_beg, b.estper_end,
76 b.evtwin_beg, b.evtwin_end
77 from &crsp..dsf a, temp b
78 where a.permno=b.permno and b.estper_beg<=a.date<=b.evtwin_end;
79
80 /* Merge in the risk factors */
81 /* User can create her own risk factors and use it instead of FF+M ones*/
82 create view evtrets1
83 as select a.*, (b.mktrf+b.rf) as mkt, b.mktrf, b.rf,b.smb, b.hml, b.umd
84 from evtrets_temp a left join
85 ff.factors_daily (keep=date mktrf smb hml umd rf) b
86 on a.date=b.date;
87
88 /*Bring in delisting returns*/
89 create table evtrets (drop=ret1 where=(not missing(mkt)))
90 as select a.*,
91 (1+a.ret1)*sum(1,b.dlret)-1-a.mkt as exret label='Market-adjusted total
91 ! ret',
92 (1+a.ret1)*sum(1,b.dlret)-1 as ret "Ret adjusted for delisting"
93 from evtrets1 a left join &crsp..dsedelist (where=(missing(dlret)=0)) b
94 on a.permno=b.permno and a.date=b.dlstdt
95 order by a.permno,a.evtdate,a.date;
96 quit;
97
98 /* STEP 4. Estimating Factor Exposures over the estimation period*/
99 proc printto log=junk; run;
100
101 proc reg data=evtrets edf outest=params noprint;
102 where estper_beg<=date<=estper_end;
103 by permno evtdate;
104 eq0: model exret=;
105 eq1: model ret=mktrf;
106 eq2: model ret=mktrf smb hml;
107 eq3: model ret=mktrf smb hml umd;
108 run;
109 proc printto;run;
110
111
112 /* STEP 5. Calculating Abnormal Returns for all models */
113 /* for each trading day in the event window */
114 data abrets1/view=abrets1; merge
115 evtrets(where=(evtwin_beg<=date<=evtwin_end) in=a)
116 params (where=(_model_='eq0')
117 keep=permno evtdate _model_ _rmse_ _p_ _edf_
118 rename=(_rmse_=std0 _p_=p0 _edf_=edf0))
119 params (where=(_model_='eq1')
120 keep=permno evtdate _model_ _rmse_ intercept mktrf
121 rename=(_rmse_=std1 intercept=alpha1 mktrf=beta1))
122 params (where=(_model_='eq2')
123 keep=permno evtdate _model_ _rmse_ intercept mktrf smb hml
124 rename=(_rmse_=std2 intercept=alpha2 mktrf=beta2 smb=sminb2
124! hml=hminl2))
125 params (where=(_model_='eq3')
126 keep=permno evtdate _model_ _rmse_ intercept mktrf smb hml umd
127 rename=(_rmse_=std3 intercept=alpha3 mktrf=beta3 smb=sminb3 hml=hminl3
127! umd=umind3));
128 by permno evtdate;
129 retain missret;
130 if first.permno then missret=missing(ret);
131 if missing(ret) then missret+1; /*count number of missing returns*/
132 var0=std0**2; var1=std1**2;var2=std2**2;var3=std3**2;
133 abret0=exret;
134 expret1=alpha1+beta1*mktrf; abret1=ret-expret1;
135 expret2=alpha2+beta2*mktrf+sminb2*smb+hminl2*hml; abret2=ret-expret2;
136 expret3=alpha3+beta3*mktrf+sminb3*smb+hminl3*hml+umind3*umd;
136! abret3=ret-expret3;
137 nobs=p0+edf0; /*number of observations used in estimation*/
138 drop p0 edf0 estper_beg estper_end std0 std1 std2 std3 _model_ exret;
139 if a and nobs>&minest;
140 run;
141
142 /* Transform dates to event time using CRSP Trading Calendar */
143 /* Using the latter takes into account non-consecutive date records*/
144 proc sql; create table abrets
145 as select a.*, (b.index-c.index) as evttime
146 from abrets1 a left join caldates b
147 on a.date=b.evtdate
148 left join caldates c
149 on a.evtdate=c.evtdate
150 order by permno, evtdate, date;
151 quit;
152
153 /* Calculating Rolling Cumulative Abnormal Returns and various stats */
154 /* Transformout= calculates cumulative product of gross returns and */
155 /* subtracts 1 to arrive at the total net cumulative return */
156 proc expand data=abrets out=car method=none;
157 by permno evtdate; id date;
158 convert ret=cret/transformout=(+1 cuprod -1);
159 convert mkt=cmkt/transformout=(+1 cuprod -1);
160 convert expret1 =cexpret1 /transformout=(+1 cuprod -1);
161 convert expret2 =cexpret2 /transformout=(+1 cuprod -1);
162 convert expret3 =cexpret3 /transformout=(+1 cuprod -1);
163 convert abret0=car0/transformout=(sum);
164 convert abret1=car1/transformout=(sum);
165 convert abret2=car2/transformout=(sum);
166 convert abret3=car3/transformout=(sum);
167 run;
168
169 /* Car_Evtdate Table the cross-sectional output that contains for each
169! */
170 /* "firm-event date":
170! */
171 /* 1) CAR, BHAR, and SCAR (standardized CAR)
171! */
172 /* 2) Alpha and Beta from the estimation period
172! */
173 /* 3) Estimation period variance
173! */
174
175 /* Car_Evtwin Table contains Raw, Abnormal, Std. and Buy-and-Hold Abnormal
175! */
176 /* Daily Returns "firm-date" in event time
176! */
177 proc printto log=junk;run;
178
179 data car_evtdate
180 (drop=evttime ret mkt smb hml umd date calpha1 calpha2 calpha3
181 cmrkt csmb chml cumd evtwin_beg evtwin_end abret0 abret1
182 abret2 abret3 sar0 sar1 sar2 sar3 missret cexpret1 cexpret2
182! cexpret3)
183 car_evtwin
184 (keep=permno evtdate evttime date ret cret abret0 abret1 abret2
184! abret3
185 sar0 sar1 sar2 sar3 bhar0 bhar1 bhar2 bhar3 car0 car1 car2 car3);
186 set car;
187 by permno evtdate date;
188 /*Standardized CARs and ARs for various models*/
189 scar0=car0/(&evtwin*var0)**0.5; scar1=car1/(&evtwin*var1)**0.5;
190 scar2=car2/(&evtwin*var2)**0.5; scar3=car3/(&evtwin*var3)**0.5;
191 sar0=abret0/sqrt(var0);sar1=abret1/sqrt(var1);
192 sar2=abret2/sqrt(var2);sar3=abret3/sqrt(var3);
193 pat_scale=(nobs-2)/(nobs-4); /*Patell Z scaling factor*/
194 /*Buy-Hold Abnormal Returns*/
195 bhar0=cret-cmkt; bhar1=cret-cexpret1;
196 bhar2=cret-cexpret2; bhar3=cret-cexpret3;
197 if last.evtdate then do; nrets=&evtwin-missret; output car_evtdate; end;
198 output car_evtwin;
199 run;
200 proc printto;run;
201
202 /*Put Cross-sectional and aggregate results together for further analysis*/
203 data allcars; merge
204 car_evtwin
205 (rename=(bhar0=bhar0win bhar1=bhar1win bhar2=bhar2win bhar3=bhar3win
206 car0=car0win car1=car1win car2=car2win car3=car3win
206! cret=cretwin))
207 car_evtdate;
208 by permno evtdate;
209 run;
210
211 /* STEP 6: Compute Cumulative Average Abnormal Return (CAR_MEAN) */
212 /* and Average Buy-Hold Abnormal Return (BHAR_MEAN) */
213 /* and other stats across all distinct events */
214 proc means data=allcars noprint;
215 class evttime; id nobs;
216 var ret cret car0 car1 car2 car3 bhar0 bhar1 bhar2 bhar3
217 bhar0win bhar1win bhar2win bhar3win cretwin
218 car0win car1win car2win car3win
219 scar0 scar1 scar2 scar3 abret0 abret1 abret2 abret3
220 sar0 sar1 sar2 sar3 pat_scale;
221 output out=allstats
222 mean= n= t= sum=/autoname;
223 run;
224
225 /*calculate different stats for assessing */
226 /*statistical signficance of abnormal returns*/
227 data MA_Evtdate (keep=evttime car0_n cret_mean car0_mean car0_t scar0_t
228 bhar0_mean pat_car0 model)
229 MM_Evtdate (keep=evttime car1_n cret_mean car1_mean car1_t scar1_t
230 bhar1_mean pat_car1 model )
231 FF_Evtdate (keep=evttime car2_n cret_mean car2_mean car2_t scar2_t
232 bhar2_mean pat_car2 model )
233 FFM_Evtdate (keep=evttime car3_n cret_mean car3_mean car3_t scar3_t
234 bhar3_mean pat_car3 model )
235 MA_Evtwin (keep=evttime cretwin_mean abret0_n ret_mean abret0_mean
236 car0win_mean bhar0win_mean abret0_t sar0_t pat_ar0 )
237 MM_Evtwin (keep=evttime cretwin_mean abret1_n ret_mean abret1_mean
238 car1win_mean bhar1win_mean abret1_t sar1_t pat_ar1 )
239 FF_Evtwin (keep=evttime cretwin_mean abret2_n ret_mean abret2_mean
240 car2win_mean bhar2win_mean abret2_t sar2_t pat_ar2 )
241 FFM_Evtwin (keep=evttime cretwin_mean abret3_n ret_mean abret3_mean
242 car3win_mean bhar3win_mean abret3_t sar3_t pat_ar3 );
243 set allstats;
244 by evttime;
245 if _n_=1 and missing(evttime) then do;
246 abret0_mean=.; abret1_mean=.;
247 abret2_mean=.; abret3_mean=.;
248 cretwin_mean=0; ret_mean=.;
249 bhar1win_mean=0; bhar1win_mean=0;
250 bhar2win_mean=0;bhar3win_mean=0;
251 end;
252 /*Patell Z statistics*/
253 pat_car0=scar0_mean/(sqrt(pat_scale_sum)/scar0_n);
254 pat_car1=scar1_mean/(sqrt(pat_scale_sum)/scar1_n);
255 pat_car2=scar2_mean/(sqrt(pat_scale_sum)/scar2_n);
256 pat_car3=scar3_mean/(sqrt(pat_scale_sum)/scar3_n);
257 pat_ar0=sar0_mean/(sqrt(pat_scale_sum)/sar0_n);
258 pat_ar1=sar1_mean/(sqrt(pat_scale_sum)/sar1_n);
259 pat_ar2=sar2_mean/(sqrt(pat_scale_sum)/sar2_n);
260 pat_ar3=sar3_mean/(sqrt(pat_scale_sum)/sar3_n);
261 label
262 pat_ar0= 'Patell Z for AR_MA' pat_ar1= 'Patell Z for
262! AR_MM'
263 pat_ar2= 'Patell Z for AR_FF' pat_ar3= 'Patell Z for
263! AR_FFM'
264 abret0_t= 'CS t-stat, AR_MA' abret1_t= 'CS t-stat, AR_MM'
265 abret2_t= 'CS t-stat, AR_FF' abret3_t= 'CS t-stat, AR_FFM'
266 sar0_t= 'Std CS test, AR_MA' sar1_t= 'Std CS test,
266! AR_MM'
267 sar2_t= 'Std CS test, AR_FF' sar3_t= 'Std CS test,
267! AR_FFM'
268 abret0_mean= 'Mean AR_MA' abret1_mean= 'Mean AR_MM'
269 abret2_mean= 'Mean AR_FF' abret3_mean= 'Mean AR_FFM'
270 car0_n= 'Number of events in the portfolio'
271 abret0_n= 'Number of events in the portfolio'
272 evttime= 'Event Time t'
273 cret_mean= "Mean CTR (&start, &end)"
274 cretwin_mean= "Mean CTR (&start,t) "
275 car0win_mean= "Average CAR_MA (&start, t)"
276 car1win_mean= "Average CAR_MM (&start, t)"
277 car2win_mean= "Average CAR_FF (&start, t)"
278 car3win_mean= "Average CAR_FFM (&start, t)"
279 bhar0win_mean= "Mean BHAR_MA (&start, t)"
280 bhar1win_mean= "Mean BHAR_MM (&start, t)"
281 bhar2win_mean= "Mean BHAR_FF (&start, t)"
282 bhar3win_mean= "Mean BHAR_FFM (&start, t)"
283 ;
284 format ret_mean cret_mean abret0_mean abret1_mean abret2_mean
284! abret3_mean
285 car0_mean car1_mean car2_mean car3_mean bhar0_mean bhar1_mean
286 bhar2_mean bhar3_mean cretwin_mean
287 bhar0win_mean bhar1win_mean bhar2win_mean bhar3win_mean
288 car0win_mean car1win_mean car2win_mean car3win_mean percent7.4
289 abret0_t abret1_t abret2_t abret3_t sar0_t sar1_t sar2_t sar3_t
290 pat_car0 pat_car1 pat_car2 pat_car3 pat_ar0 pat_ar1 pat_ar2
290! pat_ar3
291 car0_t car1_t car2_t car3_t scar0_t scar1_t scar2_t scar3_t
291! comma10.2;
292 if evttime=0 then do; model='Market-Adjusted'; output MA_Evtdate;
293 model='Market Model'; output MM_Evtdate;
294 model='FF Model'; output FF_Evtdate;
295 model='Carhart Model'; output FFM_Evtdate;
296 end;
297 if missing(evttime) then evttime=&start-1;
298 output MA_Evtwin; output MM_Evtwin; output FF_Evtwin; output FFM_Evtwin;
299 run;
300
301 /* STEP 7. Putting Event Date CARs and BHARS for various risk models
301! together*/
302 data allevtdate; set
303 MA_Evtdate (rename=(car0_mean=car_mean bhar0_mean=bhar_mean
304 car0_n=n car0_t=car_t scar0_t=scar_t pat_car0=pat_car))
305 MM_Evtdate (rename=(car1_mean=car_mean bhar1_mean=bhar_mean
306 car1_n=n car1_t=car_t scar1_t=scar_t pat_car1=pat_car))
307 FF_Evtdate (rename=(car2_mean=car_mean bhar2_mean=bhar_mean
308 car2_n=n car2_t=car_t scar2_t=scar_t pat_car2=pat_car))
309 FFM_evtdate (rename=(car3_mean=car_mean bhar3_mean=bhar_mean
310 car3_n=n car3_t=car_t scar3_t=scar_t pat_car3=pat_car));
311 length=&evtwin;
312 label pat_car= 'Patell Z'
313 car_mean= "Mean CAR (&start, &end)"
314 bhar_mean= "Mean BHAR (&start, &end)"
315 car_t= 'Cross-sectional t-stat for CAR'
316 scar_t= 'Standaridized cross-sectional t-stat for CAR'
317 length= 'Length of event window in trading days';
318 run;
319
320 /*Cross-sectional output for CARs/BHARs at the firm-event level*/
321 data car_evtdate;
322 retain permno evtdate alpha1 beta1 cret car0 bhar0 var0 car1 bhar1 var1
323 car2 bhar2 var2 car3 bhar3 var3 nrets nobs;
324 set car_evtdate;
325 label alpha1= 'Alpha (Market Model)' beta1='Beta (Market Model'
326 car0= 'CAR_MA' car1='CAR_MM'
327 car2= 'CAR_FF' car3='CAR_FFM'
328 bhar0= 'BHAR_MA' bhar1='BHAR_MM'
329 bhar2= 'BHAR_FF' bhar3='BHAR_FFM'
330 var0= 'Estimation period variance (Market-adjusted returns)'
331 var1= 'Estimation period variance (Market Model)'
332 var2= 'Estimation period variance (FF Model)'
333 var3= 'Estimation period variance (Carhart Model)'
334 cret= 'Cumulative Total Return'
335 nrets= 'Number of non-missing returns in event window'
336 nobs= 'Length of the estimation period';
337 keep permno evtdate alpha1 beta1 cret car0 bhar0 var0 car1 bhar1 var1
338 car2 bhar2 var2 car3 bhar3 var3 nrets nobs;
339 format cret alpha1 car0 bhar0 car1 bhar1 car2 bhar2 car3 bhar3 percent7.4
340 beta1 comma10.3;
341 run;
342
343 /* As an illustration, plot Carhart CAARs and average BHARs in the event
343! window*/
344 options nodate orientation=landscape; ods pdf file="Carhart_evtret.pdf";
345 goptions device=pdfc; /* Plot Saved in Home Directory */
346 *goptions hsize=4 vsize=3;
347 axis1 label=(angle=90 "Cumulative Returns");
348 axis2 label=("Event time");
349 symbol interpol=join w=3 l=1;
350 proc gplot data =FFM_Evtwin;
351 where evttime>=&start;
352 Title "Cumulative Total Returns vs. Carhart CAARs and BHARs around the
352! event date";
353 plot (cretwin_mean car3win_mean bhar3win_mean)*evttime
354 /overlay legend vaxis=axis1 haxis=axis2;
355 run;quit; ods pdf close;
356
357 /*house cleaning*/
358 proc sql;
359 drop table abrets, allcars, allstats, caldates, car, car_evtwin, evtrets,
359! temp,
360 evtrets_temp,ffm_evtdate, ff_evtdate, ma_evtdate, mm_evtdate,
360! params;
361 drop view evtrets1, abrets1; quit;
362
363 %mend;
364 /*
364! ***************************************************************************
364! ***** */
365 /* ************* Material Copyright Wharton Research Data Services
365! ************** */
366 /* ****************************** All Rights Reserved
366! ***************************** */
367 /*
367! ***************************************************************************
367! ***** */
NOTE: Remote submit to WRDS complete.
192
193
194 ods html5 (id=saspy_internal) close;ods listing;
195
32 The SAS System 15:11 Tuesday, June 30, 2020
196