市盈率(P/E ratio)是衡量一公司股票价值是否合理的重要指标之一。本文首先对市盈率指标进行简单的介绍,并探讨了公式背后的经济学含义;其次对几篇学界论文进行简要介绍,深化对市盈率概念的理解,为投资者使用市盈率指标时提供更多思路和参考;最后基于聚宽平台,展示该指标在平台中的使用方法以及简单的策略构建。
市盈率(Price earnings ratio,即P/E ratio)也称“本益比”、“股价收益比率”或“市价盈利比率(市盈率)”。其计算公式为:
P/E=Price/EPSP/E=Price/EPS
P/E=Price/EPS
P/E=Price/EPS
计算时,股价通常取最新股价,而EPS有多种取值方法。若采用上一年度已公布的EPS计算,则称为历史市盈率;若采用对未来EPS的预估,则称为预估市盈率;若采用过去12个月内净利润除以总发行已售股数,则称为滚动市盈率(TTM)。
市盈率公式背后的经济学含义
从经济学含义的角度我们可以更深刻地理解市盈率这个指标。对于一个公司的股票,投资者购买的成本是当前的价格,得到的收益是之后每年的分红。若不考虑货币的时间价值并假定每年分红不变,P/E比率就是投资人能收回成本的年限。
上文介绍了P/E指标的基本经济学含义和应用方法,若想要对该指标有更深刻的认识和理解,就要到学术界的研究中一探究竟了。学界对市盈率能否作为投资决策的衡量指标也有着多年的研究,本文选取四篇论文,挑选其关于市盈率的部分,根据其解决问题的脉络进行总结。
P/E能作为预测收益率的指标吗?
对市盈率的研究始于20世纪70年代。Nicholson(1960)和Basu(1977)发现,不论是否剔除风险因素,低P/E的股票收益率均明显高于高市盈率股票。在格雷厄姆 Security Analysis 和 J.Siegel Stocks for the long run 等书籍中,学者们都通过实证数据验证了低P/E股会在未来带来较高收益率的结论。这一结论背后的逻辑支撑也会在下文进行讨论。
有的研究得到了不同结果,主要是因为其选取的股票池和时间段不同。与大家结论较为不同的有Fama & French (1992)。这篇文章提出了著名的三因子模型,但在该模型的前半部分作者花了很长篇幅对P/E、P/B等因子进行了各种测试,并且发现,当使用1963至1990年美国股票数据时,收益率与P/E有一个U型的关系,先下降后上升,即高P/E值股票在这个时段也可以获得超额收益。从理论层面来说,高P/E股票产生较高回报有两种可能:一种是行业本身P/E值较高,公司未来利润增长潜力大,比如高科技板块股票市盈率接近100倍;另一种是在牛市的大趋势下,市场非理*易的情绪严重,投资者们笃定股票将背离其内在价值而不断上涨,这时买入高P/E的股票也有可能带来额外回报。
总的来说,学术界的主流观点是P/E在大多数情况下与收益率呈负相关关系,只有在特定的时间段和股票池中才会产生特殊情况,比如U型关系。
P/E作为收益率预测指标的背后逻辑是什么?
大多数研究支持收益率与P/E的负相关关系,这让我们想要研究:这种负相关关系存在的原因是什么呢?一般认为,股票价格应围绕其价值上下波动,EPS反应公司盈利能力,表现其投资价值,所以如果P/E值较低,说明相对于EPS来说价格较低,则其盈利能力相对于价格来说被低估。从长期来看,市场应该为其较高的盈利能力“买账”,所以未来价格会上升。
Fuller et al. (1993) 提出了收益率与P/E的负相关关系的包括以上观点的三种解释,但这三个想法一一被实证研究所否定:
1、低P/E说明当期EPS高,当期EPS高可能说明未来EPS高,盈利能力强,所以未来价格会上升。研究表明不论是相邻年份、相隔年份还是以4期为单位取平均,EPS之间都没有显著的相关性。研究通过否定各期EPS之间的相关性,否定了当下P/E对未来EPS的预测能力,给传统的P/E对收益率影响的理论一记重击。
2、分析师对股票未来情况预测的误差导致超额收益。使用分析师未来8年内对于EPS增长情况的预测,发现预测结果大致都比实际情况高5%左右,预测的相对情况和实际的相对情况比较接近,即每组的超额增长接近,不会在收益上造成区别。
3、P/E不同可能代表某些风险因子不同,这些风险因子导致超额收益。使用barra的分析系统,发现不同P/E组的α之差是7.8%,而P/E、P/B和市场波动性产生的α之和是7.1%。P/E与P/B相关性较高,所以与P/E无关的风险因子对α的总贡献只有0.7%。
最终,这篇文章没有在实证层面给出P/E能预测盈利能力的原因,但提出了另外一个假设:当期的EPS与下一期的EPS是不相关的,每期的EPS都服从相同的分布,所以当期P/E较低的股票相对来说P较低。如果此时买入,就是用较低的价格买入了一个具有相同分布的EPS,期待未来价格会反转,获得收益。
Campbell & Shiller (1998)的研究在一定程度上证实了上一假设。该文章研究的是D/P(每股分红/股票价格),而D(每股股利)与EPS呈正相关关系,故该研究的D/P也可以很大程度上反应P/E的情况。二人对股票当年的D/P与之后一年的D/P进行回归,发现相关系数很低,这与上一篇文章发现的各期EPS间相关系数较低的结论一致;但使用当期D/P对下一年价格变动进行回归,发现当期D/P有较强的预测能力。文章结论指出,D/P的变动是由P带动而回归均值的,可以想见P/E的情况也类似。所以,P/E作为收益率预测指标的背后逻辑,在于价格的均值回归。
P/E因子还有其他计算方法吗?
在文章开头,我们提到了使用不同EPS作为P/E分母,得到不同的P/E值。但 Anderson & Brooks (2006) 突破了以往使用过去一年的EPS和当时的P计算P/E的方法,而是综合考虑过去8年的EPS,并且采取多种加权方式,考察怎样才能最好地刻画未来的P。
研究首先尝试使用当前年、一年以前直到7年以前的EPS(分别记为EP1~EP8)分别进行排序,根据这个排序构建投资组合并考察收益率,发现EP1~EP8的预测效力并不是单调的,而是EP2和EP3最差。之后研究对过去8年的EPS尝试了多种不同权重的线性组合,并根据不同组合作为因子来选股,发现给临近年份赋予更高权重的组合方式相比于给临近年份赋予更低权重的方式竟然收益率更低,这与我们的直觉(认为更接近现在的年份对收益率指导作用更大)是相违背的。另外,仅使用两年EPS时,是EP1 EP8的组合带来的收益率最高,研究认为可能是EP1和EP8的相关性较低,所以EPS8能提供更多的信息。
P/E因子作为预测指标时的缺陷源于什么?
一般认为,P/E作为预测指标时的缺陷有两方面:1、不能动态地考量公司的成长情况;2、作为分母的EPS对于公司盈利能力的刻画能力有限。
在Penman & Reggiani (2014)中,作者认为P/E比率没有刻画出公司未来成长能力的风险,所以不是一个全面的指标,并提出要同时使用P/E和P/B两个比率。
首先进行了实证研究,每年根据P/E分为五组,再在每组内根据P/B分为五组。发现在确定的P/E组内,P/B越大的组合未来收益越高,但收益的标准差也越大。那么其背后原因是什么?作者引入了股利贴现模型 :
E1/P0=r?gE1/P0=r?g
E<em>1/P</em>0=r?g
E{1}/P{0}=r-g
其中E1为下一期利润,P0为当期价格,r是要求回报率,g是公司增长率。
对于确定的预估市盈率即确定的E1/P0,r-g也确定了。但该公司的g是还未落袋的,所以存在风险,对于这样的风险投资人就会要求更高的r来进行补偿。这样r和g同时增加,r-g却不变,导致预估市盈率不变,所以P/E指标的缺陷在于,并没有体现出公司成长的风险。盲目购买P/E值较低的股票,可能会陷入作者所说的value trap。
上面描述出的P/E值的问题在于:不能动态地刻画公司成长的可能性及风险。除此之外,P/E值还有另外一个问题:作为分母的EPS对于公司盈利能力的刻画能力有限。EPS的计算方式是净利润除以流通股数,而净利润这个指标相对于现金流等指标可调整空间较大;并且还有可能包含非经营性收益,如变卖固定资产,或者使用闲置资金投资金融产品等等。这些非经营性收益不一定可持续,不能完全代表该公司业务开展得好、盈利能力强。
在上文对P/E进行了深入的讨论后,这里使用聚宽平台搭建一个最简单的研究。在聚宽平台上,研究者可以很容易地提取个股在2005年之后任何时间点的P/E值。平台使用的P/E为滚动市盈率,同时也提供历史市盈率,详见这里。研究者可以使用get_fundamentals
函数来提取P/E值,更详细的代码和收益率曲线在文末的研究中有提供。
根据P/E值进行选股的简单策略
在这里,我们给出一个简单的根据P/E值选股的研究。
策略想法是:股票池为A股全体股票,时间为05年中旬到17年年底。将股票池中的股票剔除停牌及上市三个月以内的股票,根据P/E值大小分为5组。每一组持有一段时间(一天或一个月),各股权重为其市值,将收益率作为该组的收益率。在下一调仓日,重新将股票根据P/E值分为5组,重复上述过程。以此类推,这样可以得到P/E值不同的五组的收益情况。根据上一部分内容,我们猜测P/E值和收益率应该呈负相关关系,即P/E值最小的那一组收益率最高,P/E值最大的收益率最低。研究结果表明,我们的猜想基本是正确的。
每日调仓总收益:
每月调仓总收益:
除了对每个投资组合单独绘制收益曲线,我们也尝试了做多P/E值最低的组合,做空P/E值最高的组合,以期获得免疫市场风险的收益率。记该组合为0-4组合。12年间,若使用每日调仓,0-4投资组合总收益为171.6%;若使用每月调仓,0-4投资组合总收益为179.5%。
这部分代码和收益率曲线在文末的研究中有给出。可以发现,每月调仓得到的收益曲线基本都是每日调仓收益曲线的连续化,这也符合我们的直觉。另外,从结果可以看出,仅仅使用P/E因子作为选股指标是不太够的,解释能力并不强。
以上是单独使用P/E值构建简单策略的研究方法,研究者也可以根据自己的想法构建更多更复杂的策略。
市盈率是一个很基本的财务指标,不管是不是通过量化的方法进行选股几乎都逃不开这个指标,因为它直接联系了股价和盈利能力这两个选择股票时最重要的考虑因素。但单独通过市盈率指标进行选股可能会遗漏一些信息,这就要求我们将市盈率指标与其他指标结合起来使用。
参考资料
Fuller, R.J., L.C. Huberts and M.J.Levinson, 1993, Returns to e/p strategies, higgledy-piggledy growth, analysts' forecast errors, and omitted risk factors
Fama, E.F and K.R. French, The cross-section of expected stock returns
Penman, S.H. and F.Reggiani, 2014, The value trap: Value buys risky growth
Anderson, K. and C. Brooks, 2006, The long-term price-earnings ratio
Campbell, John Y., and Robert J. Shiller, 1998, Valuation Ratios and the Long-Run Stock Market Outlook
from jqdata import *import matplotlib.pyplot as pltimport pandas as pdimport numpy as nppd.options.mode.chained_assignment = None days=get_all_trade_days()days=list(map(lambda x:str(x),days))stocks=get_index_stocks('000001.XSHG')months=[]for i in range(len(days)-1):if days[i][5:7]!=days[i+1][5:7]:months.append(days[i])
all_prices=[[1],[1],[1],[1],[1]]q=query(valuation).filter(valuation.code.in_(stocks),valuation.pe_ratio>0)mkt_price=[]delta=[1]for j in range(3,154): #3是因为要求至少上市3个月,154是到17年年底的月份号df=get_fundamentals(q,date=months[j]).sort('pe_ratio')df.index=df.code.valuesdf=df[['pe_ratio','market_cap']]#得到股票价格及市场价格prices=get_price(stocks,start_date=months[j-3],end_date=months[j+1],fields='close')[0,:,:].T.dropna().loc[:,months[j]:months[j+1]].iloc[:,[0,-1]]mkt_price.append(get_price('000001.XSHG',start_date=months[j],end_date=months[j],fields='close')['close'][0])#去除停牌及上市不足三个月的股票vol0=get_price(stocks,start_date=months[j],end_date=months[j],fields='volume')[:,0,:].dropna()vol0=list(vol0[vol0['volume']!=0].index)prices=prices.loc[vol0,:].dropna()#计算各股票每月收益率并得到各组股票代码df['ret']=prices[months[j+1]]/prices[months[j]]-1df['ret_cap']=df['ret']*df['market_cap']five_df=list(df[int(len(df)*i/5):int(len(df)*(i+1)/5)] for i in range(5))#按市值加权,计算各组合每月收益率for i in range(5):all_prices[i].append(all_prices[i][-1]*(1+sum(five_df[i]['ret_cap'])/sum(five_df[i]['market_cap'])))mkt_price=list(map(lambda x:x/mkt_price[0],mkt_price))plt.figure(figsize=(8,4))for i in range(5):plt.plot(all_prices[i],label=i)plt.plot(mkt_price,label='mkt')plt.legend(loc=2)plt.show()#计算0-4组合的收益率并画图deltas=list(all_prices[0][i]/all_prices[0][i-1]-all_prices[4][i]/all_prices[4][i-1] for i in range(1,len(all_prices[0])))price_delta=[1]for i in range(len(deltas)):price_delta.append(price_delta[-1]*(1+deltas[i]))plt.plot(price_delta)plt.show()
all_prices=[[1],[1],[1],[1],[1]]q=query(valuation).filter(valuation.code.in_(stocks),valuation.pe_ratio>0)mkt_price=[]delta=[1]for j in range(3,154):df=get_fundamentals(q,date=months[j]).sort('pe_ratio')df.index=df.code.valuesdf=df[['pe_ratio','market_cap']]#得到股票价格及市场价格,并去除停牌股prices=get_price(stocks,start_date=months[j-3],end_date=months[j+1],fields='close')[0,:,:].T.dropna().loc[:,months[j]:months[j+1]]#.iloc[:,[0,-1]]vol0=get_price(stocks,start_date=months[j],end_date=months[j],fields='volume')[:,0,:].dropna()vol0=list(vol0[vol0['volume']!=0].index)prices=prices.loc[vol0,:].dropna()for i in range(len(list(prices))):df[list(prices)[i]]=prices.iloc[:,i]/prices.iloc[:,i-1]df.dropna(inplace=True)#将每日股票价格与市值相乘,以获取每日收益率for i in range(len(list(prices))):df[str(str(list(prices)[i])+'cap')]=df[list(prices)[i]]*df['market_cap']five_df=list(df[int(len(df)*i/5):int(len(df)*(i+1)/5)] for i in range(5))#计算各组合每日收益率for i in range(5):five_df[i].loc['sum']=five_df[i].apply(lambda x:x.sum())del five_df[i]['pe_ratio'],five_df[i]['market_cap']sm_to_add=list(five_df[i].loc['sum'])sm_to_add=sm_to_add[int(len(sm_to_add)/2):]all_prices[i]=all_prices[i]+list(map(lambda x:x*all_prices[i][-1]/sm_to_add[0],sm_to_add))[1:]mkt=list(get_price('000001.XSHG',start_date=months[3],end_date=months[154],fields='close').values)mkt_price=list(map(lambda x:float(x/mkt[0]),mkt))plt.figure(figsize=(8,4))for i in range(5):plt.plot(all_prices[i],label=i)plt.plot(mkt_price,label='mkt')plt.legend(loc=2)plt.show() #计算0-4组合的收益率并画图deltas=list(all_prices[0][i]/all_prices[0][i-1]-all_prices[4][i]/all_prices[4][i-1] for i in range(1,len(all_prices[0])))price_delta=[1]for i in range(len(deltas)):price_delta.append(price_delta[-1]*(1+deltas[i]))plt.plot(price_delta)plt.show()
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程