检验pe_ratio的值¶
缘由¶
经常看到策略里需要用到pe,pb等基本面指标来进行选股, 可是如何才能得到一个合理的正确的pe呢?
别忘了, 这里涉及到一堆的资料需要收集: 包括4个连续的季报的eps, 还有最后一个季报的发布日期, 还有一个我们查询估值表里的pe时的交易日期/查询日期以及原始的收盘价等数据. 因为公司发布的季报的日期通常都会迟后于要查询的日期一个月甚至5个月以上, 所以必须谨慎对待.
好在聚宽的数据库里直接提供了该数据的查询. 但是我想依据它的算法求证一下数据的可信度.
计算公式¶
- 估值表里的pe_ratio列, 应该就是通常说的pe_ttm. 十二个月的滚动市盈率.
依据聚宽API文档里的计算公式, 应该是这样的:
市盈率(PE,TTM)=(股票在指定交易日期的收盘价 * 截止当日公司总股本)/归属于母公司股东的净利润TTM。
变换一下:
PE_TTM = 指定交易日的收盘价(非复权的原始价格) / (该指定交易日之前的连续的4个单季度的eps之和)
今天就专注于谈谈pe_ttm版本的pe¶
ttm的字面含义: trailing twelve month, 十二个月滚动市盈率. 我们实际上是用以前的滚动的4个季度的财务指标以及查询日当前价来计算该市盈率估值的. 另外还有: 动态市盈率和静态市盈率, 市盈率I和市盈率II等多种版本.
代码如下:¶
'''求出查询日之前的连续的4个季度, 返回季度列表
'''
def get_statDate(date = '2019-08-24'):
# 年
year = int(date[:4])
# 月日
month_and_day = date[5:10]
# 季度列表
if month_and_day < '05-01':
statDate_list = [str(year-2) + "q4", str(year-1) + "q1", str(year-1) + "q2", str(year-1) + "q3"]
elif month_and_day >= '05-01' and month_and_day < '09-01':
statDate_list = [str(year-1) + "q2", str(year-1) + "q3", str(year-1) + "q4", str(year) + "q1"]
elif month_and_day >= '09-01' and month_and_day < '11-01':
statDate_list = [str(year-1) + "q3", str(year-1) + "q4", str(year) + "q1", str(year) + "q2"]
elif month_and_day >= '11-01':
statDate_list = [str(year-1) + "q4", str(year) + "q1", str(year) + "q2", str(year) + "q3"]
print ('\ndate={}, statDate={}'.format(date, statDate_list))
return statDate_list
''' 依据公式自己求出eps_ttm, 然后与聚宽的查询结果对比, 然后打印结果
'''
codes = ['000069.XSHE']
date = '2019-08-24'
def validate_pe(codes=codes, date=date, ):
'''
'''
statDate = get_statDate(date)
q = query(
valuation.code,
income.basic_eps,
indicator.eps,
indicator.pubDate,
).filter(
valuation.code.in_(codes)
).order_by(
valuation.code.asc()
)
for sdate in statDate:
jbm_df = get_fundamentals(q,statDate=sdate,) # 基本面df
print(jbm_df)
eps_list = [get_fundamentals(q,statDate=sdate,).eps.values[0] for sdate in statDate]
now_p2 = get_price(codes[0], end_date=date, fq=None)['close'][-1]
now_p3 = get_price(codes[0], end_date=date, fq='post')['close'][-1]
now_p = get_price(codes[0], end_date=date, fq='pre')['close'][-1]
print('前复权价格, 原始成交价, 后复权价格分别是: {}, {}, {}'.format(now_p, now_p2, now_p3))
pe_ttm = now_p2 / sum(eps_list)
jbm_df = get_fundamentals(
query(
valuation.code,
valuation.pe_ratio,
).filter(
valuation.code.in_(codes)
),
date=date)
res = [round(pe_ttm,3), round(jbm_df.pe_ratio.values[0], 3)]
res.append(res[0] - res[1])
res = '代码={}, 日期={}, TTM_PE(12个月滚动市盈率)={}, 直接读取的pe_ratio={}, 相差= {}'.format(
codes[0], date, *res)
return res
拿4个不同的日期为示例, 检验一下:¶
print(validate_pe(codes, '2018-01-24'))
print(validate_pe(codes, '2017-01-24'))
print(validate_pe(codes, '2015-08-22'))
print(validate_pe(codes, '2015-01-24'))
8.8/(.124+.2697+.071+.1235)
结论:¶
4个时间点, 有三个对的上, 有一个对不上而且还差别不小. 让人不敢认同呀. 有错误的地方, 敬请斧正. 欢迎探讨.
date=2015-08-20, statDate=['2014q2', '2014q3', '2014q4', '2015q1']
code basic_eps eps pubDate
0 000069.XSHE 0.1711 0.1715 2014-08-26
code basic_eps eps pubDate
0 000069.XSHE 0.124 0.124 2014-10-22
code basic_eps eps pubDate
0 000069.XSHE 0.2696 0.2697 2015-03-21
code basic_eps eps pubDate
0 000069.XSHE 0.071 0.071 2015-04-21
前复权价格, 原始成交价, 后复权价格分别是: 8.36, 9.34, 363.3
代码=000069.XSHE, 日期=2015-08-20, TTM_PE(12个月滚动市盈率)=14.681, 直接读取的pe_ratio=15.884, 相差= -1.20300000012
date=2015-09-22, statDate=['2014q3', '2014q4', '2015q1', '2015q2']
code basic_eps eps pubDate
0 000069.XSHE 0.124 0.124 2014-10-22
code basic_eps eps pubDate
0 000069.XSHE 0.2696 0.2697 2015-03-21
code basic_eps eps pubDate
0 000069.XSHE 0.071 0.071 2015-04-21
code basic_eps eps pubDate
0 000069.XSHE 0.1235 0.1235 2015-08-20
前复权价格, 原始成交价, 后复权价格分别是: 6.76, 7.55, 293.67
代码=000069.XSHE, 日期=2015-09-22, TTM_PE(12个月滚动市盈率)=12.836, 直接读取的pe_ratio=12.84, 相差= -0.0039999999995
7.55/(.124+.2697+.071+.1235)
a.