数据来源
分析数据来源为python第三方包,sharetop
这篇文章的主要目的和意义:
2023年整个经济环境处于下行周期,各行各业大部分都处于行业周期底部。如果一家上市公司内部高层对自己公司的前景和公司所处的行业有坚定的信心,而且这家公司经营正常,有很充足的现金流,那这家公司一定会抓住这个时间段来回购自己公司的股票。
结论
按照一级行业来分析
我们通过sharetop拿到2023年公司股票回购的详细数据,根据一级行业来对数据进行聚合分析。最终得到:回购股票排名前三的一级行业分别是:电子设备 116家,医药生物 109家,基础化工 92家。回购股票数量百分比排名前三的一级行业分布是:电子设备 22%,食品饮料 22%,医药生物 21%,电气设备和有色金属 都为 20%。
按照二级行业来分析
我们通过sharetop拿到2023年公司股票回购的详细数据,根据二级行业来对数据进行聚合分析。最终得到:电源设备,光电子设备,医疗器械等行业股票回购占比最大。
按照三级行业来分析
通过对最细第三级行业进行分析,过滤掉行业对应企业少于30家公司的行业,获得光伏太阳能行业回购比例最大占百分之四十七,最近一年光伏行业的股票价格一直在跌,但是他们的业绩还是一直在增长,这就让这些企业对自己的行业前景有很高的信心,他们手上的现金流也充足,就一直持续的进行股票回购。
通过对三级行业分析可以得到光伏等新能源行业对自己所在的行业前进很有信心。房地产行业对自己的行业前景最悲观,回购股票数量占比只有百分之二。
完整代码如下:
1,获取2023年回购股票的企业信息和回购股票详情
import pandas as pd
import sharetop as sp
token = "***"
sp_obj = sp.sp_prepare.BasicTop(token)
df = sp_obj.common_exec_func("stock_to_stock_repurchase", {"is_explain": False, "start_notice_date": "2023-01-01"})
df_dup = df.drop_duplicates(subset=['ts_code'],keep='first') # 存在一个公司2023年回购两次股票的情况,需要进行去重
2,获取最新的股票列表数据
def export_industry_list(row):
"""
将行业的总体数据分成三级行业数据
"""
industry_list = row['industry'].split('-')
return pd.Series(industry_list, index=['industry1', 'industry2', 'industry3'])
stock_list = sp_obj.common_exec_func("stock_to_list_data", {"is_explain": False, "fields": "ts_code,name,industry,area"})
stock_list_df = pd.concat([stock_list, stock_list.apply(export_industry_list, axis=1)], axis=1) # 将行业分开,分成三个字段
3,通过唯一的ts_code主键,从股票基本信息列表里面获取回购股票公司对应的行业分类
join_df = pd.merge(df_dup, stock_list_df, on='ts_code')
4,分别对总的股票列表和回购股票公司列表按照一级行业聚合
base_list = stock_list_df['industry1'].value_counts() #对总的股票列表按照一级行业进行聚合
reback_list = join_df['industry1'].value_counts() # 对回购股票的列表按照一级行业进行聚合
5,获取各个行业对应的总上市公司数量和2023年进行股票回购的公司数量的df
def core_process(industry, n):
"""
根据哪一级的行业来分析,排除多少家以下的行业,获取回购股票聚合df,该行业对应股票总的df
industry:industry1,industry2,industry3
n:该行业最低多少家企业
"""
base_list = stock_list_df[industry].value_counts() #对总的股票列表按照一级行业进行聚合
reback_list = join_df[industry].value_counts() # 对回购股票的列表按照一级行业进行聚合
# 获取总的上市公司按照行业聚合的df
base_list_dict = base_list.to_dict()
base_list_dict = {k: v for k, v in base_list_dict.items() if v >= n}
base_list_df_dict = {
"industry1": list(base_list_dict.keys()),
"count2": list(base_list_dict.values())
}
base_list_df = pd.DataFrame(base_list_df_dict)
# 获取2023年回购公司股票行业聚合的df
reback_list_dict = reback_list.to_dict()
reback_list_dict = {k: v for k, v in reback_list_dict.items() if k in base_list_dict}
reback_df_dict = {
"industry1": list(reback_list_dict.keys()),
"count1": list(reback_list_dict.values())
}
reback_list_df = pd.DataFrame(reback_df_dict)
return reback_list_df, base_list_df
6,根据数据绘图
def picture(reback_list_df, base_list_df):
# 通过一级行业分类将行业对应的总的公司数量和行业对应的回购股票的公司数量合并为一个df
result_join_df = pd.merge(reback_list_df, base_list_df, on='industry1')
# 计算出在各个行业中进行回购股票的公司占该行业对应的总公司数量的百分比
result_join_df.loc[:, 'per'] = round(result_join_df['count1']/result_join_df['count2'], 2)
result_join_r = result_join_df.to_dict("records")
industry1_list = [_['industry1'] for _ in result_join_r]
backup_list = [_['count1'] for _ in result_join_r]
all_list = [_['count2'] for _ in result_join_r]
per_list = [_['per']*100 for _ in result_join_r]
import plotly as py
import plotly.graph_objs as go
from plotly.subplots import make_subplots
pyplt = py.offline.plot
trace_1 = go.Bar(
x = industry1_list,
y = all_list,
name = "各行业对应企业总量"
)
trace_2 = go.Bar(
x = industry1_list,
y = backup_list,
name = "各行业回购企业总量"
)
trace_3 = go.Scatter(
x = industry1_list,
y = per_list,
name = "各行业回购企业百分比(%)",
xaxis='x',
yaxis='y2'
)
trace = [trace_1, trace_2, trace_3]
# Layout
layout = go.Layout(
yaxis2=dict(anchor='x', overlaying='y', side='right')#设置坐标轴的格式,一般次坐标轴在右侧
)
# Figure
figure = go.Figure(data = trace, layout = layout)
# Plot 图像展示
figure.show()
7,程序总入口
def run(industry="industry3", n=30):
"""
industry:industry1为一级行业,industry2为二级行业,industry3为三级行业
n:该行业最低多少家企业
"""
reback_list_df, base_list_df = core_process(industry, n)
picture(reback_list_df, base_list_df)
run()