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

文摘   教育   2024-11-08 10:02   中国  

👇 连享会 · 推文导航 | www.lianxh.cn

🍓 课程推荐:2024 机器学习与因果推断专题
主讲老师:司继春 (上海对外经贸大学) ;张宏亮(浙江大学)
课程时间:2024 年 11 月 9-10 日 ;16-17日
课程咨询:王老师 18903405450(微信)

 课程特色 · 2024机器学习与因果推断

  • 懂原理、会应用。本次课程邀请了两位老师合作讲授,目的在于最大限度地实现理论与应用的有机结合。为期四天的课程,分成两个部分:第一部分讲解常用的机器学习算法和适用条件,以及文本分析和大语言模型;第二部分通过精讲 4-6 篇发表于 Top 期刊的论文,帮助大家理解各类机器学习算法的应用场景,以及它们与传统因果推断方法的巧妙结合。
  • 以 Top 期刊论文为范例。目前多数人的困惑是不清楚如何将传统因果推断方法与机器学习结合起来。事实上,即便是 MIT 和 Harvard 的大牛们也都在「摸着石头过河」。为此,通过论文精讲和复现来学习这部分内容或许是目前最有效的方式了。张宏亮老师此前在浙江大学按照这一模式教授了「因果推断和机器学习」课程,效果甚佳:学生们能够逐渐建立起研究设计的理念,并在构造识别策略时适当地嵌入机器学习方法。

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


目录

  • 1. 事件研究法

  • 2. 编程的难点

  • 3. Stata 实例

  • 4. 结语

  • 5. 相关推文



温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:

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,事件发生日之前依次标识为 [(, ),  , > 0 ],事件发生日以后依次标识为 [(, ),  , > 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

  • 专题:Stata入门
    • Stata:根据当前日期返回是周几
  • 专题:Stata教程
    • 事件研究法笔记:Stata连享会
  • 专题:数据处理
    • Stata:文字型日期格式的转换
    • Stata数据处理:字符型日期变量的转换
    • 如何处理时间序列中的日期间隔-(with-gaps)-问题?
  • 专题:Stata程序
    • statsby: 不用循环语句的循环
  • 专题:回归分析
    • Stata:短期事件研究法(Event_Study)教程
  • 专题:其它
    • Stata:一文读懂事件研究法Event Study


🍓 课程推荐:2024 机器学习与因果推断专题
主讲老师:司继春 (上海对外经贸大学) ;张宏亮(浙江大学)
课程时间:2024 年 11 月 9-10 日 ;16-17日
课程咨询:王老师 18903405450(微信)

尊敬的老师 / 亲爱的同学们:

连享会致力于不断优化和丰富课程内容,以确保每位学员都能获得最有价值的学习体验。为了更精准地满足您的学习需求,我们诚挚地邀请您参与到我们的课程规划中来。 请您在下面的问卷中,分享您 感兴趣的学习主题或您希望深入了解的知识领域 。您的每一条建议都是我们宝贵的资源,将直接影响到我们课程的改进和创新。 我们期待您的反馈,因为您的参与和支持是我们不断前进的动力。感谢您抽出宝贵时间,与我们共同塑造更加精彩的学习旅程!https://www.wjx.cn/vm/YgPfdsJ.aspx# 再次感谢大家宝贵的意见!

New! Stata 搜索神器:lianxh 和 songbl  GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
  . ssc install lianxh
  . ssc install songbl
👉  使用:
  . lianxh DID 倍分法
  . songbl all

🍏 关于我们

  • 连享会 ( www.lianxh.cn,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。

连享会
连玉君老师团队分享,主页:lianxh.cn。白话计量,代码实操;学术路上,与君同行。
 最新文章