量化专题——用AKShare获取上市公司财报关键指标数据、输出日报摘要并打包成exe

量化专题——用AKShare获取上市公司财报关键指标数据、输出日报摘要并打包成exe

本个小案例主要学习akshare的使用和exe的打包实操,作为小韭菜的入门量化的第一步。

参考来源:

Python:用AKShare获取上市公司财报关键指标数据、输出日报摘要并打包成exe

AKshare

官方文档:akshare 使用文档
我的笔记:jenkin的文档库

代码示例

Step1 导入相关库

1
2
3
4
5
import tkinter as tk
import akshare as ak
from tkinter import messagebox


这里只获取同花顺上的关键财务指标数据(akshare关键指标有新浪和同花顺两个网站的,新浪可以获得int数据,但是更新较慢),
目标网址:中兴通讯(000063)
财务概况_F10_同花顺金融服务网 (10jqka.com.cn)

Step2 进行数据处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

def remove_unit(money): # 去除单位部分,转化为元
if money[-2:] == "万亿":
money = float(money.replace("万亿", "")) * 1000000000000
elif money[-1] == "亿":
money = float(money.replace("亿", "")) * 100000000
elif money[-1] == "万":
money = float(money.replace("万", "")) * 10000
else:
money = float(money)
return money


def get_unit(money): # 将元转为为亿元或万元或万亿元
if abs(money) > 1000000000000:
scale = 1e-12
result = f"{money * scale:,.2f}万亿元"
elif abs(money) > 10000000:
scale = 1e-8
result = f"{money * scale:,.2f}亿元"
else:
scale = 1e-4
result = f"{money * scale:,.2f}万元"
return result


def str2percentage(percentage_string):
return float(percentage_string.strip('%')) # 将字符串形式的涨跌幅转变为小数形式

Step3 根据数据生成摘要

函数如下,注意参数和后面的函数要对应。这里的代码稍显麻烦,主要是在描述同比涨跌幅时公司有要求,具体生成的格式大家可按自己的要求进行更改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

def generate_summary(name, period_desc, revenue, revenue_change, profit, profit_change, pre_profit):
if revenue_change > 0:
revenue_desc = f"同比上升{revenue_change:.2f}%"
elif revenue_change < 0:
revenue_desc = f"同比下降{abs(revenue_change):.2f}%"
else:
revenue_desc = "同比持平"

if profit >= 0 and pre_profit >= 0:
if profit > pre_profit:
profit_decs = f"同比上升{profit_change:.2f}%"
elif profit < pre_profit:
profit_decs = f"同比下降{abs(profit_change):.2f}%"
else:
profit_decs = "同比持平"
elif profit > 0 > pre_profit:
profit_decs = "扭亏为盈"
elif profit < 0 < pre_profit:
profit_decs = "转盈为亏"
else: # 连年亏损
if abs(profit) > abs(pre_profit):
profit_decs = "亏损扩大"
elif abs(profit) < abs(pre_profit):
profit_decs = "亏损减少"
else:
profit_decs = "同比持平"
# 转化为亿元、万元的单位
revenue = get_unit(revenue)
profit = get_unit(profit)

summary = f"【{name}{period_desc}实现营业总收入{revenue}{revenue_desc};" \
f"归母净利润{profit}{profit_decs}。"

return summary

Step4 获取值啊要

需要输入报告期和股票代码。(这里只获取营收和利润数据,注意同花顺上这个净利润实际上是指归母净利润)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
date_mapping_1 = {
"03-31": "季度报告:",
"06-30": "半年度报告:",
"09-30": "季度报告:",
"12-31": "年度报告:"
}
date_mapping_2 = {
"03-31": "Q1",
"06-30": "H1",
"09-30": "前三季度",
"12-31": "年"
}


def get_summary():
period = period_entry.get()
code_list = code_list_entry.get().split(',')
try:
results = [] # 输出结果

title = date_mapping_1.get(period[5:], "未知") # 摘要标题
if title == "未知":
messagebox.showerror("报告期错误")
return # 结束函数的运行
quarter = date_mapping_2.get(period[5:], "未知") # 季度描述

# 获取去年同期的报告期字符串
year = period[:4] # 获取前四个字符
int_year = int(year) - 1 # 将前四个字符转换为数字并减去1
last_year = str(int_year).zfill(4) # 将得到的数字转换为字符串,补齐至四位
yoy_period = period.replace(year, last_year, 1) # 替换字符串的前四个字符,得到去年同期的报告期

period_desc = f"{title}公司{year}{quarter}"

# 对每个输入的code取数据
for code in code_list:
# 检查code能否匹配公司
try:
company = ak.stock_individual_info_em(symbol=code)
name = company.iloc[5][1]
except KeyError:
results.append(f"{code}:无法匹配\n")
continue
# 从同花顺获取关键财务指标
try:
data = ak.stock_financial_abstract_ths(symbol=code, indicator="按报告期")
data = data.set_index(data.columns[0])
except KeyError:
results.append(f"{code}{name}获取财报数据失败\n")
continue
# 判断是否存在数据
try:
revenue = remove_unit(data.loc[period, "营业总收入"])
revenue_change = str2percentage(data.loc[period, "营业总收入同比增长率"])
profit = remove_unit(data.loc[period, "净利润"])
profit_change = str2percentage(data.loc[period, "净利润同比增长率"])
# 获取去年归母净利润数据
pre_profit = remove_unit(data.loc[yoy_period, "净利润"])
except KeyError:
results.append(f"{code}{name}报告未更新\n")
continue

# 调用函数获取财报摘要,并保存在输出列表中
summary = generate_summary(name, period_desc, revenue, revenue_change, profit, profit_change, pre_profit)
results.append(f"{summary}\n")
result_text.config(state='normal') # 将输出区域状态更改为可编辑
result_text.delete('1.0', tk.END) # 清空区域
result_text.insert(tk.END, "\n".join(results)) # 将输出列表中的内容以换行符分隔,添加到输出区域中
result_text.config(state='disabled') # 将输出区域状态更改为不可编辑
except Exception as e:
messagebox.showerror("Error", f"获取摘要时出错:{str(e)}")


# 创建主窗口
root = tk.Tk()
root.title("日报-财务报告摘要akshare")

# 添加标签和输入框
period_label = tk.Label(root, text="请输入报告期(如2023-06-30)")
period_label.pack()

period_entry = tk.Entry(root)
period_entry.pack()

code_list_label = tk.Label(root, text="请输入公司code(多个则以英文逗号分隔)")
code_list_label.pack()

code_list_entry = tk.Entry(root, width=100)
code_list_entry.pack()

# 添加按钮
run_button = tk.Button(root, text="运行", command=get_summary)
run_button.pack()

# 添加结果显示区域
result_text = tk.Text(root, height=30, width=120, state='disabled')
result_text.pack()

# 启动 GUI 循环
root.mainloop()

运行结果示例

(公司发日报后大概3-5分钟能够获得数据)

img.png

img.png

akshare的打包

首先创建一个干净的虚拟环境,并下载aksharepyinstaller库。(不用虚拟环境的话打包出的文件可能会非常大)

在你想要创建虚拟环境的目录中打开终端(直接在地址栏键入cmd然后回车),依次输入:

1
2
3
4
python -m venv akshare-venv      
akshare-venv\Scripts\activate

pip install akshare Pyinstaller

然后将写好的py文件放到创建的文件夹中:

接着就可以开始打包了,

警告: 但akshare的打包往往会出问题,打包后会缺少两个关键文件

解决参考文档:
使用pyinstaller将akshare打包exe,无法运行终极解决方法。

将源码修改后,在终端中运行:(路径要设置正确)

1
2
pyinstaller.exe -F -w akshare-ths.py --add-data D:\Python\akshare-venv\Lib\site-packages\py_mini_racer\mini_racer.dll;.

打包完成后,点开dist文件夹,此时运行exe还是会报错,我们在exe程序的相同目录中创建名为akshare的文件夹,并在其中创建名为file_fold的文件夹,
然后在akshare-venv\Lib\site-packages\akshare\file_fold中找到calendar.json这个文件,将它复制到我们创建的file_fold里。

再次运行exe即可成功打开。

---The End---

量化专题——用AKShare获取上市公司财报关键指标数据、输出日报摘要并打包成exe

http://jenkina.cn/2023/10/14/quant/quant_01/

作者

Jenkin Liu

发布时间

2023-10-14

更新时间

2024-04-16

许可协议

评论

昵称
邮箱
网址
0/500
0 条评论