阅读:0
听报道
今年疫情出现多地散发,对上市公司股价,会有短期影响吗?部分行业出台了监管政策,对相关公司股价,会有短期冲击吗?事件分析是研究此类问题的一个标准方法。
用Stata实现事件分析法,已经有标准的程序,但是只能处理已经整理好格式的数据。在实际问题中,如何获取原始数据,如何将原始数据整理成标准格式,是一个难点。本文不具体介绍事件分析的原理,主要是讨论如何编程实现。
具体而言,本文讨论的问题是:今年7月20日南京开始出现疫情时,对江苏省上市公司的股价是否有冲击?原始数据从Wind获得。其他问题的分析类似。
第一步:从Wind获得原始数据
路径:Wind—股票—多维数据—行情序列,或者直接输入HPS
另外添加参考指数代码,比如沪深300等
选择指标处打勾涨跌幅
开始日期根据事件日调整
输出方式选择多股输出(时间*品种)
也可以用Excel的Wind插件下载数据,总的来说,下载后的数据如下格式:
第二步:提取个股代码,并单独一列
我们将个股的股票代码的数字提取出来,并作为单独一列,附于最右侧
然后将数据复制到Stata中
第三步:整理成事件研究的数据格式
复制数据后,我们发现日期是红色字体,即文本格式,其实最后一列的个股代码也是文本格式,我们首先要将所有数据转换成数字格式。
// 程序中的替换数据,必须是数值型变量,所以需要将所有变量转换成数值型
gen time = date(var1,"YMD") // 将交易日转换成日期变量
format time %dCY-N-D
// var542取决于数据本身
destring var542, replace // 将wind代码转换成数值型
然后我们使用一个双重循环,把原始数据整理成事件研究的格式,跟面板数据分析的格式很像。
事件日我们选择2021年7月20日。
set obs 91630 //设置样本量,539(公司数)* 170(时间数)
gen ret = . //设置合并后的个股回报率
gen market_return = . //设置合并后的市场回报率
gen company_id = . //设置个股的代码
gen date = . //设置交易日
gen event_date = . // 设置事件日
forvalues i = 2/540 { //539个个股,默认使用变量名var2-var540
forvalues j = 1/170 { //170个交易日
local k = 170*(`i'-2)+`j' //局部宏k,定位合并后变量的位置,注意调整交易日
replace ret = var`i'[`j'] in `k' //将个股回报率并入1列,注意调整变量名
replace market_return = var541[`j'] in `k' //将市场回报率并入1列,注意调整变量名
replace company_id = var542[`i'-1] in `k' //录入个股的代码
replace date = time[`j'] in `k' //录入交易日
replace event_date = date("2021-07-20","YMD") in `k' //录入事件日
}
}
keep ret market_return company_id date event_date //保留相关变量
format date %dCY-N-D
format event_date %dCY-N-D
sort company_id date ret market_return event_date
save data, replace
处理后的数据格式,大概是这样:
第四步:生成估计窗口和事件窗口
一般来说,生成估计窗口和事件窗口有两种方法,一种是按照交易日,一种是按照自然日,我们采取交易日,因为按照自然日可能数据量不够。
sort company_id date //按股票代码、交易日进行排序
by company_id: gen datenum=_n //计数
by company_id: gen target=datenum if date==event_date //识别事件日的计数
egen td=min(target), by(company_id) //扩充事件日的计数
gen dif=datenum-td //生成交易日与事件日的差
drop datenum target td
drop if ret==. // 剔除没有涨跌幅数据的样本
by company_id: gen event_window=1 if dif>=-2 & dif<=2 //事件窗口
egen count_event_obs=count(event_window), by(company_id) //事件窗口样本计数
by company_id: gen estimation_window=1 if dif<-30 & dif>=-60 //估计窗口
egen count_est_obs=count(estimation_window), by(company_id) //估计窗口样本计数
replace event_window=0 if event_window==.
replace estimation_window=0 if estimation_window==.
// 跟前面的事件窗口和估计窗口期对应调整
tab company_id if count_event_obs<5
tab company_id if count_est_obs<30
drop if count_event_obs<5 //删除事件窗口样本小于5的个股
drop if count_est_obs<30 //删除估计窗口样本小于30的个股
第五步:根据估计窗口的系数,测算时间窗口期的异常收益率
我们针对每一只个股,使用估计窗口期测算alpha和beta,然后使用事件窗口期的实际收益和预测收益之差,获得异常收益。
set more off //取消显示限制
gen predicted_return=.
// drop if ret==. & estimation_window==1
egen id=group(company_id) //生成组号
forvalues i=1(1)505 { //手动输入最大组号,505
l id company_id if id==`i' & dif==0 //第一个是字母L的小写,好像这一行不要也行
reg ret market_return if id==`i' & estimation_window==1 //估计窗口期回归
predict p if id==`i' //使用估计窗口期的回归系数预测整体
replace predicted_return = p if id==`i' & event_window==1 //获得事件窗口期的预测值
drop p
}
sort id date
gen abnormal_return=ret-predicted_return if event_window==1 //获得异常收益
by id: egen cumulative_abnormal_return=total(abnormal_return) //获得异常收益累计值
sort id date
by id: egen ar_sd = sd(abnormal_return)
gen test=(1/sqrt(5))*(cumulative_abnormal_return/ar_sd)
list company_id cumulative_abnormal_return test if dif==0
reg cumulative_abnormal_return if dif==0, robust //异常收益累计值是否为零的稳健性检验
最后我们使用异常收益率做一个简单的回归,从回归结果来看,异常收益率显著为正,即7月20日的南京疫情,对江苏上市公司的股价,并没有带来显著的负面影响。
第六步:图形化观察
我们也可以做出异常收益率在时间窗口期的变动图,来更形象的观察变化。
gen cumulative_abnormal_return_date = .
forvalues i=1(1)505{ //手动输入最大组号,505
replace cumulative_abnormal_return_date=sum(abnormal_return) if (id==`i'&event_window==1)
} //每个公司在事件窗口内逐日累加得到的累积回报率
preserve
keep if event_window==1
bysort dif: egen cumulative_abnormal_return_t=mean(cumulative_abnormal_return_date) //计算每天的平均累积超常回报率
keep dif cumulative_abnormal_return_t
duplicates drop //仅保留事件期的观察值
twoway connect cumulative_abnormal_return_t dif, scheme(sj) //绘制时序图
restore
话题:
0
推荐
财新博客版权声明:财新博客所发布文章及图片之版权属博主本人及/或相关权利人所有,未经博主及/或相关权利人单独授权,任何网站、平面媒体不得予以转载。财新网对相关媒体的网站信息内容转载授权并不包括财新博客的文章及图片。博客文章均为作者个人观点,不代表财新网的立场和观点。