本推文由李春涛教授指导,主要向大家介绍事件研究法的stata程序,并为大家讲解一个传奇的命令post。
推文中所使用到的cntrade命令是由中南财经政法大学张璇老师和李春涛老师所编写,具体语法请参考天路——chinafin与cntrade命令。
事件研究是金融学研究必备基本功。事件研究法的基本思想是:设定事件产生影响的时间段为事件窗口(Event Window),计算事件窗口期的日异常收益率(该期实际收益率与不发生事件条件下的收益率的差值)和累计异常收益率,并用这两个指标的统计检验量衡量事件影响的显著程度。
事件研究准备阶段之
事件列表的生成
在做事件研究的时候,我们首先需要有一个事件列表。
所谓事件列表,可以简化成两列数据
股票代码,代表一家公司
日期,代表事件发生的日期
一个事件就是这样子的:
stkcd | date |
000001 | 2015-12-01 |
000002 | 2014-11-03 |
600900 | 2010-10-17 |
一般来说,这个事件来自于一个外部文件,text格式也好,Excel格式也好,总之要读入Stata,为了说明问题,我们现在采取暴力输入的方式:
clear
input stkcd str10 Eventdate
2 "2014-04-14"
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内存中只能装进去一个数据文件,要做事件研究,我们还需要交易数据,这可怎么办呢?
对于这种情况,我们可以把这个事件列表保存到矩阵中,然后清空内存中的数据,这样就可以读入交易数据了。
整个过程如下:
clear
input stkcd str10 Eventdate
2 "2014-04-14"
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)
当然,以上的过程,我们不仅输入了事件数据,还把本来是字符串的日期翻译成了Stata的Elapse Date,这个Elapse Date,实质上是一个整数。
现在,我们已经把事件列表存储到矩阵event里面了,这个矩阵有`N’行,2列,第一列是股票代码,第二列是日期。
事件研究准备阶段之
数据获取
要想对单个事件进行事件研究,我们需要这家公司事件前后的个股收益率数据和市场收益率数据,这两个数据可以通过两个命令获得,cnindex和cntrade。
cntrade可以获取上市公司历史交易数据,包括每天的收益率。
比如执行如下的命令可以得到万科上市第一天到今天的每天交易信息:
cntrade 2
cnindex是Beijing Idata Education&Technology Co., Ltd的Zhiyong Li根据我们的cntrade写的命令,可以方便地获得指数的日数据(小编提醒大家注意,cnindex目前还不能在stata14中使用,不过在13版大家可以放心使用哦)。
比如:cnindex 000300,path("D:/事件研究/") 可以帮你获得沪深300指数的日数据。
使用者两个命令之前,你必须得安装了他们,安装的方法是:
ssc install cntrade
ssc install cnindex
安装之前最好检查一下是否已经安装了,检查是否安装了,可以用命令which。
以cntrade为例,步骤如下:
cap which cntrade
if _rc!=0{
ssc install cntrade
}
所以在事件研究的准备阶段,我们可以先检查一下是否安装了这两个命令,再暴力地输入事件列表。整个准备阶段过程如下:
clear
capture mkdir "D:/事件研究/"
cap which cnindex
if _rc!=0{
ssc install cnindex
}
cap which cntrade
if _rc!=0{
ssc install cntrade
}
cnindex 000300, path("D:/事件研究/") /*下载沪深三百指数数据*/
keep date rit
rename rit rmt
sort date
save "D:/事件研究/index.dta",replace
*******Events
clear
input stkcd str10 Eventdate
2 "2014-04-14"
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)
单个事件的事件研究
以万科为例
1、确定事件
现在我们对一个事件E进行事件研究,假定这个事件E发生在万科身上,发生的日期是2015-10-20。
我们将这个日期翻译成Stata的日期格式并存储在一个local date里:
local date = date("2015-10-20","YMD")
2、准备数据
下面开始准备数据:
cntrade 2 /*获得万科的数据*/
cnindex 000300 /*获得沪深300指数的数据*/
这些数据获得后我们需要根据自己的研究目的对数据进行处理,删除无用数据,并对数据进行合并,准备数据阶段过程如下:
clear
cntrade 2, path("D:/事件研究/")
keep stkcd date rit
destring rit, force replace
replace rit = rit/100
drop in 1
sort date
merge date using "D:/事件研究/index.dta", nokeep
drop _m
order stkcd date rit rmt
此时,我们的数据包括四个变量:
stkcd date rit rmt
3、定义事件期与回归
我们需要构造一个相对的时间变量time,在事件日等于0,事件前为-1,-2, -3, ……-200,事件后为1,2,3,……
我们可以将内存中的数据截断成两个,事件前的按日期倒排序,添加时间变量time=-_N,事件日以后的正排序,添加时间变量time=_N-1。整个过程如下:
clear
cntrade 2, path("D:/事件研究/")
keep stkcd date rit
destring rit, force replace
replace rit = rit/100
drop in 1
sort date
merge date using "D:/事件研究/index.dta", nokeep
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"
现在我们内存中有了这个事件E前后的日数据,包括事件前200天及事件后10天,共211个交易日的日数据。
假定估计窗口是(-200,-10),事件窗口是(-3,10)
在估计窗口做回归:
qui reg rit rmt if time<=-10
在事件窗口进行预测:
predict AR if time>=-3, r
然后只保留预测范围内的数据:
keep if time>=-3
然后累加:
sort time
gen CAR = sum(AR)
现在,我们就有了这样的一个表格了:
4、邮寄信息
我们可以将上表中的信息装到信封中寄出去。在这里,我们要用到一个数据整理的法宝——post命令
首先,我们来看一下要邮寄那些信息:
local stkcd = stkcd[1]
local CAR1 = CAR[1]
local CAR2 = CAR[2]
local CAR3 = CAR[3]
local CAR4 = CAR[4]
local CAR5 = CAR[5]
local CAR6 = CAR[6]
local CAR7 = CAR[7]
local CAR8 = CAR[8]
local CAR9 = CAR[9]
local CAR10 = CAR[10]
local CAR11 = CAR[11]
local CAR12 = CAR[12]
local CAR13 = CAR[13]
local CAR14 = CAR[14]
接着,定义邮局,即信息接收地址:
capture postclose event
postfile event stkcd CAR1 CAR2 CAR3 CAR4 CAR5 CAR6 CAR7 CAR8 CAR9 CAR10 CAR11 CAR12 CAR13 CAR14 using "D:/事件研究/事件研究.dta",replace
最后,我们就要开始邮寄信息啦!把经过事件研究后的我们所需要的信息装进信封,调用邮局寄出去吧!
post event (`stkcd') (`CAR1') (`CAR2') (`CAR3')
(`CAR4') (`CAR5') (`CAR6') (`CAR7') (`CAR8')
(`CAR9') (`CAR10') (`CAR11') (`CAR12')
(`CAR13') (`CAR14')
多个事件的事件研究
如果我们要对多个事件进行事件研究,可以将上述过程套用一个循环。下面我们将这个过程封装起来,在循环中进行事件研究,每个事件有一个id, 循环次数就是矩阵event的行数`N’。
整体封装起来就是下面的过程:
******download index *******************
clear
capture mkdir "D:/事件研究/"
cap which cnindex
if _rc!=0{
ssc install cnindex
}
cap which cntrade
if _rc!=0{
ssc install cntrade
}
cnindex 000300, path("D:/事件研究/")
keep date rit
rename rit rmt
sort date
save "D:/事件研究/index.dta",replace
*******Events
clear
input stkcd str10 Eventdate
2 "2014-04-14"
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
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
forval i=1/`N' {
local date = scalar(event[`i',2])
local stkcd = scalar(event[`i',1])
dis `stkcd'
*生成rit(计算个股日收益率)
clear
cntrade `stkcd', path("D:/事件研究/")
keep stkcd date rit
destring rit, force replace
replace rit = rit/100
drop in 1
sort date
merge date using "D:/事件研究/index.dta", nokeep
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
local CAR1 = CAR[1]
local CAR2 = CAR[2]
local CAR3 = CAR[3]
local CAR4 = CAR[4]
local CAR5 = CAR[5]
local CAR6 = CAR[6]
local CAR7 = CAR[7]
local CAR8 = CAR[8]
local CAR9 = CAR[9]
local CAR10 = CAR[10]
local CAR11 = CAR[11]
local CAR12 = CAR[12]
local CAR13 = CAR[13]
local CAR14 = CAR[14]
post event (`i') (`stkcd') (`CAR1') (`CAR2')
(`CAR3') (`CAR4') (`CAR5') (`CAR6') (`CAR7')
(`CAR8') (`CAR9') (`CAR10') (`CAR11')
(`CAR12') (`CAR13') (`CAR14')
}
postclose event
use "D:/事件研究/事件研究.dta", clear
以上,就是本次推文的主要内容啦!
有句话是酱婶儿说的:
不要相信“等待遇到合适的人”这种鬼话,比如你等一杯生米,它不能自己变成熟饭。
所以,如果您对stata还有疑问,那为什么不主动出击呢?!!!关注我们,大神为您传道授业解惑也!
编辑/强宇曦
那些让你具有高手气场的黑科技:
此外,欢迎大家踊跃投稿,介绍一些关于stata的数据处理和分析技巧。
长按二维码关注爬虫俱乐部!
微信扫一扫
关注该公众号