基于Python的指数基金量化投资 - 指数的市盈率和市净率计算
上一篇《基于Python的指数基金量化投资 - 通过市盈率和市净率对指数估值》介绍了通过市盈率和市净率对指数进行估值,然后结合具体的估值百分位来进行投资。所以指数的市盈率和市净率是两个非常重要的指标。
这里就会有个问题,指数的市盈率和市净率怎么进行计算,指数不像个股,个股的市盈率计算起来比较简单:
同样个股的市净率计算也比较简单:
而指数是一篮子股票,例如沪深300就包含了300家上市公司,中证500包含了500家上市公司,上证50包含了50家上市公司,所以指数是一个上市公司的集合体,这个集合体我们也可以把它看成一家公司,里面包含的这些上市公司可以看成这家公司的某一部分或者某一个部门,这样的话,这家公司的市值就是所有部门的市值总和,公司净利润就是所有部门的利润总和,而公司净资产就是所有部门的净资产总和,同样再通过上面的计算过程就可以得到指数的市盈率:
同样的方式也可以得到指数的市净率:
具体怎么做呢,分为3个步骤:
1)通过指数包含的个股,解析出具体的个股信息;
2)把第一步中所有个股的总市值、总净利润和总净资产计算出来;
3)通过上面介绍的指数计算方式计算出市盈率和市净率即可;
具体来看看代码实现
首先看看市盈率的计算方式
import pandas as pd
import math
indexType =['./importfile/indexSeries/indexTpye/hs300.csv', #沪深300 - 0
'./importfile/indexSeries/indexTpye/zz500.csv', #中证500 - 1
'./importfile/indexSeries/indexTpye/zz100.csv', #中证100 - 2
'./importfile/indexSeries/indexTpye/shz50.csv', #上证50 - 3
'./importfile/indexSeries/indexTpye/hsyy300.csv', #沪深医药300 - 4
'./importfile/indexSeries/indexTpye/zzyh.csv', #中证银行 -5
'./importfile/indexSeries/indexTpye/zzxf.csv', #中证消费 -6
'./importfile/indexSeries/indexTpye/zzbj.csv', #中证白酒 -7
'./importfile/indexSeries/indexTpye/db500.csv', # 500低波动-8
'./importfile/indexSeries/indexTpye/jz300.csv', # 300价值 -9
'./importfile/indexSeries/indexTpye/yy100.csv', #医药100 -10
'./importfile/indexSeries/indexTpye/zzyyao.csv', #中证医药 -11
'./importfile/indexSeries/indexTpye/jbm50.csv', #基本面50 -12
'./importfile/indexSeries/indexTpye/shzhl.csv', #上证红利 -13
'./importfile/indexSeries/indexTpye/zzhl.csv', #中证红利 -14
'./importfile/indexSeries/indexTpye/zzjg.csv', #中证军工 -15
'./importfile/indexSeries/indexTpye/spyl.csv', #食品饮料 -16
'./importfile/indexSeries/indexTpye/zqgs.csv', #证券公司 -17
'./importfile/indexSeries/indexTpye/ylcy.csv', #养老产业 -18
'./importfile/indexSeries/indexTpye/szhl.csv', #深证红利 -19
'./importfile/indexSeries/indexTpye/zzhb.csv', #中证环保 -20
'./importfile/indexSeries/indexTpye/cyb.csv'] #创业板 -21
# 指数文件,里面提供了指数包含的个股信息
idx = -1
total_share = 1
for indexCnt in range(len(indexType)):
csv_data = pd.read_csv(indexType[indexCnt])
total_profit_sum = 0
total_total_sum = 0
for i in range(csv_data.shape[0]):
if csv_data.values[i][4] >= 600000:
stock_info_prc = pd.read_csv('C:/Program Files(x86)/Python/prjs/exportfile/stockDataAll/sh.' + str(csv_data.values[i][4]) +'.csv')
stock_info_epsTTM = pd.read_csv('./exportfile/stockDataProfit/' +str(csv_data.values[i][4]) + '.csv')
elif csv_data.values[i][4] >= 300000:
stock_info_prc = pd.read_csv('C:/Program Files (x86)/Python/prjs/exportfile/stockDataAll/sz.'+ str(csv_data.values[i][4]) + '.csv')
stock_info_epsTTM = pd.read_csv('./exportfile/stockDataProfit/' +str(csv_data.values[i][4]) + '.csv')
else:
len_name = len(str(csv_data.values[i][4]))
if len_name == 1:
stock_code = '00000' +str(csv_data.values[i][4])
elif len_name == 2:
stock_code = '0000' +str(csv_data.values[i][4])
elif len_name == 3:
stock_code = '000' +str(csv_data.values[i][4])
elif len_name == 4:
stock_code = '00' +str(csv_data.values[i][4])
elif len_name == 5:
stock_code = '0' + str(csv_data.values[i][4])
elif len_name == 6:
stock_code =str(csv_data.values[i][4])
else:
stock_code = ''
stock_info_prc = pd.read_csv('C:/Program Files(x86)/Python/prjs/exportfile/stockDataAll/sz.' + stock_code + '.csv')
stock_info_epsTTM = pd.read_csv('./exportfile/stockDataProfit/' +stock_code + '.csv')
stock_single_price = stock_info_prc['close']
stock_single_pe = stock_info_prc['peTTM']
stock_single_eps = stock_info_epsTTM['epsTTM']
stock_single_total = stock_info_epsTTM['liqaShare']
#解析个股的信息,包含个股价格、市值、市盈率和市净率
stock_single_total_tmp = stock_single_total.values[-1]
if math.isnan(stock_single_total_tmp):
stock_single_total_tmp = stock_single_total.values[-2]
stock_single_profit = stock_single_eps.values[-1] *stock_single_total_tmp
if stock_single_pe.values[idx] < 0 or stock_single_eps.values[-1]< 0 or stock_single_pe.values[idx] > 500:
weight_sum = 0
else:
weight_sum = total_share / csv_data.shape[0]
total_profit_sum = weight_sum * stock_single_profit + total_profit_sum
total_total_sum = weight_sum * stock_single_total_tmp *stock_single_price.values[idx] + total_total_sum
calc_pe = str(total_total_sum / total_profit_sum)
#通过公式计算出市盈率
print('index name : ' + csv_data.values[0][2])
print('weight_sum PE : ' +calc_pe)
print('---------------')
其次再看看市净率的计算过程
import pandas as pd
import math
indexType =['./importfile/indexSeries/indexTpye/hs300.csv', #沪深300 - 0
'./importfile/indexSeries/indexTpye/zz500.csv', #中证500 - 1
'./importfile/indexSeries/indexTpye/zz100.csv', #中证100 - 2
'./importfile/indexSeries/indexTpye/shz50.csv', #上证50 - 3
'./importfile/indexSeries/indexTpye/hsyy300.csv', #沪深医药300 - 4
'./importfile/indexSeries/indexTpye/zzyh.csv', #中证银行 -5
'./importfile/indexSeries/indexTpye/zzxf.csv', #中证消费 -6
'./importfile/indexSeries/indexTpye/zzbj.csv', #中证白酒 -7
'./importfile/indexSeries/indexTpye/db500.csv', # 500低波动-8
'./importfile/indexSeries/indexTpye/jz300.csv', # 300价值 -9
'./importfile/indexSeries/indexTpye/yy100.csv', #医药100 -10
'./importfile/indexSeries/indexTpye/zzyyao.csv', #中证医药 -11
'./importfile/indexSeries/indexTpye/jbm50.csv', #基本面50 -12
'./importfile/indexSeries/indexTpye/shzhl.csv', #上证红利 -13
'./importfile/indexSeries/indexTpye/zzhl.csv', #中证红利 -14
'./importfile/indexSeries/indexTpye/zzjg.csv', #中证军工 -15
'./importfile/indexSeries/indexTpye/spyl.csv', #食品饮料 -16
'./importfile/indexSeries/indexTpye/zqgs.csv', #证券公司 -17
'./importfile/indexSeries/indexTpye/ylcy.csv', #养老产业 -18
'./importfile/indexSeries/indexTpye/szhl.csv', #深证红利 -19
'./importfile/indexSeries/indexTpye/zzhb.csv', #中证环保 -20
'./importfile/indexSeries/indexTpye/cyb.csv'] #创业板 -21
# 指数文件,里面提供了指数包含的个股信息
idx = -1
total_share = 1
for indexCnt in range(len(indexType)):
total_profit_sum = 0
total_asset_sum = 0
total_total_sum = 0
csv_data= pd.read_csv(indexType[indexCnt])
for i in range(csv_data.shape[0]):
if csv_data.values[i][4] >= 600000:
stock_info_prc = pd.read_csv('C:/Program Files(x86)/Python/prjs/exportfile/stockDataAll/sh.' + str(csv_data.values[i][4]) +'.csv')
stock_info_epsTTM = pd.read_csv('./exportfile/stockDataProfit/' +str(csv_data.values[i][4]) + '.csv')
elif csv_data.values[i][4] >= 300000:
stock_info_prc = pd.read_csv('C:/Program Files(x86)/Python/prjs/exportfile/stockDataAll/sz.' + str(csv_data.values[i][4]) +'.csv')
stock_info_epsTTM = pd.read_csv('./exportfile/stockDataProfit/' +str(csv_data.values[i][4]) + '.csv')
else:
len_name = len(str(csv_data.values[i][4]))
if len_name == 1:
stock_code = '00000' +str(csv_data.values[i][4])
elif len_name == 2:
stock_code = '0000' +str(csv_data.values[i][4])
elif len_name == 3:
stock_code = '000' +str(csv_data.values[i][4])
elif len_name == 4:
stock_code = '00' +str(csv_data.values[i][4])
elif len_name == 5:
stock_code = '0' +str(csv_data.values[i][4])
elif len_name == 6:
stock_code =str(csv_data.values[i][4])
else:
stock_code = ''
stock_info_prc = pd.read_csv('C:/Program Files (x86)/Python/prjs/exportfile/stockDataAll/sz.'+ stock_code + '.csv')
stock_info_epsTTM = pd.read_csv('./exportfile/stockDataProfit/' +stock_code + '.csv')
stock_single_price = stock_info_prc['close']
stock_single_pb = stock_info_prc['pbMRQ']
stock_single_eps =stock_info_epsTTM['epsTTM']
stock_single_total = stock_info_epsTTM['liqaShare']
#解析个股的信息,包含个股价格、市值、市盈率和市净率
stock_single_total_tmp = stock_single_total.values[-1]
if math.isnan(stock_single_total_tmp):
stock_single_total_tmp = stock_single_total.values[-2]
stock_single_profit = stock_single_eps.values[-1] *stock_single_total_tmp
stock_single_asset = stock_single_total_tmp *stock_single_price.values[idx] / stock_single_pb.values[idx]
if stock_single_pb.values[idx] < 0 or stock_single_eps.values[-1]< 0:
weight_sum = 0
else:
weight_sum = total_share / csv_data.shape[0]
total_profit_sum = weight_sum * stock_single_profit + total_profit_sum
total_asset_sum = weight_sum * stock_single_asset + total_asset_sum
total_total_sum = weight_sum * stock_single_total_tmp *stock_single_price.values[idx] + total_total_sum
calc_pb =str(total_total_sum / total_asset_sum)
# 通过公式计算出市盈率
print('index name : ' +csv_data.values[0][2])
print('weight_sum PB : ' + calc_pb)
print('----------------')
大家注意几个问题:
1、代码中用到的指数文件shz50.csv等可以在中证指数官网下载,也可以直接联系小将获取;
2、另外个股信息数据和个股盈利数据(’prjs/exportfile/stockDataAll/sz.' + stock_code + '.csv'),'./exportfile/stockDataProfit/' + stock_code + '.csv' )可以在baostock上下载,在文章中《202102_基于Python的指数基金量化投资 - 股票数据源baostock》有相关介绍。
课程参考:网易云课堂 基于Python的量化指数基金投资