* ----------------------------------------- * ----------------------------------------- * * Stata event study * ----------------------------------------- * ----------------------------------------- * please refer to the following for more instruction * http://dss.princeton.edu/usingdata/stata/analysis/eventstudy.html * http://dss.princeton.edu/usingdata/stata/analysis/eventstudydataprep.html *use http://dss.princeton.edu/sampleData/eventdates.dta /* about 11k */ *save C:\stata15mp\eventdates.dta *use http://dss.princeton.edu/sampleData/stockdata.dta, clear /* about 90m */ *save C:\stata15mp\stockdata.dta /* * merge the above two datasets use C:\stata15mp\eventdates.dta, clear drop targetname *file size will be a lot smaller after deleting this variable* sort company_id *sort so that can merger later* save eventdate_1, replace use C:\stata15mp\stockdata, clear sort company_id *for merging* merge company_id using eventdate_1 drop if _merge != 3 *only keep observation with the complete event* save eventda, replace */ * ----------------------------------------- * ----------------------------------------- *path cd "c:\dba 2019 summer\good one index\stata15mp" // change the dirctory. Make Stata15 folder the main one clear all set memory 80m // set stata memory for this study. Not necessary for stata 15 *----------------------------------- *-> 2.1 define event date *----------------------------------- use eventda, clear drop comnam tsset company_id date sort company_id date by company_id: gen datenum=_n // define new date variale, 1,2,3,... for each company, it starts from 1 and then one more for the following date by company_id: gen target=datenum if date==event_date // define event date, and if it is the event data, target variable will be defined as n egen td = min(target), by(company_id) // extend the observation of the target to give the rest of the observations the same number sot that difference can be calculated gen dif = datenum-td // set zero for the event date as the starting date. This will be used as setting up the event window and esimation window list comp date event_date datenum target td dif in 1/20 /* also need to watch out for the format of date For calendar days: gen difc=date-event_date */ *----------------------------------------------------------- *-> 2.2 define the event window and the estimation window *----------------------------------------------------------- *--------------------------------------------------------------------------- *-2.2.1 define event window [-2, 2] two days before and after the event date by company_id: gen event_window=1 if (dif>=-2 & dif<=2) // set event window egen count_event_obs=count(event_window), by(company_id) // ? *------------------------------------------ *-2.2.2 define estimation window [-60, -30] by company_id: gen estimation_window = 1 if (dif<-30 & dif>=-60) //estimation window so that expected (benchmark) return could be calculated. //total observation for each firm is 360, a year egen count_est_obs = count(estimation_window), by(company_id) //? * if count_est_obs<30, then the firm will be deleted, because there are not sufficient sample to estimate returns *------------------------------------------------------------- *-2.2.3 Seperate evennt window and non-event window by 0 and 1 list comp date target dif *window in 1/30, sep(0) list comp date target dif *window in 290/360, sep(0) replace event_window = 0 if event_window==. replace estimation_window = 0 if estimation_window==. list comp date target dif *window in 1/30, sep(0) list comp date target dif *window in 290/360, sep(0) *--------------------------------------------------------------------------------- *-2.2.4 delete firms with insufficient observations *- event window observations less than five days, those firms will be deleted tab company_id if count_event_obs<5 xtdes if count_event_obs<5, p(0) // calculate the number of firms of such drop if count_event_obs<5 *-observation less than 30 in the estimation window, those firms will be deleted tab company_id if count_est_obs<30 xtdes if count_est_obs<30, p(0) // calculate the number of firms of such; xtdescribe command: use help xtdes to get help file drop if count_est_obs<30 *-summary of the rest of the firms xtdes, p(0) //panel data *----------------------------------- *-> 2.3 calculate returns *----------------------------------- cap drop predicted_return gen predicted_return=. // used for storing the variable for return cap drop id egen id=group(company_id) // redefine firm id as 1,2,3...,for the next loop operation qui tab id local N = r(r) // count the number of firms forvalues i=1(1)`N' { *-run regression in the estimation window qui reg ret market_return if (id==`i' & estimation_window==1) // if you remove qui, you will see the regression results for each firm in th estimation window *-get the return predict p if id==`i' *To calculate predicted values, use the predict command after the regress or newey command *"predict p" This creates a variable “p” of the fitted values of ret; https://www.ssc.wisc.edu/~bhansen/390/stata.pdf *so use predict command, we get the predicted return of the stock, or the expected return of the stock. So we can calculate the abnormal return *-calculate return in the event window replace predicted_return = p if (id==`i' & event_window==1) drop p // results will be kep in the variable: predicted_return, so drop p. } *------------------------------------- *-> 2.4 calculate abnormal return and cumulative abnormal retun *------------------------------------- *- Abnormal Returns gen abnormal_return = ret - predicted_return if event_window==1 *- CAR_id: sum of each firm (sum)(CAR: cumulative abnoral return, the key in event study. *No impact of the event, then CAR =0; CAR>0==> positive impact to stock market, like share repurchase; *CAR<0, negative impact, like reducing dividend sort id date by id: egen CAR_id = sum(abnormal_return) // get CAR, important list id date dif abnormal_return CAR_id if (event_window==1 & id==1) *- CAR_date: sum according distance from event day(sum by date) cap drop CAR_date bysort comp: gen CAR_date = sum(abnormal_return) if event_window==1 list id date dif abnormal_return CAR_date if (event_window==1 & id ==1) * so the above is to get CAR day by day /*-------------------------------------------------------------------------------------------------- * 2.5 hypothesis exam hypothesis: there is a significant impact of the event on the market; CAR is non-zero significantly ---------------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------- *-2.5.1 the significant of the firms' cumulative abnormal return cap drop ar_sd cap drop test_id cap drop sig cap drop pvalue *- t value, the basis of this hypothesis test sort id date by id: egen ar_sd = sd(abnormal_return) // standard deviation gen test_id =(1/sqrt(5))*(CAR_id /ar_sd) // t value, you can find it by browsig the table *- p value gen pvalue = normal(test_id) replace pvalue = 1 - pvalue if test_id>0 replace pvalue = pvalue*2 // two tale p value *-show significant level gen sig = "* " if pvalue <= 0.10 replace sig = "** " if pvalue <= 0.05 replace sig = "***" if pvalue <= 0.01 *-show results gsort -sig list company_id CAR_id test_id pvalue sig if dif==0&sig!="" // dif==0, so this is the event date, and with signifant result gsort -sig list company_id CAR_id test_id sig if dif==-1 & sig!="" //the day before the event, news could be released earlier list company_id CAR_id test_id sig if dif==-2 & sig!="" //two days before the event list company_id CAR_id test_id sig if dif==0 & sig!="" //the day of the event list company_id CAR_id test_id sig if dif==1 & sig!="" //the day after the event list company_id CAR_id test_id sig if dif==2 & sig!="" //two days after the event *Note: this test uses the sample standard deviation. * A less conservative alternative is to use the population standard deviation. * To derive this from the sample standard deviation produced by Stata, multiply ar_sd by the square root of n-1/n; * in our example, by the square root of 4/5. *--------------------------------------------------- *-2.5.2 cumulative abnormal return is significant? *-2.5.2.1 simple sum of return in the event window reg CAR_id, robust // first approach: regression ttest CAR_id=0 // second approach: t test, this is a common way. *Hypothesis: CAR=0? IF CAR=1, for example, use CAR_id=1 *The results show that CAR is signiciantly differ from zero *-2.5.2.2 sumalative abnormal return by date in the event window reg CAR_date if dif==-2, robust noheader reg CAR_date if dif==-1, robust noheader reg CAR_date if dif== 0, robust noheader reg CAR_date if dif== 1, robust noheader reg CAR_date if dif== 2, robust noheader *results of the above show p value of dif=0,1,2 are zero; conclusion: event is significant, lasting two days *but p value of dif=-1, -2 are high, not significant *-conclusion: no news leaked before the event *-a- results reported in a table local j=1 forvalues i = -2(1)2{ dis in g "date = " in y `i' reg CAR_date if dif==`i', robust noheader est store r`j++' } esttab r1 r2 r3 r4 r5, mtitle(-2 -1 0 1 2) *-b- matrix mat A = J(5,5,0) forvalues i = -2(1)2{ qui reg CAR_date if dif==`i', robust local b = _b[_cons] // coefficient mat V = e(V) local se= sqrt(V[1,1]) // standard deviation local t = `b'/`se' // t value local pvalue = normal(`t') if `t'>0{ local pvalue = 1-`pvalue' } local pvalue = `pvalue'*2 mat A[`=`i'+3',1] = (`i',`b',`se',`t',`pvalue') } mat colnames A = date coef se t pvalue mat list A *-c- graph preserve keep id date dif event_window CAR_date keep if event_window == 1 cap drop CAR_t keep if event_window == 1 sort dif by dif: egen CAR_t = mean(CAR_date) keep dif CAR_t duplicates drop twoway connect CAR_t dif restore *-d- dummy variable * refer to Cowan(2005, Evnetus User's Guide, p.78) * Karafiath(1988, Financial Review, 23(3), 351¨C358.) * define dummy variable of event window cap drop dum* tab dif if abs(dif)<4&dif!=3, gen(dum) drop dum1 *-OLS reg ret market_return dum*, robust //check together of the different days around the event *-Cross-section heteroscedasticity qui tsset company_id dif xtgls ret market_return dum*, p(het) *-Consider both cross-section heteroscedasticity and cross-section correlation // xtgls ret market_return dum*, p(c) *----------------------------------------------------------------- *-2.5.4 sign test, another approach, to test significance *you can check the p value for whether the results are significant *----------------------------------------------------------------- *-Statistics J3 = [N^+/N - 0.5]*(2*sqrt{N}) -- N(0,1) *-refer to Campbell, J., A. Lo, A. MacKinlay. * The Econometrics of Financial Markets[M]. * Cambridge Univ Press, 1997. * Overall inspection preserve keep if event_window == 1 qui count if abnormal_return > 0 local Np = r(N) local N = _N local J3 = (`Np'/`N' - 0.5)*2*sqrt(`N') local pvalue = normal(`J3') if `J3' > 0{ local pvalue = 1- `pvalue' } local pvalue = `pvalue'*2 dis in g " J3" _col(8) " = " in y %6.4f `J3' _n /// in g "p-value = " in y %6.4f `pvalue' restore *-Daily exam mat A = J(5,5,0) forvalues i = -2(1)2{ qui count if (dif==`i' & abnormal_return>0 & event_window==1) local Np = r(N) // number of firms with positive abnormal returns qui count if (dif==`i' & abnormal_return!=. & event_window==1) local N = r(N) // total number of firms local J3 = (`Np'/`N' - 0.5)*2*sqrt(`N') local pvalue = normal(`J3') if `J3' > 0{ local pvalue = 1- `pvalue' } local pvalue = `pvalue'*2 mat A[`=`i'+3',1] = (`i', `J3', `pvalue', `Np', `N') } mat colnames A = date J3 p-value N+ N mat list A *---------- over ------------------