有问题,不要怕!点击推文底部“阅读原文”下载爬虫俱乐部用户问题登记表并按要求填写后发送至邮箱statatraining@163.com,我们会及时为您解答哟~
喜大普奔~爬虫俱乐部的github主站正式上线了!我们的网站地址是:https://stata-club.github.io,粉丝们可以通过该网站访问过去的推文哟~
重磅推出:
爬虫俱乐部之前推出的线下培训,得到了各位老师的一致好评。为了更加方便大家学习,满足更多Stata用户的学习需求,爬虫俱乐部近期即将推出在线直播课程,敬请大家关注!
之前的推文《免费事件研究,一片片从邮局寄来》中,我们曾向大家介绍过事件研究的Stata程序,温故而知新!本篇推文对该程序进行了更新和完善,今天再和小编一起学习一下金融学研究必备基本功—事件研究。
事件研究法的基本思想是:事件研究是针对某一个事件窗口(Event Window)来计算累计超额收益率(CAR),累计超额收益率是时间窗口期的实际收益与正常收益差值的累计相加。正常收益是使用CAPM模型或者FAma-French三因素模型对事件前的一段区间(Estimation Window)进行估计参数,然后计算事件窗口期没有发生此事件的正常收益。
一、事件研究准备阶段之事件列表的生成
首先我们要确定如下的事件列表,说明每只股票所对应事件发生的时间:

一般来说,这个事件列表来自于一个外部文件(比如text、EXCEL),需要读入Stata。为了简单说明问题,我们采取直接输入的事件列表:
clear
capture mkdir D:/事件研究/
input stkcd str10 Eventdate
2 "2015-10-20"
600900 "2015-04-14"
28 "2016-04-14"
600000 "2016-04-14"
601898 "2016-04-14"
601988 "2016-04-14"
601666 "2016-04-14"
end
事件列表列举后, 我们需要计算事件窗口期的股票累计超额收益率。由于Stata内存中只能读入一个数据文件,事件列表读入后,怎么读入其他的数据?对于这种情况,我们可以把这个事件列表保存到矩阵中,然后清空内存中的数据,读入交易数。当需要事件列表时只需调用矩阵即可。过程如下:
set matsize 500
cap gen Eventdate1=date(Eventdate,"YMD")
drop Eventdate
rename Eventdate1 Eventdate
format Eventdate %dCY-N-D // 日期从字符串型转换为数值型
sort stkcd Eventdate // stkcd、Eventdate 分表为事件列表矩阵的两列
local N=_N // N为矩阵的行数
mkmat stkcd Eventdate, mat(event) // 事件列表数据存储为名为event的矩阵
二、事件研究准备阶段之获取收益率数据
目前,我们已经把事件列表存储到矩阵event里,该矩阵为N行2列,第一列是stkcd股票代码,第二列是evendate事件日期。接下来,可以直接读入股票的交易数据。
之前的推文《免费事件研究,一片片从邮局寄来》中,使用了cntrade命令获取个股收益率数据,市场收益率数据则需用cnindex命令获取。现在,cntrade命令经过爬虫俱乐部的更新后,可以直接下载市场收益率了,只需添加index选项即可,详见推文《cntrade也可以下载股指数据啦》;另外,cntrade更新后下载得到的收益率数据为数值百分比,不需要从字符型转换数值型。
首先,检查我们是否已经安装了cntrade,如果没有需要按照以下,步骤如下:
cap which cntrade
if _rc!=0{
ssc install cntrade
}
获取沪深300指数历史市场报价数据:
cntrade 000300, index
keep date rmt
sort date
save "D:/事件研究/index.dta",replace
获取个股的历史收益数据(以万科股票000002为例):
clear
cntrade 2, path("D:/事件研究/")
keep stkcd date rit // 只保留我们所需的股票代码日期和收益率信息
sort date

使用merge命令通过date变量将个股收益率和市场收益率横向合并为一个文件,得到每日的个股收益率和市场收益率信息
merge 1:1 date using "D:/事件研究/index.dta"
drop _m
order stkcd date rit rmt

此时,我们的数据包括四个变量:stkcd date rit rmt
三、单只股票单个事件的事件研究
1. 定义事件期
我们需要构造一个相对的时间变量time,在事件日等于0,事件前为-1,-2, -3,... ,-200,事件后为1,2,3,……
我们可以将内存中的数据截断成两个,事件前的按日期倒排序,添加时间变量time=-_N,事件日以后的正排序,添加时间变量time=_N-1。整个过程如下:
根据事件列表,2015-10-20当日的事件E是万科的,可以确定事件日为2015-10-20:
local date = date("2015-10-20","YMD")
定义事件日`date’ 前的时间变量为-1,-2,-3...:
preserve
keep if date<`date' // 保留事件日前的数据
gsort -date // 按日期倒排序
gen time=-_n // 生成事件变量为行数序号的相反数
keep if time>=-200 // 保留事件日前200天的数据
save "D:/事件研究/pre_event.dta", replace
restore
这里用到的preserve、restore命令在之前的推文《preserve restore---Stata的起死回生之术》中介绍过,方便我们将数据分为事件前、事件后。

生成事件日后的时间变量0,1,2,........:
keep if date>=`date' // 保留事件日及其之后的数据
sort date
gen time = _n-1 // 生成时间变量,事件日为0,事件后为1,2,3...
keep if time<=10

事件日前后数据合并:
append using "D:/事件研究/pre_event.dta"
经过处理,现在我们得到了包括事件前200天及事件后10天的交易数据,共211天。
2. 计算异常收益率
假定估计窗口是(-200,-10),事件窗口是(-3,10)
在估计窗口用个股收益率(rit)对市场交易率(rmt)做回归,并估计事件窗口的异常收益率:
qui reg rit rmt if time<=-10
predict AR if time>=-3, r
保留事件窗口期的数据,使用sum命令累加得到累计超额收益率:
keep if time>=-3
sort time
gen CAR = sum(AR)
keep stkcd time CAR

四、通过循环对矩阵event存储的事件进行研究
矩阵event的`N’行2列是所有的事件,需要对每一行的事件进行分析,这时需要我们对行号进行循环,来达到事件列表里所有事件进行研究:
forval i=1/`N' { // 对矩阵行号进行循环
local date = scalar(event[`i',2]) // 提取该行的事件日期
local stkcd = scalar(event[`i',1]) // 提取该行的股票代码
dis `stkcd'
clear
cntrade `stkcd', path("D:/事件研究/")
keep stkcd date rit
drop in 1
sort date
merge m:m date using "D:/事件研究/index.dta"
drop _m
order stkcd date rit rmt
preserve
keep if date<`date'
gsort -date
gen time=-_n
keep if time>=-200
save "D:/事件研究/pre_event.dta", replace
restore
keep if date>=`date'
sort date
gen time = _n-1
keep if time<=10
append using "D:/事件研究/pre_event.dta"
qui reg rit rmt if time<=-10
predict AR if time>=-3, r
keep if time>=-3
sort time
gen CAR = sum(AR)
keep stkcd time CAR
save `i’.dta
}
五、post寄出事件研究的累计超额收益率
通过上述的程序,我们得到了事件列表中所有事件的累计超额收益率,如何把这些信息整理到一个文件中呢?如果将每次事件研究得到的数据文件一一合并起来,就太过繁琐了,更有效的办法是使用数据整理法宝级命令—post,每次事件研究后,直接把需要的累计超额收益率的数据邮寄到特定的地址。
首先,我们把需要的数据信息放入local宏里,包括id(事件列表行号`i’)stkcd(股票代码)CAR1—CAR14(事件窗口期14天的累计异常收益率), 在循环过程中,行号和股票代码已经被放入宏中,因此我们只需要把14天累计异常收益率放进宏中即可。
forvalues m=1(1)14{
local CAR`m’ = CAR[`m’]
}
然后再通过post命令,把宏里的数据信息装入信封寄出即可。
先定义邮件,设定好接收地址:
postfile event id stkcd CAR1 CAR2 CAR3 CAR4 CAR5 CAR6 CAR7 CAR8 ///
CAR9 CAR10 CAR11 CAR12 CAR13 CAR14 ///
using "D:/事件研究/事件研究.dta",replace
再用post命令将我们循环得到的多次事件研究的累计超额收益率数据按照定义的格式邮寄到我们设定好的地址:
post event (`i') (`stkcd') (`CAR1') (`CAR2') ///
(`CAR3') (`CAR4') (`CAR5') (`CAR6') (`CAR7') ///
(`CAR8') (`CAR9') (`CAR10') (`CAR11') ///
(`CAR12') (`CAR13') (`CAR14')
一份份超额收益率的数据寄出后,我们关闭邮件系统即可:
postclose event
use D:/事件研究/事件研究.dta, 打开事件研究文件,每次事件研究得到的CAR值一目了然:

全部程序:
clear
capture mkdir "D:/事件研究/"
cap which cntrade
if _rc!=0{
ssc install cntrade
}
cntrade 000300, index
keep date rmt
sort date
save "D:/事件研究/index.dta",replace
capture postclose event
postfile event id stkcd CAR1 CAR2 CAR3 CAR4 ///
CAR5 CAR6 CAR7 CAR8 CAR9 CAR10 CAR11 CAR12 CAR13 CAR14 using "D:/事件研究/事件研究.dta",replace
*******Events
clear
input stkcd str10 Eventdate
2 "2015-10-20"
600900 "2015-04-14"
28 "2016-04-14"
600000 "2016-04-14"
601898 "2016-04-14"
601988 "2016-04-14"
601666 "2016-04-14"
end
set matsize 500
cap gen Eventdate1=date(Eventdate,"YMD")
drop Eventdate
rename Eventdate1 Eventdate
format Eventdate %dCY-N-D
sort stkcd Eventdate
*******Events Matrix
local N=_N
mkmat stkcd Eventdate, mat(event)
**save the event into a matrix called event
forval i=1/`N' {
local date = scalar(event[`i',2])
local stkcd = scalar(event[`i',1])
dis `stkcd'
clear
cntrade `stkcd', path("D:/事件研究/")
keep stkcd date rit
drop in 1
sort date
merge m:m date using "D:/事件研究/index.dta"
drop _m
order stkcd date rit rmt
preserve
keep if date<`date'
gsort -date
gen time=-_n
keep if time>=-200
save "D:/事件研究/pre_event.dta", replace
restore
keep if date>=`date'
sort date
gen time = _n-1
keep if time<=10
append using "D:/事件研究/pre_event.dta"
qui reg rit rmt if time<=-10
predict AR if time>=-3, r
keep if time>=-3
sort time
gen CAR = sum(AR)
keep stkcd time CAR
forvalues m=1(1)14{
local CAR`m’ = CAR[`m’]
}
post event (`i') (`stkcd') (`CAR1') (`CAR2') ///
(`CAR3') (`CAR4') (`CAR5') (`CAR6') (`CAR7') ///
(`CAR8') (`CAR9') (`CAR10') (`CAR11') ///
(`CAR12') (`CAR13') (`CAR14') ///
}
postclose event
use D:/事件研究/事件研究.dta,clear
注:此推文中的图片及封面(除操作部分的)均来源于网络!如有雷同,纯属巧合!
以上就是今天给大家分享的内容了,说得好就赏个铜板呗!有钱的捧个钱场,有人的捧个人场~。另外,我们开通了苹果手机打赏通道,只要扫描下方的二维码,就可以打赏啦!
应广大粉丝要求,爬虫俱乐部的推文公众号打赏功能可以开发票啦,累计打赏超过1000元我们即可给您开具发票,发票类别为“咨询费”。用心做事,只为做您更贴心的小爬虫。第一批发票已经寄到各位小主的手中,大家快来给小爬虫打赏呀~
文字编辑:吴晓蔓
技术总编:刘贝贝
往期推文推荐:
2.hello,MySQL--Stata连接MySQL数据库
3.hello,MySQL--odbcload读取MySQL数据
关于我们
微信公众号“爬虫俱乐部”分享实用的stata命令,欢迎转载、打赏。爬虫俱乐部是由李春涛教授领导下的研究生及本科生组成的大数据分析和数据挖掘团队。
此外,欢迎大家踊跃投稿,介绍一些关于stata的数据处理和分析技巧。
投稿邮箱:statatraining@163.com
投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿”+“推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到关于stata分析数据的问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。


