Stata:事件研究法的编程实现

发布时间:2021-08-31 阅读 291

Stata连享会   主页 || 视频 || 推文 || 知乎 || Bilibili 站

温馨提示: 定期 清理浏览器缓存,可以获得最佳浏览体验。

New! lianxh 命令发布了:
随时搜索推文、Stata 资源。安装:
. ssc install lianxh
详情参见帮助文件 (有惊喜):
. help lianxh
连享会新命令:cnssc, ihelp, rdbalance, gitee, installpkg

课程详情 https://gitee.com/lianxh/Course

课程主页 https://gitee.com/lianxh/Course

⛳ Stata 系列推文:

PDF下载 - 推文合集

作者:左祥太 (武汉纺织大学)
邮箱Shutter_Z@outlook.com


目录


1. 事件研究法

事件研究法 (Event Study) 指的是,通过研究事件窗口期资本市场的收益与按照事件估计期所预测的正常收益之差,从而定量化这件事情给公司带来的具体影响。具体地,通过利用正常期间收益的拟合线段来预估事件窗口期的预期收益,从而与实际收益相减产生窗口期内每一天的超额收益 (AR),然后再对超额收益 (AR) 进行求和,便可以得到整个事件窗口期内的累计超额收益 (CAR)。通过对累计超额收益 (CAR) 的分析与检验,便可以计算出整个事件所带来的累计影响。

在财务会计领域,事件研究法一般可以用于研究单一事件 (公司披露、并购绩效、股利政策、政策事件等) 对单一公司或者受到影响的多家公司的影响。但也有学者通过机器学习的方式对多种事件进行探讨研究 (李镁潆和徐美萍,2018)。

本推文将以自行编写的事件研究法实现 do 文档为例,来讲解事件研究法的实现手段。相比于已然存在的事件研究法命令 estudyeventstudy2,自行编写事件研究法的实现命令更有利于我们对事件研究法实现原理以及方式的认识。

2. 编程的难点

想要编写短期事件研究法的有关 do-file,首先要理清以下概念:

  • 事件日 (Event date):被研究事件的发生日;
  • 事件窗口期 (Event window):被研究事件发生日的前后数日 (自行选择);
  • 事件估计期 (Event estimation):用以估计事件窗口期收益的一段时间,一般为事件发生日前 210 个交易日至前 11 个交易日,并且不应与事件窗口期有重合;
  • 正常收益 (Normal returns):在没有发生特定事情情况下的收益,一般通过 Stata 利用个股收益与市场收益率进行 regress 回归之后,通过 predict 命令进行预测;
  • 异常收益 (Abnormal returns,AR):在发生特定事件之后,事件窗口期的个股实际收益与个股正常收益之差;
  • 累计异常收益 (Cumulative abnormal returns,CAR):事件窗口期各交易日异常收益之和。

接着,我们来具体看一下事件研究法的编程难点:

  • 日期清洗:对于日期的清洗,我们需要把事件发生日所在的日期归为 0,事件发生日之前依次标识为 [(t1t2),  t1t2 > 0 ],事件发生日以后依次标识为 [(t3t4),  t3t4 > 0 ]。这样做的好处是可以很方便地一次性完成对后续内容中事件估计期以及事件窗口期的划分,对日期清洗的关键代码如下:
/*在导入数据之后*/
/*本例中设置窗口期为包括事件发生日在内的前后各一天*/

/*获取数据*/
. cnssc install lxhget, replace
. lxhget event_study_data.xlsx, replace
. import excel using "event_study_data.xlsx", clear firstrow

sort code date 
by code: gen date_p1 = _n	
by code: gen date_p2 = date_p1 if date == event_date

//这几行代码是为了分组之后顺序排列并且筛选出事件发生日对应的数字
by code: replace date_p2 = date_p1 if date-event_date<=1 ///
         & date-event_date>=-1

//把窗口期对应的数字全部替换出来
egen date_p3 = mean(date_p2)
gen date_p4 = round(date_p3)

//这两步是为了取出特定事件日所对应的数字,以方便后续做差
gen date_new = date_p1 - date_p4

//到这一步为止,date_new 会表现为上文 (t1,t4)的模式
drop date_p1 - date_p4					
keep if date_new >= -210					
  • 估计期与窗口期的梳理:在完成上述的日期清洗过程之后,我们就需要对日期进行划分,以便在后续的回归以及预测中直接利用 regressif 的方式对事件估计期内的数据进行回归,并对事件窗口期的预计收益进行填充。在 Stata 中,通过使用如下命令完成对事件估计期与事件窗口期地划分:
/*后续命令均在清洗完数据日期的情况下进行*/
/*设定事件估计期*/
gen event_estimation = 1
replace event_estimation = 0 if date_new >= (-1) & date_new <= 1
//上述命令表示产生 event_estimation 并且在事件窗口期 (-1, 1) 内令其为0

/*设定事件窗口期*/
gen event_window = 0
replace event_window = 1 if date_new >= (-1) & date_new <= 1
//上述命令表示产生 event_window 并且在事件窗口期 (-1, 1) 内令其为1
  • 分组回归计算预期收入:这一步比较简单,仅需按照对应的组别与估计期进行回归 (利用 if 进行条件限制) ,随后于窗口期所在日期进行交叉合并 (利用 if 进行条件限制);
/*分组回归预测对应组别窗口期的预期收入*/
egen id = group(code)
egen max_id = max(id)

//这一步是为了看最大的组数	
gen predict_return = .
forvalues i = 1/11 {
  reg market_earn share_earn if id == `i'   ///
      & event_estimation == 1 
  predict p if id == `i'
  replace predict_return = p if id == `i'	///
          & event_window == 1
  drop p
}
  • CAR 的批量导出:回归分析预测 AR 之后,很多小伙伴会发现在计算 CAR 的时候,数据会很多且不容易看,这时就需要对最终的 CAR 值进行如下的处理以批量导出;
/*导出整个窗口期的 CAR */
  by code: gen CAR = CAR_initial[_N]	//保留最后的 CAR
  preserve
    keep code CAR 
    duplicates drop code CAR, force
    save CAR.dta, replace
  restore	
/*使用 preserve 与 restore 便可以在不破坏原始数据的情况下导出所有公司的 CAR,
避免原始数据的破坏有助于后续 T 检验的进行*/
  • T 检验:在完成分组计算 CAR 值的任务后,还需要对 CAR 值进行 T 检验,T 检验的目的是检验 CAR 值是否会显著异于 0,即特定事件所造成的影响到底是否显著。
/*分别对不同组别进行 T 检验后合并所有数据*/
forvalues i = 1/11{
  gen CAR_`i' = CAR_initial if id == `i'
}

//这里的操作是为了后续切片分组 T 检验
forvalues i = 1/11{
  preserve
  keep if id == `i' 
  drop if event_window == 0
  keep id code CAR_`i' 
  ttest CAR_`i' == 0
  gen mean = r(mu_1)				//返回均值
  gen ttest = r(p)				//返回 T 检验显著水平
  save `i'.dta, replace
  restore
}

//在不破坏原始数据的情况下分组进行 T 检验,并保存在不同的 dta 文件当中
use 1.dta, clear
forvalues i = 2/11{
  append using `i'.dta
}
forvalues i = 1/11{
  drop CAR_`i'
}
duplicates drop id, force
save Ttest.dta, replace

上述五点内容便是实现 Stata 事件研究法编程的重难点内容,下面不妨对上述内容进行组合,从而完成一份完整的事件研究法的计算操作。

3. Stata 实例

下面我们利用 A 股上市的纺织企业在 2021 年 3 月 8 日至 2021 年 3 月 31 日之间的个股收益率与市场收益率为例进行上述事件研究法的分析,其中假定事件日为 2021 年 3 月 24 日。

. /*获取数据*/
. cnssc install lxhget, replace
. lxhget event_study_data.xlsx, replace
. import excel using "event_study_data.xlsx", clear firstrow
 
. /* 
> Notes:
>   code:       股票代码
>   date:       对应交易日
>   share_earn: 个股收益率
>   event_date: 事件发生日 (假定为 2021 年 3 月 24 日)
>                倘若事件发生在非交易日,则需将其归入最近的交易日
>   market_earn:市场收益率
> */
 
. des 
Contains data
  obs:           341                          
 vars:             5                          
---------------------------------------------------------------
              storage   display    value
variable name   type    format     label      variable label
---------------------------------------------------------------
code            str6    %9s                   code
date            int     %td..                 date
share_earn      double  %10.0g                share_earn
event_date      int     %td..                 event_date
market_earn     double  %10.0g                market_earn
---------------------------------------------------------------
Sorted by: 
     Note: Dataset has changed since last saved.

在导入数据之后,我们便需要首先对数据日期进行清洗,清洗数据之前请务必保证变量 date 中的数据为日期型 %td。下面开始对数据日期进行清洗:

. /*日期清洗*/
. sort code date 
. by code: gen date_p1 = _n       
. by code: gen date_p2 = date_p1 if date == event_date
. by code: replace date_p2 = date_p1 if date-event_date<=1 ///
>                  & date-event_date>=-1
. egen date_p3 = mean(date_p2)
. gen date_p4 = round(date_p3)
. gen date_new = date_p1 - date_p4
. drop date_p1 - date_p4 
//执行完上述操作之后,本例中产生的新变量 data_new 会排列为 (-12, 18) 的数字

完成对数据日期的初步清洗之后,就需要设置事件估计期与事件窗口期,如前文述所提及内容,应当设置两个变量:event_estimation 在事件估计期内取 1,在其余时间内取 0;event_window 在事件窗口期内取 1,在其余时间内取 0。这样做的好处首先是方便后续对个股进行带有 if 限制的回归,再就是方便取交集陈列 AR 。

. gen event_estimation = 1
. replace event_estimation = 0 if date_new >= (-1) & date_new <= 1
. gen event_window = 0
. replace event_window = 1 if date_new >= (-1) & date_new <= 1

至此,已经完成了所有的数据清洗以及对事件估计期、事件窗口期的划分,接下来就需要分组回归,利用事件估计期的个股收益率与市场收益率进行 OLS 回归,再对事件窗口期的预期收益进行预测:

. egen id = group(code) //对 code 进行分组,用虚拟变量 id 作为股票的标识代码
. egen max_id = max(id) //查看分组的最大值,并记录下来用以循环
. gen predict_return = .
. forvalues i = 1/ 11 {
  2.	reg market_earn share_earn if id == `i' & event_estimation == 1 
  3.    predict p if id == `i'
  4.    replace predict_return = p if id == `i' & event_window == 1
  5.    drop p
  6. }

/*在完成对 11 个组别的分组回归之后,便可以打开数据编辑器,
发现 predict_return 这一变量在事件窗口期的预期收益都已经被填充完毕了*/

接下来就是计算 AR 与 CAR 以及导出 CAR 值:

. gen AR= share_earn - predict_return
. bysort code(date): gen CAR_initial = sum(AR)  
. by code: gen CAR = CAR_initial[_N]  
. preserve   
. keep code CAR 
. duplicates drop code CAR, force
. save CAR.dta, replace
. list in 1/5, noobs
  +--------------------+
  |   code         CAR |
  |--------------------|
  | 000158    .6552294 |
  | 000726   -3.471135 |
  | 000850    2.343248 |
  | 002042   -2.396834 |
  | 002083   -2.122637 |
  +--------------------+
. restore

经过上述操作我们便完成了对 CAR 的批量导出,如果后续仍需要利用 CAR 的数字,仅需对 CAR.dta 使用 merge 命令进行合并即可。

下面将会对各个股票的 CAR 值进行 T 检验以判断特定事件是否具有显著影响:

. //利用上文提到的命令进行
. forvalues i = 1/11{
  2.     gen CAR_`i' = CAR_initial if id == `i'
  3. }

. forvalues i = 1/11{
  2.     preserve
  3.     keep if id == `i' 
  4.     drop if event_window == 0
  5.     keep id code CAR_`i' 
  6.     ttest CAR_`i' == 0
  7.     gen mean = r(mu_1)     //返回均值
  8.     gen ttest = r(p)       //返回 T 检验显著水平
  9.     save `i'.dta, replace
 10.     restore
 11. }

 . use 1.dta, clear
. forvalues i = 2/11{
  2.     append using `i'.dta
  3. }
  
. forvalues i = 1/11{
  2.     drop CAR_`i'
  3. }
  
. duplicates drop id, force
. save Ttest.dta, replace

. list in 1/5, noobs
  +------------------------------------+
  |   code   id        mean      ttest |
  |------------------------------------|
  | 000158    1   -.8955065   .4369857 |
  | 000726    2   -2.256298   .0657222 |
  | 000850    3   -.3159555   .8345436 |
  | 002042    4    -1.12922   .2710876 |
  | 002083    5   -2.044071   .0104669 |
  +------------------------------------+

到这里为止,我们便完成了事件研究法的所有流程,这时工作路径下的文件夹中将会出现 1.dta ~ n.dta 这些文件,n 为您的股票总个数。这些都是工作产生的临时文件,可以用 erase 进行删除,仅需保留 CAR.dta 与 Ttest.dta 即可。这两个 .dta 文件当中都保留了对应的股票代码,后续如果需要继续使用的话,仅需要利用 merge 命令按照股票代码进行合并即可。

4. 结语

事件研究法 (Event Study) 是一种在会计领域和金融领域都比较常见的研究方法,得益于部分学者的努力,我们可以使用 estudyeventstudy2 来进行一键式的傻瓜操作,但利用编程的方式来实现,更有利于加深我们对事件研究法细节的掌握,以及锻炼我们对 Stata 的熟练程度。

5. 相关推文

Note:产生如下推文列表的 Stata 命令为:
lianxh 事件研究 日期 循环, m
安装最新版 lianxh 命令:
ssc install lianxh, replace

相关课程

免费公开课

最新课程-直播课

专题 嘉宾 直播/回看视频
最新专题 文本分析、机器学习、效率专题、生存分析等
研究设计 连玉君 我的特斯拉-实证研究设计-幻灯片-
面板模型 连玉君 动态面板模型-幻灯片-
面板模型 连玉君 直击面板数据模型 [免费公开课,2小时]
  • Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。

课程主页

课程主页

关于我们

  • Stata连享会 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 连享会-主页知乎专栏,400+ 推文,实证分析不再抓狂。直播间 有很多视频课程,可以随时观看。
  • 公众号关键词搜索/回复 功能已经上线。大家可以在公众号左下角点击键盘图标,输入简要关键词,以便快速呈现历史推文,获取工具软件和数据下载。常见关键词:课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法

连享会小程序:扫一扫,看推文,看视频……

扫码加入连享会微信群,提问交流更方便

✏ 连享会-常见问题解答:
https://gitee.com/lianxh/Course/wikis

New! lianxh 命令发布了:
随时搜索连享会推文、Stata 资源,安装命令如下:
. ssc install lianxh
使用详情参见帮助文件 (有惊喜):
. help lianxh