股票基本面统计
使用get_stock_basics()函数一次性下载所有股票基本面数据。这对观察股票的整体市场情况很有帮助。
import tushare as ts
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
stock = ts.get_stock_basics() # 下载股票基本面数据
stock.to_excel('stock.xlsx') # 保存为电子表格
stock.shape # Out: (3678, 22)
数据集规模为3823x22,每行是一支股票的基本数据。字段详情请查看Tushare的网站。数据集字段详情查看http://tushare.org 网站。本节用到的数据列有:code,股票代码;name,名称;industry,所属行业;area,地区;pe,市盈率;totals,总股本(亿元人民币);esp,每股收益;timeToMarket,上市日期。
下面从电子表格文件中读取数据,注意股票代码code列的处理细节。Pandas读取数据时,总是试图将数据自动转换为数值类型。深市类似'002522'的股票代码读入后,将丢失前导字符“00”,变为整数2522,因此读取时特意指定code字段为字符串。
df = pd.read_excel('stock.xlsx', dtype={'code': 'str'}) # code字符串类型
df.set_index('code', inplace=True) # 将code设为索引列
df.loc['002522'] # 显示某支股票基本面
len(df.industry.unique()) # 显示行业数
len(df.area.unique()) # 显示地区数(即股票的归属省份)
# 按地区统计上市公司数量,体现地区经济实力
df.groupby('area').size().sort_values(ascending=False)
由上面的统计结果可见,经济越发达、越有活力的地区,上市公司的数量越多。读者还可以按行业进行类似的统计。数据框中的timeToMarket字段代表上市日期,其数据是格式形如“20190315”的整数类型。我们可以提取出其中的年份以统计每年的股票发行数量。
year = df.timeToMarket.astype('str').str[:4] # 转为字符串,提取前4位的年份
yearnum = df.groupby(year).size() # 按年份统计,得到每年股票发行量
yearnum
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定中文黑体字体
# 下面的False修正坐标轴上负号'-'显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
# 数据集中有几支股票没有发行年份(年份为0), 作图时排除0年份
yearnum[yearnum.index!='0'].plot(fontsize=14, title='年IPO数量')
从图中可见IPO发行年份的几个高点和国内股票市场的几次牛市时间对应,熊市时发行数量跌入低谷。下面计算市场的平均市盈率pe,这是衡量股票市场估值的重要参数。
df.pe.mean() # 简单的算术平均pe
观察数据集发现,数据集中亏损股票的pe为0,因此考虑剔除亏损股票。
df[df.pe > 0].pe.mean() # 剔除亏损股票后计算pe均值
上面的pe是简单的算术平均,以市值为权重的加权pe可能更能准确地反映市场状况。由于下载的数据集中没有总市值和股票单价,因此只能根据现有的字段推算总市值。由某些列的值计算新的列值也是数据处理中常有的情况。这里推算总市值的依据如下:
股票单价 = 4esp(每股收益)pe(市盈率)
总市值 = 股票单价*totals总股本(亿元人民币)
数据集中每股收益esp是单个季度的收益,因此全年收益要乘以4。
df['tvalue'] = 4 * df.esp * df.pe * df.totals # 计算总市值,增加新列tvalue
np.sum(df.pe * df.tvalue) / df.tvalue.sum() # 计算以市值为权重的加权pe
上面的计算结果反映了某次季报后的市场加权pe情况,结果和市场真实值相比有差异。这是因为股票的每个季度收益不同,因而不能简单按“4*单季收益”来计算全年收益。
我国股票市场现分为沪市(股票代码60开头)、深圳主板(股票代码00开头)、创业板(股票代码30开头)及最新上市的科创板(股票代码68开头)。如下代码可计算不同板块的pe值和股票数。
df['board'] = df.index.str[:2] # 取code的前2个字符,新增board列
# 按板块类型统计pe均值,计数
df.groupby('board').pe.agg([('pe均值', 'mean'), ('股票数', 'count')])