Bubbles for Fama(2018, JFE)的泡沫识别策略:应用于中国股票市场

今年9月的JFE发了篇评价Fama“价格变动是理性的,价格飙升不等同于价格泡沫”观点的文章,核心结论有:
i)行业层面,价格的剧烈上扬并不表示未来资产收益的降低(即动量效应是存在的);
ii)但是,价格的急增与未来股票崩盘有显著正相关;
iii)价格波动、新股发行、BP、EP、股价上升的路径,都能具有预测未来股价崩盘的效用;
iv)上述因子可以对泡沫做出有效择时。

这篇文章给出的识别泡沫和崩盘的策略是这样的:

1.分析单位是一个行业(要求每个行业中至少包含10个公司)

2.将行业价值加权回报率在过去两年内超过100%或者raw return在过去五年内超过50%定义为行业泡沫

3.将泡沫启动后的任意两年内回报率下降超过40%定义为崩盘

4.这种识别方法意味着同一个两年时间段内可能会有几个不同的泡沫启动,应对方法是只选取最先开始的一个泡沫,直到两年结束才开始标记该行业的下一个泡沫

刚好我老板最近对泡沫很感兴趣,于是大手一挥就让我用中国市场的数据跑一跑看看能不能从中国市场的泡沫和崩盘里找出些有趣的话题,这里把我今天跑数据的笔记记录一下,留作以后备查。(在对中国股票市场的复制中,阈值和回报率衡量方式有一定的调整,并不完全一样。)

原始数据是来自CSMAR所有的个股月交易数据,1990-2018年,一共 596,789  个观测,先describe一波

数据描述见CSMAR的说明:http://www.gtarsc.com/SingleTable/DataBaseInfo?nodeid=4176

第一步是将月个股交易数据转变为月行业交易数据,这一步用的是流通市值加权。

use "/Users/mengjiexu/bubble/mondata.dta"

*-将字符串的交易月份转变为date格式
g trdmntcode=monthly(trdmnt,"YM")
format trdmntcode %tm

*- 计算行业月流通市值加权收益率
bys trdmnt nnindcd:egen sxq=sum(mretwd*msmvosd)
bys trdmnt nnindcd:egen totalvosd=sum(msmvosd)
bys trdmnt nnindcd:gen wr=sxq/totalvosd
drop sxq totalvosd
keep trdmnt year wr nnindcd nindnme trdmntcode
duplicates drop nnindcd trdmnt,force

第二步是需要算24个月窗口期的行业累计收益率和Buy and hold return,这里的难点是对于每一个月都要算其未来24个月的收益率,好在我发现了一个超棒的包:rangestat,刚好可以用来解决这个需求。rangestat的help文档里写它的功能是“Generate statistics using observations within range”,亲测了一波觉得这个说明写得特别实在。这里计算buy and hold收益率的一个Tip就是可以将连乘转变为连加形式,然后再用自然对数减1就成,数学上可以证明是等价的,比如你的收益率是r,那么exp(total(ln(1+r))-1就是窗口期的buy and hold收益率(total即对窗口期内的ln(1+r)求和)。

sort nnindcd trdmnt
by nnindcd:g l=_n
g t=ln(wr+1)
*- 
计算滚动buy and hold收益率
rangestat (count) t (sum) t (obs) t, by(nnindcd) interval(l 1 24)
g R = exp(t)-1
*- 计算累计收益率
rangestat (sum) wr, by(nnindcd) interval(l 1 24)

第三步是根据buy and hold return 或raw return的阈值保留可能的泡沫时间节点,然后去除交叠的泡沫。去除交叠泡沫这点比较tricky,首先你需要把字符串格式的交易时间转变成stata数字编码的date格式,然后才好对月份进行比大小和做加减。转成date格式后,一步就能完成去除交叠泡沫:by nnindcd:drop if trdmntcode[_n+1]<trdmntcode[_n]+24。

preserve
keep if wr_sum>=2.7 
sort nnindcd l
*- 
去除交叠的bubble
by nnindcd:drop if trdmntcode[_n+1]<trdmntcode[_n]+24 
*- 标记bubble
g flag=1
sort nnindcd trdmntcode
save "/Users/mengjiexu/bubble/bubbleexist.dta"

 

第四步是就是对最终选出的泡沫发生时间节点做标记(flag=1),然后merge回原始数据截取泡沫发生后该行业的回报率,这里用preserve和retsore会减少一些merge的冗余步骤。这里的一个小挑战是很难区分泡沫发生节点之前和之后的月份,所以先按行业年份排了序得到组内每个观测的rank,然后组内标记出泡沫发生那个月份的序号作为benchmark,将该组内其他观测的rank减去benchmark就可以得到每个组内所有观测相对于泡沫发生月份的gap,泡沫发生之后的月份即gap大约0的观测。

restore
sort nnindcd trdmntcode
merge nnindcd trdmntcode using bubbleexist
drop _merge

*- 保留标记bubble发生后的月数据
sort nnindcd trdmntcode
by nnindcd: g rank=_n
by nnindcd: g bench=rank if flag==1
replace bench=0 if bench==.
by nnindcd: egen rbench=sum(bench)
drop bench
g gap=rank-rbench
keep if gap>=0 
keep if rbench!=0

最后一步就是画图啦,由于是面板数据,所以用xtline可以一次性画出所有泡沫发生后该行业的回报率趋势

encode(nnindcd),g(nnindcdcode)
xtset nnindcdcode trdmntcode 
xtline wr_sum  
xtline R

从图上来看,中国股票市场行业泡沫发生后确实有部分行业会在一定时间内崩盘,但并不是绝对的,JFE那篇文章也提到过原因有两个:1.一些朝阳行业确实在持续增长,根本不会崩盘 2.泡沫的顶点公认的难预测,价格一般都会在泡沫破灭前持续上涨,给投资者带来不错的净收益。

code和文章放到我的github上了惹:https://github.com/xumj9/bubble/tree/master,数据太大了而且可以直接从CSMAR上下我就不放了( ̄) 

 

主要参考文献和链接:

https://zhuanlan.zhihu.com/p/24174267

http://bbs.pinggu.org/thread-740917-1-1.html

Greenwood, Robin, Andrei Shleifer, and Yang You 2018 Bubbles for Fama. Journal of Financial Economics. http://www.sciencedirect.com/science/article/pii/S0304405X1830254X.

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章