财新传媒 财新传媒

阅读: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

推荐

经纬

经纬

357篇文章 5天前更新

经济学博士

文章