从估值看当前A股 指数分析

value.jpeg

简书不维护了,欢迎关注我的知乎:波罗学的个人主页

知乎地址

自2018年2月份开始,由于一些可知的原因,我们的大A股已经持续了一年的下跌,近3600点跌到了最低的2500左右。大家都在说现在的市场估值已经相当低了。那今天我们就用数据说话,来具体看看当前的市场估值情况。

注:因为选取数据有部分缺失,故数据选取时间统一为2012年1月1日~2019年2月14日(单身狗在情人节规划这篇文章,怎苦字了得!)。非金融出生,加入部分自己的思考,有错请指正。

什么是估值

谈到股市,最常听到的就是诸如 "股市已经到达3000点了"、"股市刚刚突破了4000点"之类的话。此处的多少点上某种意义上是代表了人们愿意为股市付出的价。

那么估值呢?简言之就是估计的某件东西的价值,该数字通常是无法准确得知的。一家公司的估值,主要是由该公司当前情况和未来的发展潜力等多方面因素决定。市场的估值则是可以由这些大大小的公司来决定,可由其成分股通过某些算法计算而得,可参见指数估值计算方法

那么如何来评价市场估值的高低呢?我们知道,准确的估值是无法得知的,大家常会用PE和PB来衡量估值高低,PE为市盈率,即市值/盈利,PB是市净率,即市值/净资产。当这些指标高于某个值时,我们就会认为当前的估值处于高位,反之则处于低位。我们可以此来简化估值的评估逻辑。

那么,下面将通过数据来分析这些指标,来评价下当前股市。

分析工具为Python,下面首先导入一些必要的python包,数据来自于TusharePro


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as stats
import tushare as ts

api = ts.pro_api(token='认证token')

以啥分析市场

市场,通常可以用某些指数来代表。指数有很多,通常都是基于不同标准编制的。

我们这里将选取同花顺股票软件上的六大指数来进行分析,即上证综指(000001.SH)、深圳成指(399001.SZ)、创业板指(399006.SZ)、沪深300(000300.SH)、上证50(000016.SH)和中证500(000905.SH)。

关于各个指数的样本和一些选取的准则,可以自行网上搜索。

获取目标数据

接下来我们开始获取数据,并做一些相应的处理,如对数据按交易时间升序排列以便于后续的分析。

因为需要获取六大指数的数据,首先定义一些辅助变量:


index_codes = [
    '000001.SH',
    '399001.SZ',
    '399006.SZ',
    '000300.SH',
    '000016.SH',
    '000905.SH'
]
start_date = '20120101' # 开始日期
end_date = '20190214'   # 结束日期
index_dict = {}         # 存储指标数据

为了批量获取数据,定义一个单指数数据获取与处理的函数,返回值为pd.DataFrame类型,pandas为我们提供了很多常用的数据分析方法。


def get_index_valudation_indicator_df(code, start_date, end_date):
    fields = 'trade_date,pe,pb'
    data = api.index_dailybasic(
        ts_code=code,
        start_date=start_date,
        end_date=end_date,
        fields=fields
    )

    data = data.drop_duplicates()
    data.index = pd.to_datetime(data['trade_date'])
    data = data.sort_index()
    return data

到这里,我们开始正式下载数据。一个for循环获取就把所有数据加载到index_dict中,多么简洁快速。代码如下:

for index_code in index_codes:
    index_dict[index_code] = get_index_valudation_indicator_df(index_code, start_date, end_date)

先检查下各指数数据行数,确保成功获取数据:

for k, index_df in index_dict.items():
    print(k, len(index_df))

输出如下:

000001.SH 1728
399001.SZ 1728
399006.SZ 1728
000300.SH 1728
000016.SH 1728
000905.SH 1728

都为1728行,一切正常!来简单观察一下数据,以上证综指为例打印出结尾5行数据:

index_dict['000001.SH'].tail(5)

输出如下:

            trade_date  pe  pb
trade_date          
2019-02-01  20190201    12.61   1.30
2019-02-11  20190211    12.77   1.32
2019-02-12  20190212    12.83   1.32
2019-02-13  20190213    13.08   1.35
2019-02-14  20190214    13.07   1.34

pandas为我们提供了一个info方法可以查看数据的整体情况。如下:

index_dict['000001.SH'].info()

输出如下:

 <class 'pandas.core.frame.DataFrame'>
 DatetimeIndex: 1728 entries, 2012-01-04 to 2019-02-14
 Data columns (total 3 columns):
 trade_date 1728 non-null object
 pe 1728 non-null float64
 pb 1728 non-null float64
 dtypes: float64(2), object(1)
 memory usage: 54.0+ KB

可以看出我们的数据时间跨度为2012年01月04日至2019年02月14日,共1728条记录。不是从2012年1月1日开始当然是因为1月1日至1月3日是元旦假期。

注:最初数据获取时,选择了2010年1月1日~2019年2月14日,但数据检查时发现部分指数缺失,故退而求其次缩短了时间段。

开始正式分析

进入正题,我们该如何进行分析?先来谈一些个人对估值的看法。

我们经常会听到这样的说法,美股PE和PB为某个范围内时则表明当前的估值是合理的,若高于或低于该值就被认为是贵或便宜了。中国也是如此,不过A股通常会比美股的合理值高出一不少,这是否表明泡沫的存在?个人看法,中国经济长期处在高速发展阶段,所存环境不同与美股截然不同,对未来的预期高一点自然是可以理解的。简单的思考后,我总结出了如下几个观点:

  • 合理的估值会随着大环境变化而变化;
  • 合理的估值随着不同市场行业的预期不同而不同;
  • 合理的估值在一定时间周期与大环境下是相对确定的;

基于以上这些看法,下面开始具体的分析。

A股当前的合理估值是多少

虽然从长期来看,合理的估值在不断变化,但短期内是有一个值可供我们参考的。那么我们如何获取到这个值呢?能想到的办法就是从历史数据中分析而来,可计算的几个指标有:平均数、频率分布最高区间(类似众数)、中位数。这里选取的是7年的数据,当然没有什么理由,在保证数据准确完备的前提下选的时间线尽量长点。下面开始来计算这些指标。

先定义一个函数计算历史估值的分布情况并返回最高分布区间,并计算出这个区间的平均数。


def get_interval_freq_max(data):
    c = pd.cut(data, bins=10).value_counts() # 计算各区间分布数量,假设为10
    p = c / c.sum()  # 计算各区间分布频率
    m = p.max()  # 计算最大值
   for k, v in p.items(): # 找出最大值的key,即所在区间
       if m == v:
            max_interval = k
            return data[(data >= max_interval.left) & (data <= max_interval.right)].mean()

计算指标并输出,最后转化为pd.DataFrame类型以便于作图,下面为代码实现:

index_current_indicator_dict = {}
for k, index in index_dict.items():
    index_current_indicator_dict[k] = {
        'pb': index['pb'][-1],
        'pb_mean': index['pb'].mean(),
        'pb_high_feq': get_interval_freq_max(index['pb']),
        'pb_median': index['pb'].median(),
        'pe': index['pe'][-1],
        'pe_mean': index['pe'].mean(),
        'pe_high_feq': get_interval_freq_max(index['pe']),
        'pe_median': index['pe'].median()
    }

indicator_df = pd.DataFrame(index_current_indicator_dict)
print(indicator_df)
            000001.SH   399001.SZ   399006.SZ   000300.SH   000016.SH   000905.SH
pb          1.340000    2.250000    3.840000    1.380000    1.170000    1.680000
pb_high_feq 1.601113    3.118865    5.752357    1.494908    1.205844    2.235625
pb_mean     1.605637    2.710625    5.342436    1.552286    1.343003    2.629954
pb_median   1.590000    2.640000    4.990000    1.500000    1.270000    2.480000
pe          13.070000   20.130000   34.870000   12.300000   10.230000   19.360000
pe_high_feq 11.022995   15.323544   35.389715   11.991063   10.478383   27.131933
pe_mean     13.755469   24.546250   55.418264   12.171325   10.062737   36.700735
pe_median   13.550000   21.475000   54.820000   11.970000   9.970000    34.140000

从输出的数据分析不够直观,下面我们来尝试通过图形方式展现,先来看PB:

columns = ['pb', 'pb_mean', 'pb_high_feq', 'pb_median']
indicator_df.loc[columns].T.plot(kind='bar', figsize=(15, 5))

输出如下:


image.png

读图可以得到如下的结论:

  • 无论使用哪个指标作为合理估值,选取的6大指数PB(即蓝色柱)当前都处在低位;
  • 创业板的PB最高,这或许与大家对创业板公司的成长有较高预期有关;
  • 无论使用哪个指标作为合理估值,中证500当前PB与它们都有较大的差距;

再来看PE:

columns = ['pe', 'pe_mean', 'pe_high_feq', 'pe_median']
indicator_df.loc[columns].T.plot(kind='bar', figsize=(15, 5))
image.png

读上图会发现一些与PB指标相同的结论,比如创业板估值依然是最高,中证500当前被严重低估等。那么有哪些不同呢?一个最易得出的结论就是多数指数当前的市盈率在其他各指标中并非最低。不知道这是不是近期企业盈利下降有关。

总体而言,如果钟爱于指数投资、坚信价值回归,当前或许较适合增加中证500配置比重。

当前估值处在历史什么位置

以上的分析主要从总体角度观察。下面我们将从时间序列上观察估值的历史变化,而最好的方式从分位的角度来看问题。

我们先来计算各指数的估值处在近7年的什么分位,计算代码如下:

index_current_quantile_dict = {}

for k, index in index_dict.items():
    index_current_quantile_dict[k] = {
        'pb_percentile': stats.percentileofscore(index['pb'], index['pb'][-1]),
        'pe_percentile':stats.percentileofscore(index['pe'], index['pe'][-1])
    }

pd.DataFrame(index_current_quantile_dict)

输出如下:

                000001.SH   399001.SZ   399006.SZ   000300.SH   000016.SH   000905.SH
pb_percentile   13.425926   33.767361   25.954861   23.350694   19.994213   4.687500
pe_percentile   45.949074   47.366898   10.358796   55.555556   57.725694   3.009259

从这张表可以得出哪些结论?所有指数的市净率都处在1/2分位以下,而对于市盈率,除了中证500和创业板指,都位于1/2分位附近。创业板指和中证500低估较为明显,特别是中证500,无论从净资产还是盈利角度来看都有很大的投资价值。

上面是计算最近的情况,我们也可以通过绘制历史的变化图,来看看不同时期估值指标的表现情况。同时可以添加相应的分位辅助线(包括1/4、1/2、3/4分位)来更好的对比。

以上证指数为例:

data_pe = index_dict['000001.SH'][['pe']].copy()
data_pb = index_dict['000001.SH'][['pb']].copy()
data_pe['pe_Q1'] = data_pe['pe'].quantile(0.25)
data_pe['pe_Q2'] = data_pe['pe'].quantile(0.5)
data_pe['pe_Q3'] = data_pe['pe'].quantile(0.75)
data_pb['pb_Q1'] = data_pb['pb'].quantile(0.25)
data_pb['pb_Q2'] = data_pb['pb'].quantile(0.5)
data_pb['pb_Q3'] = data_pb['pb'].quantile(0.75)

准备好数据,直接作出两指标的时间序列变化图:

fig = plt.figure()
ax_pe, ax_pb = fig.subplots(2, 1)
ax_pe.set_title('pe timeseries')
ax_pb.set_title('pb timeseries')
data_pe[['pe_Q1', 'pe_Q2', 'pe_Q3', 'pe']].plot(figsize=(12, 15), ax=ax_pe)
data_pb[['pb_Q1', 'pb_Q2', 'pb_Q3', 'pb']].plot(figsize=(12, 15), ax=ax_pb)
plt.show()

绘图结果:


image.png

可以看出,在2012年至2014年期间估值长期处于低位,足足有两年之久。所以说,虽然当前资产较为便宜,但并不代表就来一定会上涨。不过或许是蓄力越久,爆发就有力。众所周知,2014年下半年至2015年上半年的那一波疯牛市。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容