siat 3.10.130__py3-none-any.whl → 3.10.132__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. build/lib/build/lib/siat/__init__.py +75 -0
  2. build/lib/build/lib/siat/allin.py +137 -0
  3. build/lib/build/lib/siat/assets_liquidity.py +915 -0
  4. build/lib/build/lib/siat/beta_adjustment.py +1058 -0
  5. build/lib/build/lib/siat/beta_adjustment_china.py +548 -0
  6. build/lib/build/lib/siat/blockchain.py +143 -0
  7. build/lib/build/lib/siat/bond.py +2900 -0
  8. build/lib/build/lib/siat/bond_base.py +992 -0
  9. build/lib/build/lib/siat/bond_china.py +100 -0
  10. build/lib/build/lib/siat/bond_zh_sina.py +143 -0
  11. build/lib/build/lib/siat/capm_beta.py +783 -0
  12. build/lib/build/lib/siat/capm_beta2.py +887 -0
  13. build/lib/build/lib/siat/common.py +5360 -0
  14. build/lib/build/lib/siat/compare_cross.py +642 -0
  15. build/lib/build/lib/siat/copyrights.py +18 -0
  16. build/lib/build/lib/siat/cryptocurrency.py +667 -0
  17. build/lib/build/lib/siat/economy.py +1471 -0
  18. build/lib/build/lib/siat/economy2.py +1853 -0
  19. build/lib/build/lib/siat/esg.py +536 -0
  20. build/lib/build/lib/siat/event_study.py +815 -0
  21. build/lib/build/lib/siat/fama_french.py +1521 -0
  22. build/lib/build/lib/siat/fin_stmt2_yahoo.py +982 -0
  23. build/lib/build/lib/siat/financial_base.py +1160 -0
  24. build/lib/build/lib/siat/financial_statements.py +598 -0
  25. build/lib/build/lib/siat/financials.py +2339 -0
  26. build/lib/build/lib/siat/financials2.py +1278 -0
  27. build/lib/build/lib/siat/financials_china.py +4433 -0
  28. build/lib/build/lib/siat/financials_china2.py +2212 -0
  29. build/lib/build/lib/siat/fund.py +629 -0
  30. build/lib/build/lib/siat/fund_china.py +3307 -0
  31. build/lib/build/lib/siat/future_china.py +551 -0
  32. build/lib/build/lib/siat/google_authenticator.py +47 -0
  33. build/lib/build/lib/siat/grafix.py +3636 -0
  34. build/lib/build/lib/siat/holding_risk.py +867 -0
  35. build/lib/build/lib/siat/luchy_draw.py +638 -0
  36. build/lib/build/lib/siat/market_china.py +1168 -0
  37. build/lib/build/lib/siat/markowitz.py +2363 -0
  38. build/lib/build/lib/siat/markowitz2.py +3150 -0
  39. build/lib/build/lib/siat/markowitz2_20250704.py +2969 -0
  40. build/lib/build/lib/siat/markowitz2_20250705.py +3158 -0
  41. build/lib/build/lib/siat/markowitz_simple.py +373 -0
  42. build/lib/build/lib/siat/ml_cases.py +2291 -0
  43. build/lib/build/lib/siat/ml_cases_example.py +60 -0
  44. build/lib/build/lib/siat/option_china.py +3069 -0
  45. build/lib/build/lib/siat/option_pricing.py +1925 -0
  46. build/lib/build/lib/siat/other_indexes.py +409 -0
  47. build/lib/build/lib/siat/risk_adjusted_return.py +1576 -0
  48. build/lib/build/lib/siat/risk_adjusted_return2.py +1900 -0
  49. build/lib/build/lib/siat/risk_evaluation.py +2218 -0
  50. build/lib/build/lib/siat/risk_free_rate.py +351 -0
  51. build/lib/build/lib/siat/sector_china.py +4140 -0
  52. build/lib/build/lib/siat/security_price2.py +727 -0
  53. build/lib/build/lib/siat/security_prices.py +3408 -0
  54. build/lib/build/lib/siat/security_trend.py +402 -0
  55. build/lib/build/lib/siat/security_trend2.py +646 -0
  56. build/lib/build/lib/siat/stock.py +4284 -0
  57. build/lib/build/lib/siat/stock_advice_linear.py +934 -0
  58. build/lib/build/lib/siat/stock_base.py +26 -0
  59. build/lib/build/lib/siat/stock_china.py +2095 -0
  60. build/lib/build/lib/siat/stock_prices_kneighbors.py +910 -0
  61. build/lib/build/lib/siat/stock_prices_linear.py +386 -0
  62. build/lib/build/lib/siat/stock_profile.py +707 -0
  63. build/lib/build/lib/siat/stock_technical.py +3305 -0
  64. build/lib/build/lib/siat/stooq.py +74 -0
  65. build/lib/build/lib/siat/transaction.py +347 -0
  66. build/lib/build/lib/siat/translate.py +5183 -0
  67. build/lib/build/lib/siat/valuation.py +1378 -0
  68. build/lib/build/lib/siat/valuation_china.py +2076 -0
  69. build/lib/build/lib/siat/var_model_validation.py +444 -0
  70. build/lib/build/lib/siat/yf_name.py +811 -0
  71. build/lib/siat/__init__.py +75 -0
  72. build/lib/siat/allin.py +137 -0
  73. build/lib/siat/assets_liquidity.py +915 -0
  74. build/lib/siat/beta_adjustment.py +1058 -0
  75. build/lib/siat/beta_adjustment_china.py +548 -0
  76. build/lib/siat/blockchain.py +143 -0
  77. build/lib/siat/bond.py +2900 -0
  78. build/lib/siat/bond_base.py +992 -0
  79. build/lib/siat/bond_china.py +100 -0
  80. build/lib/siat/bond_zh_sina.py +143 -0
  81. build/lib/siat/capm_beta.py +783 -0
  82. build/lib/siat/capm_beta2.py +887 -0
  83. build/lib/siat/common.py +5360 -0
  84. build/lib/siat/compare_cross.py +642 -0
  85. build/lib/siat/copyrights.py +18 -0
  86. build/lib/siat/cryptocurrency.py +667 -0
  87. build/lib/siat/economy.py +1471 -0
  88. build/lib/siat/economy2.py +1853 -0
  89. build/lib/siat/esg.py +536 -0
  90. build/lib/siat/event_study.py +815 -0
  91. build/lib/siat/fama_french.py +1521 -0
  92. build/lib/siat/fin_stmt2_yahoo.py +982 -0
  93. build/lib/siat/financial_base.py +1160 -0
  94. build/lib/siat/financial_statements.py +598 -0
  95. build/lib/siat/financials.py +2339 -0
  96. build/lib/siat/financials2.py +1278 -0
  97. build/lib/siat/financials_china.py +4433 -0
  98. build/lib/siat/financials_china2.py +2212 -0
  99. build/lib/siat/fund.py +629 -0
  100. build/lib/siat/fund_china.py +3307 -0
  101. build/lib/siat/future_china.py +551 -0
  102. build/lib/siat/google_authenticator.py +47 -0
  103. build/lib/siat/grafix.py +3636 -0
  104. build/lib/siat/holding_risk.py +867 -0
  105. build/lib/siat/luchy_draw.py +638 -0
  106. build/lib/siat/market_china.py +1168 -0
  107. build/lib/siat/markowitz.py +2363 -0
  108. build/lib/siat/markowitz2.py +3150 -0
  109. build/lib/siat/markowitz2_20250704.py +2969 -0
  110. build/lib/siat/markowitz2_20250705.py +3158 -0
  111. build/lib/siat/markowitz_simple.py +373 -0
  112. build/lib/siat/ml_cases.py +2291 -0
  113. build/lib/siat/ml_cases_example.py +60 -0
  114. build/lib/siat/option_china.py +3069 -0
  115. build/lib/siat/option_pricing.py +1925 -0
  116. build/lib/siat/other_indexes.py +409 -0
  117. build/lib/siat/risk_adjusted_return.py +1576 -0
  118. build/lib/siat/risk_adjusted_return2.py +1900 -0
  119. build/lib/siat/risk_evaluation.py +2218 -0
  120. build/lib/siat/risk_free_rate.py +351 -0
  121. build/lib/siat/sector_china.py +4140 -0
  122. build/lib/siat/security_price2.py +727 -0
  123. build/lib/siat/security_prices.py +3408 -0
  124. build/lib/siat/security_trend.py +402 -0
  125. build/lib/siat/security_trend2.py +646 -0
  126. build/lib/siat/stock.py +4284 -0
  127. build/lib/siat/stock_advice_linear.py +934 -0
  128. build/lib/siat/stock_base.py +26 -0
  129. build/lib/siat/stock_china.py +2095 -0
  130. build/lib/siat/stock_prices_kneighbors.py +910 -0
  131. build/lib/siat/stock_prices_linear.py +386 -0
  132. build/lib/siat/stock_profile.py +707 -0
  133. build/lib/siat/stock_technical.py +3305 -0
  134. build/lib/siat/stooq.py +74 -0
  135. build/lib/siat/transaction.py +347 -0
  136. build/lib/siat/translate.py +5183 -0
  137. build/lib/siat/valuation.py +1378 -0
  138. build/lib/siat/valuation_china.py +2076 -0
  139. build/lib/siat/var_model_validation.py +444 -0
  140. build/lib/siat/yf_name.py +811 -0
  141. siat/__init__.py +0 -0
  142. siat/allin.py +0 -0
  143. siat/assets_liquidity.py +0 -0
  144. siat/beta_adjustment.py +0 -0
  145. siat/beta_adjustment_china.py +0 -0
  146. siat/blockchain.py +0 -0
  147. siat/bond.py +0 -0
  148. siat/bond_base.py +0 -0
  149. siat/bond_china.py +0 -0
  150. siat/bond_zh_sina.py +0 -0
  151. siat/capm_beta.py +0 -0
  152. siat/capm_beta2.py +0 -0
  153. siat/common.py +94 -30
  154. siat/compare_cross.py +0 -0
  155. siat/copyrights.py +0 -0
  156. siat/cryptocurrency.py +0 -0
  157. siat/economy.py +0 -0
  158. siat/economy2.py +0 -0
  159. siat/esg.py +0 -0
  160. siat/event_study.py +0 -0
  161. siat/fama_french.py +0 -0
  162. siat/fin_stmt2_yahoo.py +0 -0
  163. siat/financial_base.py +0 -0
  164. siat/financial_statements.py +0 -0
  165. siat/financials.py +0 -0
  166. siat/financials2.py +0 -0
  167. siat/financials_china.py +0 -0
  168. siat/financials_china2.py +0 -0
  169. siat/fund.py +0 -0
  170. siat/fund_china.py +0 -0
  171. siat/future_china.py +0 -0
  172. siat/google_authenticator.py +0 -0
  173. siat/grafix.py +1 -1
  174. siat/holding_risk.py +0 -0
  175. siat/luchy_draw.py +0 -0
  176. siat/market_china.py +7 -1
  177. siat/markowitz.py +0 -0
  178. siat/markowitz2.py +240 -39
  179. siat/markowitz2_20250704.py +2969 -0
  180. siat/markowitz2_20250705.py +3158 -0
  181. siat/markowitz_simple.py +0 -0
  182. siat/ml_cases.py +0 -0
  183. siat/ml_cases_example.py +0 -0
  184. siat/option_china.py +0 -0
  185. siat/option_pricing.py +0 -0
  186. siat/other_indexes.py +0 -0
  187. siat/risk_adjusted_return.py +0 -0
  188. siat/risk_adjusted_return2.py +0 -0
  189. siat/risk_evaluation.py +0 -0
  190. siat/risk_free_rate.py +0 -0
  191. siat/sector_china.py +0 -0
  192. siat/security_price2.py +0 -0
  193. siat/security_prices.py +3 -1
  194. siat/security_trend.py +0 -0
  195. siat/security_trend2.py +1 -1
  196. siat/stock.py +4 -2
  197. siat/stock_advice_linear.py +0 -0
  198. siat/stock_base.py +0 -0
  199. siat/stock_china.py +0 -0
  200. siat/stock_prices_kneighbors.py +0 -0
  201. siat/stock_prices_linear.py +0 -0
  202. siat/stock_profile.py +0 -0
  203. siat/stock_technical.py +0 -0
  204. siat/stooq.py +0 -0
  205. siat/transaction.py +0 -0
  206. siat/translate.py +11 -11
  207. siat/valuation.py +0 -0
  208. siat/valuation_china.py +0 -0
  209. siat/var_model_validation.py +0 -0
  210. siat/yf_name.py +0 -0
  211. {siat-3.10.130.dist-info → siat-3.10.132.dist-info}/METADATA +11 -11
  212. siat-3.10.132.dist-info/RECORD +218 -0
  213. siat-3.10.132.dist-info/top_level.txt +4 -0
  214. siat-3.10.130.dist-info/RECORD +0 -76
  215. siat-3.10.130.dist-info/top_level.txt +0 -1
  216. {siat-3.10.130.dist-info → siat-3.10.132.dist-info}/WHEEL +0 -0
  217. {siat-3.10.130.dist-info → siat-3.10.132.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,2212 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """
4
+ 本模块功能:计算财务报表指标,基于东方财富,仅限于中国大陆上市的企业
5
+ 所属工具包:证券投资分析工具SIAT
6
+ SIAT:Security Investment Analysis Tool
7
+ 创建日期:2024年4月21日
8
+ 最新修订日期:2022年5月18日
9
+ 作者:王德宏 (WANG Dehong, Peter)
10
+ 作者单位:北京外国语大学国际商学院
11
+ 作者邮件:wdehong2000@163.com
12
+ 版权所有:王德宏
13
+ 用途限制:仅限研究与教学使用,不可商用!商用需要额外授权。
14
+ 特别声明:作者不对使用本工具进行证券投资导致的任何损益负责!
15
+ """
16
+ #==============================================================================
17
+ #本模块的公共引用
18
+ import pandas as pd
19
+ import akshare as ak
20
+
21
+ # 这条语句似乎有时失灵!?
22
+ from siat.stock_china import *
23
+ from siat.financials_china import *
24
+ from siat.translate import *
25
+ #==============================================================================
26
+ #==============================================================================
27
+ if __name__=='__main__':
28
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
29
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
30
+
31
+ tickers = ['002415.SZ',#海康威视
32
+ '002236.SZ',#大华股份
33
+ "002528.SZ",#英飞拓
34
+ "300275.SZ",#梅安森
35
+ "603019.SS",#中科曙光
36
+ ]
37
+
38
+ fsdates = ['2022-12-31','2021-12-31','2020-12-31','2019-12-31']
39
+
40
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
41
+
42
+ def get_fin_stmt_ak_multi(tickers,fsdates):
43
+ """
44
+ 功能:获得多个股票的全部财报,基于akshare,合成,排序:股票代码+财报日期降序
45
+ 选择:仅保留fsdates日期的数据。注意:fsdates要比预计的多一项,以便计算期初数
46
+ """
47
+ from siat.financials_china import get_fin_stmt_ak
48
+ from siat.financials_china import fs_entry_begin_china
49
+
50
+ #循环获取全部股票的财报,并合成
51
+ df=pd.DataFrame()
52
+ for t in tickers:
53
+ dft=get_fin_stmt_ak(t)
54
+ if dft is None:
55
+ print(" #Warning(get_fin_stmt_ak_multi): currently data unavailable for",t)
56
+ continue
57
+ if len(dft) ==0:
58
+ print(" #Warning(get_fin_stmt_ak_multi): zero records available for",t)
59
+ continue
60
+
61
+ #按日期升序
62
+ dft.sort_index(ascending=True,inplace=True)
63
+ #选择指定的日期
64
+ dfs=dft[dft['endDate'].isin(fsdates)]
65
+
66
+ #列改名
67
+ dfs.rename(columns={'所有者权益(或股东权益)合计':'所有者权益合计',
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
+ },inplace=True)
96
+
97
+ #计算指标
98
+ entry_list=list(dfs)
99
+ #dfs['应收账款占比%']=round(dfs['应收账款']/dfs['资产总计']*100,2)
100
+ dfs['应收账款占比%']=dfs.apply(lambda x:round(x['应收账款']/x['资产总计']*100,2),axis=1)
101
+
102
+ #dfs['存货占比%']=round(dfs['存货']/dfs['资产总计']*100,2)
103
+ dfs['存货占比%']=dfs.apply(lambda x:round(x['存货']/x['资产总计']*100,2),axis=1)
104
+
105
+ if ('流动资产合计' in entry_list) and ('流动负债合计' in entry_list):
106
+ dfs['流动比率%']=dfs.apply(lambda x:round(x['流动资产合计']/x['流动负债合计']*100,2),axis=1)
107
+ dfs['速动资产合计']=dfs.apply(lambda x:x['流动资产合计']-x['存货'],axis=1)
108
+ dfs['速动比率%']=dfs.apply(lambda x:round(x['速动资产合计']/x['流动负债合计']*100,2),axis=1)
109
+ dfs['资产负债率%']=dfs.apply(lambda x:round(x['负债合计']/x['资产总计']*100,2),axis=1)
110
+
111
+ if not ('营业总收入' in entry_list) and ('营业收入' in entry_list):
112
+ dfs['营业总收入']=dfs['营业收入']
113
+ if not ('营业成本' in entry_list) and ('营业收入' in entry_list) and ('营业利润' in entry_list):
114
+ dfs['营业成本']=dfs['营业收入'] - dfs['营业利润']
115
+
116
+ dfs['毛利润']=dfs.apply(lambda x:x['营业总收入']-x['营业成本'],axis=1)
117
+ dfs['毛利润率%']=dfs.apply(lambda x:round(x['毛利润']/x['营业总收入']*100,2),axis=1)
118
+ dfs['营业利润率%']=dfs.apply(lambda x:round(x['营业利润']/x['营业总收入']*100,2),axis=1)
119
+
120
+ if '销售费用' in entry_list:
121
+ dfs['销售费用率%']=dfs.apply(lambda x:round(x['销售费用']/x['营业总收入']*100,2),axis=1)
122
+
123
+ if not ('管理费用' in entry_list) and ('业务及管理费用' in entry_list):
124
+ dfs['管理费用']=dfs['业务及管理费用']
125
+ dfs['管理费用率%']=dfs.apply(lambda x:round(x['管理费用']/x['营业总收入']*100,2),axis=1)
126
+ try:
127
+ dfs['研发费用率%']=dfs.apply(lambda x:round(x['研发费用']/x['营业总收入']*100,2),axis=1)
128
+ except:
129
+ dfs['研发费用率%']='-'
130
+
131
+ if not ('营业外收入' in entry_list) and ('加:营业外收入' in entry_list):
132
+ dfs['营业外收入']=dfs['加:营业外收入']
133
+ if not ('营业外支出' in entry_list) and ('减:营业外支出' in entry_list):
134
+ dfs['营业外支出']=dfs['减:营业外支出']
135
+ dfs['营业外收支']=dfs.apply(lambda x:x['营业外收入']-x['营业外支出'],axis=1)
136
+ dfs['税前利润']=dfs['利润总额']
137
+ dfs['税前利润率%']=dfs.apply(lambda x:round(x['利润总额']/x['营业总收入']*100,2),axis=1)
138
+
139
+ if not ('所得税费用' in entry_list) and ('减:所得税' in entry_list):
140
+ dfs['所得税费用']=dfs['减:所得税']
141
+ if '所得税费用' in list(dfs):
142
+ dfs['实际所得税率%']=dfs.apply(lambda x:round(x['所得税费用']/x['利润总额']*100,2),axis=1)
143
+
144
+ dfs['净利润率%']=dfs.apply(lambda x:round(x['净利润']/x['营业总收入']*100,2),axis=1)
145
+
146
+ #dfs['流通股股数']=dfs.apply(lambda x:round(x['净利润']/x['基本每股收益'],0),axis=1)
147
+ """
148
+ if '流动负债合计' in entry_list:
149
+ dfs['短期现金偿债能力%']=dfs.apply(lambda x:round(x['经营活动现金流净额']/x['流动负债合计']*100,2),axis=1)
150
+ dfs['长期现金偿债能力%']=dfs.apply(lambda x:round(x['经营活动现金流净额']/x['负债合计']*100,2),axis=1)
151
+ #dfs['现金支付股利能力(元)']=dfs.apply(lambda x:round(x['经营活动现金流净额']/x['流通股股数'],2),axis=1)
152
+
153
+ if not ('所有者权益合计' in entry_list) and ('负债及股东权益总计' in entry_list) and ('负债合计' in entry_list):
154
+ dfs['所有者权益合计']=dfs['负债及股东权益总计'] - dfs['负债合计']
155
+ dfs['现金综合支付能力%']=dfs.apply(lambda x:round(x['经营活动现金流净额']/x['所有者权益合计']*100,2),axis=1)
156
+ dfs['销售现金比率%']=dfs.apply(lambda x:round(x['经营活动现金流入']/x['营业总收入']*100,2),axis=1)
157
+ dfs['盈利现金比率%']=dfs.apply(lambda x:round(x['经营活动现金流净额']/x['净利润'],2),axis=1)
158
+ dfs['资产现金回收率%']=dfs.apply(lambda x:round(x['经营活动现金流净额']/x['资产总计']*100,2),axis=1)
159
+ dfs['现金流入流出比率%']=dfs.apply(lambda x:round(x['经营活动现金流入']/x['经营活动现金流出']*100,2),axis=1)
160
+
161
+ if not (((dfs['销售商品、提供劳务收到的现金']==0).all()) or ((dfs['购买商品、接受劳务支付的现金']==0).all())):
162
+ dfs['现金购销比率%']=dfs.apply(lambda x:round(x['购买商品、接受劳务支付的现金']/x['销售商品、提供劳务收到的现金']*100,2),axis=1)
163
+ dfs['营业现金回笼率%']=dfs.apply(lambda x:round(x['销售商品、提供劳务收到的现金']/x['营业总收入']*100,2),axis=1)
164
+ dfs['支付给职工的现金比率%']=dfs.apply(lambda x:round(x['支付给职工以及为职工支付的现金']/x['销售商品、提供劳务收到的现金']*100,2),axis=1)
165
+ """
166
+ # 自定义财务比率
167
+
168
+ #获取字段列表,增加期初项目
169
+ #去掉重复的列
170
+ dfst=dfs.T
171
+ dfst['index_tmp']=dfst.index #防止仅仅因为数值相同而被当作重复项误删
172
+ dfst.drop_duplicates(subset='index_tmp',keep='first',inplace=True)
173
+ dfst.drop(columns=['index_tmp'],axis=1,inplace=True)
174
+ dfs=dfst.T
175
+
176
+ col_list=list(dfs)
177
+ for c in col_list:
178
+ #print(c)
179
+ """
180
+ if isinstance(c,float) or isinstance(c,int):
181
+ dfs[c+"_期初"]=dfs[c].shift(1)
182
+ """
183
+ """
184
+ if not (c+"_期初" in col_list):
185
+ try:
186
+ dfs[c+"_期初"]=dfs[c].shift(1)
187
+ except:
188
+ print(" #Warning(get_fin_stmt_ak_multi): problematic column",c,'in the fin statements of',t)
189
+ else:
190
+ continue
191
+ """
192
+ dfs=fs_entry_begin_china(dfs,account_entry=c,suffix='_期初')
193
+
194
+ #给字段排序,便于检查对比
195
+ col_list_qc=list(dfs)
196
+ col_list2=sorted(col_list_qc)
197
+ dfs2=dfs[col_list2]
198
+
199
+ #合成
200
+ try:
201
+ df=df.append(dfs2)
202
+ except:
203
+ df=df._append(dfs2)
204
+
205
+ if df is None:
206
+ return None
207
+ if len(df)==0:
208
+ return None
209
+
210
+ #删除空值行:谨慎!!!
211
+ #df.dropna(inplace=True)
212
+
213
+ #删除多余的列,修改列名
214
+ #del df['ticker_期初']
215
+ df.rename(columns={'endDate_期初':'endDate_上期'},inplace=True)
216
+
217
+ #标注股票简称,去掉其中的(A股)字样
218
+ df["股票简称"]=df['ticker'].apply(lambda x: ticker_name(x,'stock').replace("(A股)",''))
219
+
220
+ """
221
+ # 替换nan为-
222
+ df.fillna('-',inplace=True)
223
+ df.replace(0,'-',inplace=True)
224
+ """
225
+
226
+ return df
227
+
228
+ #==============================================================================
229
+ if __name__=='__main__':
230
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
231
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
232
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
233
+
234
+ ticker="000002.SZ"
235
+ fsdate='2021-12-31'
236
+ item="货币资金"
237
+
238
+ select_item(df,ticker,fsdate,item)
239
+
240
+ def select_item(df,ticker,fsdate,item):
241
+ """
242
+ 功能:根据股票代码、财报日期和科目(含期初)查询金额;若全为零则提示
243
+ """
244
+
245
+ col_list=['ticker',"股票简称",'endDate',"endDate_上期",item,item+"_期初"]
246
+ dfs=df[(df['ticker']==ticker) & (df['endDate']==fsdate)][col_list]
247
+
248
+ try:
249
+ item_value=dfs[item].values[0]
250
+ item_value_qc=dfs[item+"_期初"].values[0]
251
+ except:
252
+ print(" #Warning(select_item):",ticker+"在"+fsdate+"的"+item+"未找到")
253
+ nann=float("nan")
254
+ return nann,nann,nann
255
+
256
+ #全为零提示
257
+ """
258
+ if (item_value==0) & (item_value_qc==0):
259
+ print(" #Warning(select_item):",ticker+"在"+fsdate+"的"+item+"及其期初数均为零")
260
+ """
261
+ return item_value,item_value_qc,dfs
262
+ #==============================================================================
263
+ if __name__=='__main__':
264
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
265
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
266
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
267
+
268
+ itemword1="固定资产"
269
+ itemword1="资产"
270
+ itemword2="计"
271
+
272
+ dfs=find_fs_items(df,itemword1,itemword2)
273
+
274
+ def find_fs_items(df,itemword1,itemword2='',printout=True):
275
+ """
276
+ 功能:搜索财务报表中含有关键词itemword的项目,并判断这些项目是否整列全为零
277
+ """
278
+
279
+ col_list=list(df)
280
+ col_yes=[]
281
+ for c in col_list:
282
+ if (itemword1 in c) & (itemword2 in c):
283
+ col_yes=col_yes+[c]
284
+
285
+ dfs=pd.DataFrame(columns=['报表项目','是否全为零'])
286
+ for cy in col_yes:
287
+ allzero=(df[cy].std()==0)
288
+
289
+ row=pd.Series({'报表项目':cy,'是否全为零':allzero})
290
+ try:
291
+ dfs=dfs.append(row,ignore_index=True)
292
+ except:
293
+ dfs=dfs._append(row,ignore_index=True)
294
+
295
+ if printout:
296
+ #设置打印对齐
297
+ pd.set_option('display.max_columns', 1000)
298
+ pd.set_option('display.width', 1000)
299
+ pd.set_option('display.max_colwidth', 1000)
300
+ pd.set_option('display.unicode.ambiguous_as_wide', True)
301
+ pd.set_option('display.unicode.east_asian_width', True)
302
+
303
+ #无序号打印
304
+ print('')
305
+ print(dfs.to_string(index=False))
306
+
307
+ return dfs
308
+
309
+ #==============================================================================
310
+ if __name__=='__main__':
311
+ title_txt="===== 重要指标的同行业对比 ====="
312
+
313
+ def title_position_original(title_txt,dfp):
314
+ """
315
+ 废弃
316
+ 功能:对dfp直接打印时计算让标题居中的位置,通过寻找各个回车符的位置。
317
+ """
318
+
319
+ #各个记录的长度
320
+ cuan=dfp.to_string(index=False)
321
+ pos_prev=0
322
+ pos=cuan.find('\n')
323
+ rowlen=pos
324
+ while pos != -1:
325
+ pos_prev=pos
326
+ pos=cuan.find('\n',pos_prev+1)
327
+ rowlen_new=pos - pos_prev
328
+ if rowlen_new > rowlen:
329
+ rowlen=rowlen_new
330
+
331
+ #抬头的长度
332
+ collist=list(dfp)
333
+ collen=0
334
+ for c in collist:
335
+ collen=collen+len(c)
336
+ collen=collen+(len(collist)-1)*2
337
+ if collen > rowlen:
338
+ rowlen=collen
339
+
340
+ blanknum=int((rowlen - len(title_txt))/2)
341
+
342
+ return blanknum-4
343
+ #==============================================================================
344
+ if __name__=='__main__':
345
+ title_txt="===== 重要指标的同行业对比 ====="
346
+
347
+ def title_position(title_txt,dfp):
348
+ """
349
+ 功能:对dfp直接打印时计算让标题居中的位置,通过寻找各个回车符的位置。
350
+ """
351
+
352
+ #各个记录的长度
353
+ cuan=dfp.to_string(index=False)+'\n'
354
+ pos=0
355
+ rowlen=0
356
+ while pos != -1:
357
+ pos_new=cuan.find('\n',pos+1)
358
+ sub_cuan=cuan[pos+1:pos_new]
359
+ rowlen_new=hzlen(sub_cuan)
360
+ #print(pos,pos_new,rowlen_new,sub_cuan)
361
+
362
+ if rowlen_new > rowlen:
363
+ rowlen=rowlen_new
364
+ pos=pos_new
365
+
366
+ title_len=hzlen(title_txt)+2
367
+ #blanknum=int((rowlen - title_len)/2)
368
+ blanknum=int((rowlen - title_len)/2)+(len(list(dfp))-2)
369
+
370
+ return blanknum
371
+
372
+ if __name__=='__main__':
373
+ title_txt="===== 重要指标的同行业对比 ====="
374
+ blanknum=title_position(title_txt,dfp)
375
+
376
+ print(' '*blanknum,title_txt)
377
+ print(dfp.to_string(index=False))
378
+
379
+ #==============================================================================
380
+ if __name__=='__main__':
381
+ title_txt="万科A财报:重要指标的同行业对比\n(财报截止日期:2021-12-31)"
382
+ footnote="*数据来源:新浪财经,2022年5月23日\n**股票列表第一项为分析对象\n*日期列表第一项为分析日期"
383
+ title_break=False
384
+ foot_break=True
385
+ foot_center=False
386
+ foot_start=4
387
+
388
+ def df_directprint_original(dfp,title_txt,footnote, \
389
+ title_break=True,foot_break=True,foot_center=False,foot_start=1, \
390
+ facecolor='papayawhip'):
391
+ """
392
+ 功能:对dfp直接打印,让标题居中,让脚注居中或指定开始位置。
393
+ """
394
+ print('')
395
+
396
+ #解析标题各行并居中打印
397
+ title_txt1=title_txt+'\n'
398
+ pos,pos_new=0,0
399
+ while pos_new != -1:
400
+ pos_new=title_txt1.find('\n',pos)
401
+ linetxt=title_txt1[pos:pos_new]
402
+ #print(linetxt)
403
+
404
+ blanknum=title_position(linetxt,dfp)
405
+
406
+ if linetxt != '\n':
407
+ print(' '*blanknum,linetxt)
408
+
409
+ pos=pos_new+1
410
+
411
+ #设置打印对齐
412
+ """
413
+ pd.set_option('display.max_columns', 1000)
414
+ pd.set_option('display.width', 1000)
415
+ pd.set_option('display.max_colwidth', 1000)
416
+ pd.set_option('display.unicode.ambiguous_as_wide', True)
417
+ pd.set_option('display.unicode.east_asian_width', True)
418
+ """
419
+
420
+ #打印数据框本身
421
+ #print(dfp.to_string(index=False))
422
+ colalign=['left']+['right']*(len(list(dfp)) - 1)
423
+ print(dfp.to_markdown(tablefmt='Simple',index=False,colalign=colalign))
424
+
425
+ #解析脚注各行并打印
426
+ if foot_break: print('')
427
+ footnote1=footnote+'\n'
428
+ pos,pos_new=0,0
429
+ while pos_new != -1:
430
+ pos_new=footnote1.find('\n',pos)
431
+ linetxt=footnote1[pos:pos_new]
432
+ #print(linetxt)
433
+ if foot_center:
434
+ blanknum=title_position(linetxt,dfp)
435
+ else:
436
+ blanknum=foot_start-1
437
+
438
+ if linetxt != '\n':
439
+ if blanknum >2:
440
+ print(' '*blanknum,linetxt)
441
+ else:
442
+ print(linetxt)
443
+
444
+ pos=pos_new+1
445
+
446
+ return
447
+
448
+ #==============================================================================
449
+ """
450
+ def df_directprint(dfp,title_txt,footnote, \
451
+ title_break=True,foot_break=True,foot_center=False,foot_start=1, \
452
+ decimals=2,facecolor='papayawhip'):
453
+ """
454
+ def df_directprint(dfp,title_txt,footnote,decimals=2,facecolor='papayawhip',font_size='16px'):
455
+ """
456
+ 功能:对dfp直接打印,使用pandas style打印,套壳函数df_display_CSS
457
+ """
458
+ #替换nan和inf
459
+ import pandas as pd
460
+ import numpy as np
461
+ dfp.replace([np.inf, -np.inf],'-', inplace=True)
462
+ dfp.replace([np.nan],'-', inplace=True)
463
+
464
+ #print('') #空一行
465
+
466
+ """
467
+ #解析标题各行并居中打印
468
+ title_txt1=title_txt+'\n'
469
+ pos,pos_new=0,0
470
+ while pos_new != -1:
471
+ pos_new=title_txt1.find('\n',pos)
472
+ linetxt=title_txt1[pos:pos_new]
473
+ #print(linetxt)
474
+
475
+ blanknum=title_position(linetxt,dfp)
476
+
477
+ if linetxt != '\n':
478
+ print(' '*blanknum,linetxt)
479
+
480
+ pos=pos_new+1
481
+ """
482
+
483
+ #确定表格字体大小
484
+ titile_font_size=font_size
485
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
486
+
487
+ df_display_CSS(dfp,titletxt=title_txt,footnote=footnote,facecolor=facecolor, \
488
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
489
+ data_font_size=data_font_size)
490
+
491
+ """
492
+ disph=dfp.style.hide() #不显示索引列
493
+ dispp=disph.format(precision=decimals) #设置带有小数点的列精度调整为小数点后2位
494
+
495
+ #设置标题/列名
496
+ dispt=dispp.set_caption(title_txt).set_table_styles(
497
+ [{'selector':'caption', #设置标题对齐
498
+ 'props':[('color','black'),('font-size','18px'),('font-weight','bold')]}, \
499
+ {'selector':'th.col_heading', #设置列名对齐
500
+ 'props':[('color','black'),('background-color',facecolor), \
501
+ ('font-size','17px'),('text-align','center'),('margin','auto')]}])
502
+
503
+ #设置数据对齐
504
+ dispt1=dispt.set_properties(**{'font-size':'17px'})
505
+ dispf=dispt1.set_properties(**{'text-align':'center'})
506
+
507
+ #设置前景背景颜色
508
+ try:
509
+ dispf2=dispf.set_properties(**{'background-color':facecolor,'color':'black'})
510
+ except:
511
+ print(" #Warning(df_directprint): unknown color",facecolor,"\b, changed to default one")
512
+ dispf2=dispf.set_properties(**{'background-color':'papayawhip','color':'black'})
513
+
514
+ #打印数据框本身
515
+ from IPython.display import display
516
+ display(dispf2)
517
+ """
518
+ """
519
+ #print(dfp.to_string(index=False))
520
+ colalign=['left']+['right']*(len(list(dfp)) - 1)
521
+ print(dfp.to_markdown(tablefmt='Simple',index=False,colalign=colalign))
522
+ """
523
+
524
+ #解析脚注各行并打印
525
+ """
526
+ if foot_break: print('')
527
+ footnote1=footnote+'\n'
528
+ pos,pos_new=0,0
529
+ while pos_new != -1:
530
+ pos_new=footnote1.find('\n',pos)
531
+ linetxt=footnote1[pos:pos_new]
532
+ #print(linetxt)
533
+ if foot_center:
534
+ blanknum=title_position(linetxt,dfp)
535
+ else:
536
+ blanknum=foot_start-1
537
+
538
+ if linetxt != '\n':
539
+ if blanknum >2:
540
+ print(' '*blanknum,linetxt)
541
+ else:
542
+ print(linetxt)
543
+
544
+ pos=pos_new+1
545
+ """
546
+ #print('') #空一行
547
+ #print(footnote,'\n')
548
+
549
+ return
550
+ #==============================================================================
551
+
552
+ if __name__=='__main__':
553
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
554
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
555
+
556
+ tickers=['601328.SS','601398.SS','601288.SS','601988.SS','601939.SS','601658.SS']
557
+ fsdates=['2022-12-31','2021-12-31','2010-12-31','2019-12-31']
558
+
559
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
560
+
561
+ ticker="601328.SS"
562
+ fsdate='2022-12-31'
563
+ items=["货币资金","应收票据","应收账款"]
564
+ dfp=fs_item_analysis_1(df,ticker,fsdate,items)
565
+
566
+ def fs_item_analysis_1(df,ticker,fsdate,items,title_txt='',notes='', \
567
+ facecolor='papayawhip',font_size='16px'):
568
+ """
569
+ 功能:比较给定财报日期的资产项目、期初数、期末数、变动额和变动幅度%
570
+ """
571
+
572
+ #循环获取科目
573
+ dfp=pd.DataFrame(columns=['报表项目','期初数', '期末数', '变动额', '变动幅度%'])
574
+ yiyuan=100000000
575
+
576
+ import math
577
+ for i in items:
578
+ i_value,i_value_qc,dft=select_item(df,ticker,fsdate,i)
579
+
580
+ """
581
+ if not(i_value != 0 or i_value_qc != 0):
582
+ print(" #Warning(income_cost_analysis_1): 因其零值而忽略"+i+"项目")
583
+ continue
584
+ """
585
+
586
+ if not math.isnan(i_value):
587
+ i_value_yy=round(i_value/yiyuan,4)
588
+ i_value_qc_yy=round(i_value_qc/yiyuan,4)
589
+ i_value_chg_yy=round(i_value_yy - i_value_qc_yy,2)
590
+ if not(i_value_qc_yy==0):
591
+ i_value_chg_pct=round(i_value_chg_yy/i_value_qc_yy*100,2)
592
+ #对于变动幅度符号的修正
593
+ if (i_value_chg_pct < 0) and (i_value_qc_yy < 0):
594
+ i_value_chg_pct=abs(i_value_chg_pct)
595
+ else:
596
+ i_value_chg_pct='-'
597
+ else:
598
+ i_value_qc_yy,i_value_yy,i_value_chg_yy,i_value_chg_pct='-','-','-','-'
599
+
600
+ row=pd.Series({'报表项目':i,'期初数':i_value_qc_yy, \
601
+ '期末数':i_value_yy, '变动额':i_value_chg_yy, \
602
+ '变动幅度%':i_value_chg_pct})
603
+ try:
604
+ dfp=dfp.append(row,ignore_index=True)
605
+ except:
606
+ dfp=dfp._append(row,ignore_index=True)
607
+
608
+ dfp=dfp.replace(0,'-')
609
+ dfp=dfp.fillna('-')
610
+
611
+ #无序号打印
612
+ if title_txt=='':
613
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
614
+ title_txt=tname+"财报分析:重要项目的变动情况\n(截至"+fsdate+")"
615
+ import datetime; todaydt=datetime.date.today()
616
+ #footnote="*单位:亿元,数据来源:新浪财经,"+str(today)
617
+ #footnote="*单位:亿元,本期报表日期:"+fsdate+',数据来源:新浪财经'
618
+ footnote="单位:亿元,数据来源:新浪财经,"+str(todaydt)
619
+
620
+ if notes=='':
621
+ foottext=footnote
622
+ else:
623
+ foottext=notes+'\n'+footnote
624
+
625
+ #确定表格字体大小
626
+ titile_font_size=font_size
627
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
628
+
629
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
630
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
631
+ first_col_align='left', \
632
+ facecolor=facecolor,decimals=2, \
633
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
634
+ data_font_size=data_font_size)
635
+
636
+ return dfp
637
+
638
+
639
+ #==============================================================================
640
+ if __name__=='__main__':
641
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
642
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
643
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
644
+
645
+ ticker="000002.SZ"
646
+ fsdates=['2021-12-31','2020-12-31','2019-12-31']
647
+ items=["应收账款","资产总计"]
648
+ find_fs_items(df,itemword1="应收账款",itemword2='')
649
+ find_fs_items(df,itemword1="资产",itemword2='计')
650
+
651
+ dfp=fs_item_analysis_2(df,ticker,fsdates,items)
652
+
653
+ def fs_item_analysis_2(df,ticker,fsdates,items,title_txt='',notes='', \
654
+ facecolor='papayawhip',font_size='16px'):
655
+ """
656
+ 功能:比较给定财报日期的报表项目、最近几年fsdates、占比%
657
+ """
658
+ fsdates1=sorted(fsdates,reverse=True)
659
+
660
+ #循环获取科目
661
+ col_list=['报表项目(亿元)']+fsdates1
662
+ dfp=pd.DataFrame(columns=col_list)
663
+
664
+ yiyuan=100000000
665
+ import math
666
+
667
+ for i in items:
668
+ row_list=[i]
669
+ for fd in fsdates1:
670
+ i_value,_,_=select_item(df,ticker,fd,i)
671
+ row_list=row_list+[round(i_value/yiyuan,4)]
672
+ dfp.loc[len(dfp)] = row_list
673
+
674
+ last_row=[items[0]+"占比%"]
675
+ for fd in fsdates1:
676
+ rate=round(dfp[fd][0]/dfp[fd][1]*100,2)
677
+ last_row=last_row+[rate]
678
+ dfp.loc[len(dfp)] = last_row
679
+
680
+ dfp=dfp.replace(0,'-')
681
+ dfp=dfp.fillna('-')
682
+
683
+ #无序号打印
684
+ if title_txt=='':
685
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
686
+ title_txt=tname+"财报分析:重要项目占比的变动趋势"
687
+ import datetime; todaydt=datetime.date.today()
688
+ footnote="数据来源:新浪财经,"+str(todaydt)
689
+
690
+ if notes=='':
691
+ foottext=footnote
692
+ else:
693
+ foottext=notes+'\n'+footnote
694
+
695
+ #确定表格字体大小
696
+ titile_font_size=font_size
697
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
698
+
699
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
700
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
701
+ first_col_align='left', \
702
+ facecolor=facecolor,decimals=2, \
703
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
704
+ data_font_size=data_font_size)
705
+
706
+ return dfp
707
+
708
+ #==============================================================================
709
+ if __name__=='__main__':
710
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
711
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
712
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
713
+
714
+ ticker="000002.SZ"
715
+ fsdates=['2021-12-31','2020-12-31','2019-12-31']
716
+
717
+ dfp=fs_item_analysis_3(df,ticker,fsdates)
718
+
719
+ def fs_item_analysis_3(df,ticker,fsdates,title_txt='',notes='', \
720
+ facecolor='papayawhip',font_size='16px'):
721
+ """
722
+ 功能:比较给定财报日期的流动比率、最近几年fsdates
723
+ """
724
+ fsdates1=sorted(fsdates,reverse=True)
725
+
726
+ #循环获取科目
727
+ col_list=['报表项目(亿元)']+fsdates1
728
+ dfp=pd.DataFrame(columns=col_list)
729
+ yiyuan=100000000
730
+
731
+ items=['流动资产合计','流动负债合计']
732
+ for i in items:
733
+ row_list=[i]
734
+ for fd in fsdates1:
735
+ i_value,_,_=select_item(df,ticker,fd,i)
736
+ row_list=row_list+[round(i_value/yiyuan,4)]
737
+ dfp.loc[len(dfp)] = row_list
738
+
739
+ last_row=["流动比率%"]
740
+ for fd in fsdates1:
741
+ rate=round(dfp[fd][0]/dfp[fd][1]*100,2)
742
+ last_row=last_row+[rate]
743
+ dfp.loc[len(dfp)] = last_row
744
+
745
+ dfp=dfp.replace(0,'-')
746
+ dfp=dfp.fillna('-')
747
+
748
+ #无序号打印
749
+ if title_txt=='':
750
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
751
+ title_txt=tname+"财报分析:流动比率的变动趋势"
752
+ import datetime; todaydt=datetime.date.today()
753
+ footnote="数据来源:新浪财经,"+str(todaydt)
754
+
755
+ if notes=='':
756
+ foottext=footnote
757
+ else:
758
+ foottext=notes+'\n'+footnote
759
+
760
+ #确定表格字体大小
761
+ titile_font_size=font_size
762
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
763
+
764
+ #确定表格字体大小
765
+ titile_font_size=font_size
766
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
767
+
768
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
769
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
770
+ first_col_align='left', \
771
+ facecolor=facecolor,decimals=2, \
772
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
773
+ data_font_size=data_font_size)
774
+
775
+ return dfp
776
+
777
+ #==============================================================================
778
+ if __name__=='__main__':
779
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
780
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
781
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
782
+
783
+ ticker="000002.SZ"
784
+ fsdates=['2021-12-31','2020-12-31','2019-12-31']
785
+
786
+ dfp=fs_item_analysis_4(df,ticker,fsdates)
787
+
788
+ def fs_item_analysis_4(df,ticker,fsdates,title_txt='',notes='', \
789
+ facecolor='papayawhip',font_size='16px'):
790
+ """
791
+ 功能:比较给定财报日期的流动比率、最近几年fsdates
792
+ """
793
+ fsdates1=sorted(fsdates,reverse=True)
794
+
795
+ #循环获取科目
796
+ col_list=['报表项目(亿元)']+fsdates1
797
+ dfp=pd.DataFrame(columns=col_list)
798
+ yiyuan=100000000
799
+
800
+ i='流动资产合计'
801
+ row_list=[i]
802
+ for fd in fsdates1:
803
+ i_value,_,_=select_item(df,ticker,fd,i)
804
+ row_list=row_list+[round(i_value/yiyuan,4)]
805
+ dfp.loc[len(dfp)] = row_list
806
+
807
+ i='存货'
808
+ row_list=['其中:'+i]
809
+ for fd in fsdates1:
810
+ i_value,_,_=select_item(df,ticker,fd,i)
811
+ row_list=row_list+[round(i_value/yiyuan,4)]
812
+ dfp.loc[len(dfp)] = row_list
813
+
814
+ i='速动资产合计'
815
+ row_list=[i]
816
+ for fd in fsdates1:
817
+ rate=round(dfp[fd][0]-dfp[fd][1],2)
818
+ row_list=row_list+[rate]
819
+ dfp.loc[len(dfp)] = row_list
820
+
821
+ i='流动负债合计'
822
+ row_list=[i]
823
+ for fd in fsdates1:
824
+ i_value,_,_=select_item(df,ticker,fd,i)
825
+ row_list=row_list+[round(i_value/yiyuan,4)]
826
+ dfp.loc[len(dfp)] = row_list
827
+
828
+ last_row=["速动比率%"]
829
+ for fd in fsdates1:
830
+ rate=round(dfp[fd][2]/dfp[fd][3]*100,2)
831
+ last_row=last_row+[rate]
832
+ dfp.loc[len(dfp)] = last_row
833
+
834
+ dfp=dfp.replace(0,'-')
835
+ dfp=dfp.fillna('-')
836
+
837
+ #无序号打印
838
+ if title_txt=='':
839
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
840
+ title_txt=tname+"财报分析:速动比率的变动趋势"
841
+ import datetime; todaydt=datetime.date.today()
842
+ footnote="数据来源:新浪财经,"+str(todaydt)
843
+
844
+ if notes=='':
845
+ foottext=footnote
846
+ else:
847
+ foottext=notes+'\n'+footnote
848
+
849
+ #确定表格字体大小
850
+ titile_font_size=font_size
851
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
852
+
853
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
854
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
855
+ first_col_align='left', \
856
+ facecolor=facecolor,decimals=2, \
857
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
858
+ data_font_size=data_font_size)
859
+ return dfp
860
+
861
+ #==============================================================================
862
+ if __name__=='__main__':
863
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
864
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
865
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
866
+
867
+ ticker="000002.SZ"
868
+ fsdates=['2021-12-31','2020-12-31','2019-12-31']
869
+
870
+ dfp=fs_item_analysis_5(df,ticker,fsdates)
871
+
872
+ def fs_item_analysis_5(df,ticker,fsdates,title_txt='',notes='', \
873
+ facecolor='papayawhip',font_size='16px'):
874
+ """
875
+ 功能:比较给定财报日期的流动比率、最近几年fsdates
876
+ """
877
+
878
+ #循环获取科目
879
+ col_list=['报表项目(亿元)']+fsdates
880
+ dfp=pd.DataFrame(columns=col_list)
881
+ yiyuan=100000000
882
+
883
+ fsdates1=sorted(fsdates,reverse=True)
884
+ items=['资产总计','负债合计']
885
+ for i in items:
886
+ row_list=[i]
887
+ for fd in fsdates1:
888
+ i_value,_,_=select_item(df,ticker,fd,i)
889
+ row_list=row_list+[round(i_value/yiyuan,4)]
890
+ dfp.loc[len(dfp)] = row_list
891
+
892
+ last_row=["资产负债率%"]
893
+ for fd in fsdates1:
894
+ rate=round(dfp[fd][1]/dfp[fd][0]*100,2)
895
+ last_row=last_row+[rate]
896
+ dfp.loc[len(dfp)] = last_row
897
+
898
+ dfp=dfp.replace(0,'-')
899
+ dfp=dfp.fillna('-')
900
+
901
+ #无序号打印
902
+ if title_txt=='':
903
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
904
+ title_txt=tname+"财报分析:资产负债率的变动趋势"
905
+ import datetime; todaydt=datetime.date.today()
906
+ footnote="数据来源:新浪财经,"+str(todaydt)
907
+
908
+ if notes=='':
909
+ foottext=footnote
910
+ else:
911
+ foottext=notes+'\n'+footnote
912
+
913
+ #确定表格字体大小
914
+ titile_font_size=font_size
915
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
916
+
917
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
918
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
919
+ first_col_align='left', \
920
+ facecolor=facecolor,decimals=2, \
921
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
922
+ data_font_size=data_font_size)
923
+ return dfp
924
+
925
+ #==============================================================================
926
+ if __name__=='__main__':
927
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
928
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
929
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
930
+
931
+ ticker="000002.SZ"
932
+ fsdates=['2021-12-31','2020-12-31']
933
+ items=['应收账款','营业收入']
934
+
935
+ dfp=fs_item_analysis_6(df,ticker,fsdates,items)
936
+
937
+ def fs_item_analysis_6_original(df,ticker,fsdates,items,title_txt='',notes=''):
938
+ """
939
+ 废弃!!!
940
+ 功能:比较给定财报日期的应收账款与营业收入增幅、最近几年fsdates
941
+ """
942
+
943
+ #循环获取科目
944
+ items1=[]
945
+ for i in items:
946
+ items1=items1+[i+'(亿元)']
947
+
948
+ col_list=['报表日期']+items1
949
+ dfp=pd.DataFrame(columns=col_list)
950
+ yiyuan=100000000
951
+
952
+ fsdates1=sorted(fsdates,reverse=False)
953
+ for fd in fsdates1:
954
+ row_list=[fd]
955
+ for i in items:
956
+ i_value,_,_=select_item(df,ticker,fd,i)
957
+ row_list=row_list+[round(i_value/yiyuan,4)]
958
+ dfp.loc[len(dfp)] = row_list
959
+
960
+ last_row=["增幅%"]
961
+ for i in items1:
962
+ rate=round((dfp[i][1]/dfp[i][0]-1)*100,2)
963
+ last_row=last_row+[rate]
964
+ dfp.loc[len(dfp)] = last_row
965
+
966
+ # 替换nan
967
+ dfp=dfp.fillna('-')
968
+ dfp=dfp.replace(0,'-')
969
+
970
+ #无序号打印
971
+ if title_txt=='':
972
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
973
+ title_txt=tname+"财报分析:重要关联项目的增幅对比"
974
+ import datetime; todaydt=datetime.date.today()
975
+ footnote="数据来源:新浪财经,"+str(todaydt)
976
+
977
+ if notes=='':
978
+ foottext=footnote
979
+ else:
980
+ foottext=notes+'\n'+footnote
981
+
982
+ df_directprint(dfp,title_txt,foottext)
983
+
984
+ return dfp
985
+ #==============================================================================
986
+ if __name__=='__main__':
987
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
988
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
989
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
990
+
991
+ ticker="000002.SZ"
992
+ fsdates=['2021-12-31','2020-12-31']
993
+ items=['应收账款','营业收入']
994
+
995
+ dfp=fs_item_analysis_6(df,ticker,fsdates,items)
996
+
997
+ def fs_item_analysis_6(df,ticker,fsdates,items,title_txt='',notes='', \
998
+ facecolor='papayawhip',font_size='16px'):
999
+ """
1000
+ 功能:比较给定财报日期的应收账款与营业收入增幅、最近几年fsdates
1001
+ """
1002
+
1003
+ col_list=['报表日期']+items
1004
+ dfp=pd.DataFrame(columns=col_list)
1005
+ yiyuan=100000000
1006
+ yiyuan_foot=False
1007
+
1008
+ fsdates1=sorted(fsdates,reverse=False)
1009
+ for fd in fsdates1:
1010
+ row_list=[fd]
1011
+ for i in items:
1012
+ i_value,_,_=select_item(df,ticker,fd,i)
1013
+ if not('%' in i) and not('(元)' in i):
1014
+ row_list=row_list+[round(i_value/yiyuan,4)]
1015
+ yiyuan_foot=True
1016
+ else:
1017
+ row_list=row_list+[i_value]
1018
+ dfp.loc[len(dfp)] = row_list
1019
+
1020
+ last_row=["增幅%"]
1021
+ for i in items:
1022
+ rate=round((dfp[i][1]/dfp[i][0]-1)*100,2)
1023
+ last_row=last_row+[rate]
1024
+ dfp.loc[len(dfp)] = last_row
1025
+
1026
+ # 替换nan
1027
+ dfp=dfp.fillna('-')
1028
+ dfp=dfp.replace(0,'-')
1029
+
1030
+ #无序号打印
1031
+ if title_txt=='':
1032
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
1033
+ title_txt=tname+"财报分析:重要关联项目的增幅对比"
1034
+ import datetime; todaydt=datetime.date.today()
1035
+ if yiyuan_foot:
1036
+ footnote="单位:亿元,数据来源:新浪财经,"+str(todaydt)
1037
+ else:
1038
+ footnote="数据来源:新浪财经,"+str(todaydt)
1039
+
1040
+ if notes=='':
1041
+ foottext=footnote
1042
+ else:
1043
+ foottext=notes+'\n'+footnote
1044
+
1045
+ #确定表格字体大小
1046
+ titile_font_size=font_size
1047
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
1048
+
1049
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
1050
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
1051
+ first_col_align='left', \
1052
+ facecolor=facecolor,decimals=2, \
1053
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
1054
+ data_font_size=data_font_size)
1055
+ return dfp
1056
+
1057
+ #==============================================================================
1058
+ if __name__=='__main__':
1059
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1060
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
1061
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
1062
+
1063
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1064
+ fsdate='2021-12-31'
1065
+ items=['存货','资产总计','存货占比%']
1066
+
1067
+ dfp=fs_item_analysis_7(df,tickers,fsdate,items)
1068
+
1069
+ def fs_item_analysis_7_original(df,tickers,fsdate,items,title_txt=''):
1070
+ """
1071
+ 废弃!!!
1072
+ 功能:比较给定财报日期fsdate的项目和指标,与同业相比
1073
+ """
1074
+
1075
+ #循环获取科目
1076
+ items1=[]
1077
+ for i in items:
1078
+ if not('%' in i):
1079
+ items1=items1+[i+'(亿元)']
1080
+ else:
1081
+ items1=items1+[i]
1082
+
1083
+ col_list=['上市公司']+items1
1084
+ dfp=pd.DataFrame(columns=col_list)
1085
+ yiyuan=100000000
1086
+ yiyuan_foot=False
1087
+
1088
+ for t in tickers:
1089
+ tname=ticker_name(t,'stock').replace("(A股)",'')
1090
+ row_list=[tname]
1091
+ for i in items:
1092
+ i_value,_,_=select_item(df,t,fsdate,i)
1093
+ if not('%' in i) and not('(元)' in i):
1094
+ row_list=row_list+[round(i_value/yiyuan,4)]
1095
+ yiyuan_foot=True
1096
+ else:
1097
+ row_list=row_list+[i_value]
1098
+ dfp.loc[len(dfp)] = row_list
1099
+
1100
+ #主要项目排序
1101
+
1102
+ dfp=dfp.replace(0,'-')
1103
+ dfp=dfp.fillna('-')
1104
+
1105
+ #无序号打印
1106
+ if title_txt=='':
1107
+ title_txt="=== 重要指标的同行业对比 ==="
1108
+ ticker=tickers[0]
1109
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
1110
+ title_txt=tname+"财报分析:重要指标的同行业对比\n(截至"+fsdate+")"
1111
+ import datetime; todaydt=datetime.date.today()
1112
+ if yiyuan_foot:
1113
+ footnote="单位:亿元,数据来源:新浪财经,"+str(todaydt)
1114
+ else:
1115
+ footnote="数据来源:新浪财经,"+str(todaydt)
1116
+ df_directprint(dfp,title_txt,footnote)
1117
+
1118
+ return dfp
1119
+ #==============================================================================
1120
+ if __name__=='__main__':
1121
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1122
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
1123
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
1124
+
1125
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1126
+ fsdate='2021-12-31'
1127
+ items=['存货','资产总计','存货占比%']
1128
+
1129
+ dfp=fs_item_analysis_7(df,tickers,fsdate,items)
1130
+
1131
+ def fs_item_analysis_7(df,tickers,fsdate,items,title_txt='',notes='', \
1132
+ facecolor='papayawhip',font_size='16px'):
1133
+ """
1134
+ 功能:比较给定财报日期fsdate的项目和指标,与同业相比
1135
+ """
1136
+
1137
+ col_list=['上市公司']+items
1138
+ dfp=pd.DataFrame(columns=col_list)
1139
+ yiyuan=100000000
1140
+ yiyuan_foot=False
1141
+
1142
+ for t in tickers:
1143
+ tname=ticker_name(t,'stock').replace("(A股)",'')
1144
+ row_list=[tname]
1145
+ for i in items:
1146
+ i_value,_,_=select_item(df,t,fsdate,i)
1147
+ if not('%' in i) and not('(元)' in i):
1148
+ row_list=row_list+[round(i_value/yiyuan,4)]
1149
+ yiyuan_foot=True
1150
+ else:
1151
+ row_list=row_list+[i_value]
1152
+ dfp.loc[len(dfp)] = row_list
1153
+
1154
+ dfp=dfp.replace(0,'-')
1155
+ dfp=dfp.fillna('-')
1156
+
1157
+ #对主要项目排序
1158
+ lastitem=items[1]
1159
+ for i in items:
1160
+ if '%' in i:
1161
+ lastitem=i
1162
+ break
1163
+ else:
1164
+ continue
1165
+
1166
+ try:
1167
+ dfp.sort_values(by=lastitem,ascending=False,inplace=True)
1168
+ except:
1169
+ #因混有字符串和数值而排序失败,全转换为字符串再度排序
1170
+ dfp[lastitem]=dfp[lastitem].apply(lambda x: str(x))
1171
+ dfp.sort_values(by=lastitem,ascending=False,inplace=True)
1172
+
1173
+ dfp.reset_index(drop=True,inplace=True)
1174
+ dfp.index=dfp.index+1
1175
+
1176
+ #无序号打印
1177
+ if title_txt=='':
1178
+ title_txt="=== 重要指标的同行业对比 ==="
1179
+ ticker=tickers[0]
1180
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
1181
+ title_txt=tname+"财报分析:重要指标的同行业对比\n(截至"+fsdate+")"
1182
+ import datetime; todaydt=datetime.date.today()
1183
+ if yiyuan_foot:
1184
+ #footnote="*单位:亿元,数据来源:新浪财经,"+str(today)
1185
+ #footnote="*单位:亿元,本期报表日期:"+fsdate+',数据来源:新浪财经'
1186
+ footnote="单位:亿元,数据来源:新浪财经,"+str(todaydt)
1187
+ else:
1188
+ #footnote="*数据来源:新浪财经,"+str(today)
1189
+ #footnote="*本期报表日期:"+fsdate+',数据来源:新浪财经'
1190
+ footnote='数据来源:新浪财经,'+str(todaydt)
1191
+
1192
+ if notes=='':
1193
+ foottext=footnote
1194
+ else:
1195
+ foottext=notes+'\n'+footnote
1196
+
1197
+ #确定表格字体大小
1198
+ titile_font_size=font_size
1199
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
1200
+
1201
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
1202
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
1203
+ first_col_align='left', \
1204
+ facecolor=facecolor,decimals=2, \
1205
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
1206
+ data_font_size=data_font_size)
1207
+ return dfp
1208
+
1209
+ #==============================================================================
1210
+ if __name__=='__main__':
1211
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1212
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
1213
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
1214
+
1215
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1216
+ fsdate='2021-12-31'
1217
+ items=['资产总计','资产负债率%','流动比率%','速动比率%']
1218
+ dfp=fs_item_analysis_8(df,tickers,fsdate,items)
1219
+
1220
+ def fs_item_analysis_8(df,tickers,fsdate,items,title_txt='',notes='', \
1221
+ facecolor='papayawhip',font_size='16px'):
1222
+ """
1223
+ 功能:比较给定财报日期fsdate的项目和指标,与同业相比
1224
+ 区别:项目不带‘(亿元)’字样,避免行过长
1225
+ """
1226
+
1227
+ #循环获取科目
1228
+ col_list=['上市公司']+items
1229
+ dfp=pd.DataFrame(columns=col_list)
1230
+ yiyuan=100000000
1231
+ yiyuan_foot=False
1232
+
1233
+ for t in tickers:
1234
+ tname=ticker_name(t,'stock').replace("(A股)",'')
1235
+ row_list=[tname]
1236
+ for i in items:
1237
+ i_value,_,_=select_item(df,t,fsdate,i)
1238
+ if not('%' in i) and not('(元)' in i):
1239
+ row_list=row_list+[round(i_value/yiyuan,4)]
1240
+ yiyuan_foot=True
1241
+ else:
1242
+ row_list=row_list+[i_value]
1243
+ dfp.loc[len(dfp)] = row_list
1244
+
1245
+ #对主要项目排序
1246
+ lastitem=items[1]
1247
+ for i in items:
1248
+ if '%' in i:
1249
+ lastitem=i
1250
+ break
1251
+ else:
1252
+ continue
1253
+
1254
+ try:
1255
+ dfp.sort_values(by=lastitem,ascending=False,inplace=True)
1256
+ except:
1257
+ #因混有字符串和数值而排序失败,全转换为字符串再度排序
1258
+ dfp[lastitem]=dfp[lastitem].apply(lambda x: str(x))
1259
+ dfp.sort_values(by=lastitem,ascending=False,inplace=True)
1260
+
1261
+ dfp.reset_index(drop=True,inplace=True)
1262
+ dfp.index=dfp.index+1
1263
+
1264
+ dfp=dfp.replace(0,'-')
1265
+ dfp=dfp.fillna('-')
1266
+
1267
+ #无序号打印
1268
+ if title_txt=='':
1269
+ ticker=tickers[0]
1270
+ tname=ticker_name(ticker,'stock').replace("(A股)",'')
1271
+ title_txt=tname+"财报分析:重要指标的同行业对比\n(截至"+fsdate+")"
1272
+
1273
+ import datetime; todaydt=datetime.date.today()
1274
+ if yiyuan_foot:
1275
+ #footnote="*单位:亿元,数据来源:新浪财经,"+str(today)
1276
+ #footnote="*单位:亿元,本期报表日期:"+fsdate+',数据来源:新浪财经'
1277
+ footnote="单位:亿元,"+'数据来源:新浪财经,'+str(todaydt)
1278
+ else:
1279
+ #footnote="*数据来源:新浪财经,"+str(today)
1280
+ #footnote="*本期报表日期:"+fsdate+',数据来源:新浪财经'
1281
+ footnote='数据来源:新浪财经,'+str(todaydt)
1282
+
1283
+ if notes=='':
1284
+ foottext=footnote
1285
+ else:
1286
+ foottext=notes+'\n'+footnote
1287
+
1288
+ #确定表格字体大小
1289
+ titile_font_size=font_size
1290
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-1)+'px'
1291
+
1292
+ #df_directprint(dfp,title_txt,foottext,facecolor=facecolor)
1293
+ df_display_CSS(df=dfp,titletxt=title_txt,footnote=foottext, \
1294
+ first_col_align='left', \
1295
+ facecolor=facecolor,decimals=2, \
1296
+ titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
1297
+ data_font_size=data_font_size)
1298
+ return dfp
1299
+
1300
+ #==============================================================================
1301
+ if __name__=='__main__':
1302
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1303
+ fsdates=['2022-12-31','2021-12-31','2020-12-31','2019-12-31']
1304
+ asset_liab_structure_china(tickers,fsdates)
1305
+
1306
+ def asset_liab_china(tickers,fsdates,facecolor='papayawhip',font_size='16px'):
1307
+ """
1308
+ 套壳函数asset_liab_structure_china
1309
+ """
1310
+ asset_liab_structure_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
1311
+
1312
+ return
1313
+
1314
+
1315
+ def asset_liab_structure_china(tickers,fsdates,facecolor='papayawhip',font_size='16px'):
1316
+ """
1317
+ 功能:分析上市公司的资产负债基本结构,并与同业公司对比。
1318
+ 注意1:分析近三期情况,fsdates要给出四个报表日期,以便获得期初数。
1319
+ 注意2:可以分析连续的年报或季报,但不能混个年报和季报。
1320
+ 注意3:tickers中的第一家公司为主要分析对象。
1321
+ 注意4:fsdates中的日期要降序排列,第一个日期建议为最近的财报日。
1322
+ """
1323
+ # 检查证券个数
1324
+ if isinstance(tickers,str):
1325
+ print(" #Warning(asset_liab_structure_china): expecting multiple tickers in a list for",tickers)
1326
+ return
1327
+
1328
+ # 检查财报日期个数
1329
+ if isinstance(fsdates,str):
1330
+
1331
+ fsdateslist=[fsdates]
1332
+ y4int=int(fsdates[0:4])
1333
+ mmddstr=fsdates[4:len(fsdates)]
1334
+ for y in range(1,4):
1335
+ y4next=y4int - y
1336
+ fsdateslist=fsdateslist+[str(y4next)+mmddstr]
1337
+ print(" #Notice(asset_liab_structure_china): extended to 4 dates for financial statements")
1338
+ fsdates=fsdateslist
1339
+
1340
+ # 检查日期个数是否为4个,最后一个作为上期对比。最终列示前3项的结果
1341
+ if len(fsdates) <= 3:
1342
+ print(" #Warning(asset_liab_structure_china): expecting 4 consecutive dates for financial statements")
1343
+ return
1344
+
1345
+ comparator=tickers[0]
1346
+ comparee=tickers[1:]
1347
+ print(" Conducting asset-liability analysis ...")
1348
+ print(" Focus on:",ticker_name(comparator,'stock'))
1349
+ #print(" Comparee :",ticker_name(comparee))
1350
+ print(" Peers:",end='')
1351
+ if comparee != []:
1352
+ print_list(ticker_name(comparee,'stock'))
1353
+ else:
1354
+ print(" N/A")
1355
+
1356
+ #主要分析对象
1357
+ ticker=tickers[0]
1358
+
1359
+ #将日期规范化,以便排序正确
1360
+ fsdates1=[]
1361
+ for d in fsdates:
1362
+ result,fd=check_date2(d)
1363
+ if not result:
1364
+ print(" #Warning(asset_liab_structure_china): invalid date",d)
1365
+ return
1366
+ fsdates1=fsdates1+[fd]
1367
+ fsdates=fsdates1
1368
+
1369
+ #检查是否定期报告日期
1370
+ reportdates=['03-31','06-30','09-30','12-31']
1371
+ for d in fsdates:
1372
+ mm_dd=d[5:]
1373
+ if not (mm_dd in reportdates):
1374
+ print(" #Warning(asset_liab_structure_china): invalid date for financial statements in China",d)
1375
+ return
1376
+
1377
+ #最近的财报日
1378
+ fsdates=sorted(fsdates,reverse=True)
1379
+ fsdate=fsdates[0]
1380
+
1381
+ #获取所有比较公司tickers的所有财报fsdates
1382
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
1383
+ if df is None:
1384
+ print(" #Warning(asset_liab_structure_china): failed to retrieve any info for tickers in the periods")
1385
+ print(" Solution: check ticker spelling and try at least 10 minutes later")
1386
+ return
1387
+
1388
+ #title_head=ticker_name(comparator,'stock')+"资产负债分析:"
1389
+ title_head=ticker_name(comparator,'stock')+":"
1390
+
1391
+ ### 资产负债表的主要项目
1392
+ #资产变动趋势2
1393
+ title_txt=title_head+"主要资产项目,"+fsdate
1394
+ items2=["货币资金","应收账款","存货","长期股权投资","固定资产净额","资产总计"]
1395
+ """
1396
+ notes1="注1:货币资金包括库存现金、银行存款和其他货币资金三个部分"
1397
+ notes2="注2:其他货币资金包括银行汇(本)票存款、信用证保证金存款和信用卡存款等"
1398
+ notes3="注3:长期股权投资是指企业对其子公司、合营企业及联营企业的权益性投资"
1399
+ notes4="注4:固定资产净额 = 固定资产原值 - 累计折旧 - 资产减值准备"
1400
+ """
1401
+ notes1="注:\n货币资金包括库存现金、银行存款和其他货币资金三个部分"
1402
+ notes2="其他货币资金包括银行汇(本)票存款、信用证保证金存款和信用卡存款等"
1403
+ notes3="长期股权投资是指企业对其子公司、合营企业及联营企业的权益性投资"
1404
+ notes4="固定资产净额 = 固定资产原值 - 累计折旧 - 资产减值准备"
1405
+
1406
+ notes=notes1+'\n'+notes2+'\n'+notes3+'\n'+notes4
1407
+ dfp2=fs_item_analysis_1(df,ticker,fsdate,items2,title_txt,notes, \
1408
+ facecolor=facecolor,font_size=font_size)
1409
+
1410
+ #负债变动趋势
1411
+ title_txt=title_head+"主要负债项目,"+fsdate
1412
+ items3=["短期借款","长期借款","应付账款","预收款项","应交税费","应付职工薪酬","负债合计"]
1413
+ dfp3=fs_item_analysis_1(df,ticker,fsdate,items3,title_txt, \
1414
+ facecolor=facecolor,font_size=font_size)
1415
+
1416
+ #所有者权益变动趋势
1417
+ title_txt=title_head+"主要权益项目,"+fsdate
1418
+ items4=["实收资本(或股本)","资本公积","盈余公积","未分配利润","所有者权益合计"]
1419
+ """
1420
+ notes1="注1:实收资本(或股本,Paid-in Capital)指企业实际收到的投资人投入的资本"
1421
+ notes2="注2:资本公积是由股东投入的因故不能计入实收资本(或股本)中的那部分投入资金"
1422
+ notes3=" 资本公积包括资本(股本)溢价、其他资本公积、资产评估增值、资本折算差额"
1423
+ notes4=" 资本(股本)溢价是公司发行权益证券时价格超出票面价值的部分"
1424
+ notes5=" 其他资本公积包括金融资产公允价值变动、被投资单位净利润以外的变动等"
1425
+ notes6=" 资产评估增值是重估企业资产时,重估价高于资产的账面净值的部分"
1426
+ notes7=" 资本折算差额是外币资本因汇率变动产生的差额"
1427
+ notes8="注3:盈余公积是企业按照要求从税后利润中提取的、属于留存收益范畴的资金"
1428
+ notes9=" 企业从历年利润中提取的留存于企业的内部积累,包括盈余公积和未分配利润"
1429
+ notes10=" 公司制企业的盈余公积包括法定盈余公积和任意盈余公积"
1430
+ notes11=" 法定盈余公积是指企业按照规定比例从净利润中必须提取的盈余公积"
1431
+ notes12=" 任意盈余公积是指企业内部可自主决定比例提取的盈余公积"
1432
+ notes13=" 企业提取的盈余公积可用于弥补亏损、转增资本、发放现金股利或利润等"
1433
+ notes14="注4:未分配利润是净利润经弥补亏损、提取盈余公积和向投资者分配利润后的资金"
1434
+ """
1435
+ notes1="注:\n实收资本(或股本,Paid-in Capital)指企业实际收到的投资人投入的资本"
1436
+ notes2="资本公积是由股东投入的因故不能计入实收资本(或股本)中的那部分投入资金"
1437
+ notes3="资本公积包括资本(股本)溢价、其他资本公积、资产评估增值、资本折算差额"
1438
+ notes4="资本(股本)溢价是公司发行权益证券时价格超出票面价值的部分"
1439
+ notes5="其他资本公积包括金融资产公允价值变动、被投资单位净利润以外的变动等"
1440
+ notes6="资产评估增值是重估企业资产时,重估价高于资产的账面净值的部分"
1441
+ notes7="资本折算差额是外币资本因汇率变动产生的差额"
1442
+ notes8="盈余公积是企业按照要求从税后利润中提取的、属于留存收益范畴的资金"
1443
+ notes9="企业从历年利润中提取的留存于企业的内部积累,包括盈余公积和未分配利润"
1444
+ notes10="公司制企业的盈余公积包括法定盈余公积和任意盈余公积"
1445
+ notes11="法定盈余公积是指企业按照规定比例从净利润中必须提取的盈余公积"
1446
+ notes12="任意盈余公积是指企业内部可自主决定比例提取的盈余公积"
1447
+ notes13="企业提取的盈余公积可用于弥补亏损、转增资本、发放现金股利或利润等"
1448
+ notes14="未分配利润是净利润经弥补亏损、提取盈余公积和向投资者分配利润后的资金"
1449
+
1450
+ notesA=notes1+'\n'+notes2+'\n'+notes3+'\n'+notes4+'\n'+notes5+'\n'+notes6+'\n'+notes7
1451
+ notesB=notes8+'\n'+notes9+'\n'+notes10+'\n'+notes11+'\n'+notes12+'\n'+notes13+'\n'+notes14
1452
+
1453
+ notes=notesA+'\n'+notesB
1454
+ dfp4=fs_item_analysis_1(df,ticker,fsdate,items4,title_txt,notes, \
1455
+ facecolor=facecolor,font_size=font_size)
1456
+
1457
+ ### 货币资金与应收项目
1458
+ #资产变动趋势1:"货币资金","应收票据","应收账款"
1459
+ title_txt=title_head+"货币资金与应收项目,"+fsdate
1460
+ items1=["货币资金","应收票据","应收账款"]
1461
+ dfp1=fs_item_analysis_1(df,ticker,fsdate,items1,title_txt, \
1462
+ facecolor=facecolor,font_size=font_size)
1463
+
1464
+ #应收账款占比变动分析
1465
+ fsdates1=fsdates[:3]
1466
+ items5=["应收账款","资产总计"]
1467
+ title_txt=title_head+"应收账款占比变动情况"
1468
+ dfp5=fs_item_analysis_2(df,ticker,fsdates1,items5,title_txt, \
1469
+ facecolor=facecolor,font_size=font_size)
1470
+
1471
+ #应收与营业收入增幅对比
1472
+ fsdates2=fsdates[:2]
1473
+ items6=['应收账款',"应收票据",'营业总收入']
1474
+ title_txt=title_head+"应收项目与营业收入增幅对比"
1475
+ dfp6=fs_item_analysis_6(df,ticker,fsdates2,items6,title_txt, \
1476
+ facecolor=facecolor,font_size=font_size)
1477
+
1478
+ #应收账款占比同行对比
1479
+ items7=['应收账款','资产总计','应收账款占比%']
1480
+ #title_txt=title_head+"应收账款占比同行对比"
1481
+ title_txt="应收账款占比同行对比:"+fsdate
1482
+ dfp7=fs_item_analysis_7(df,tickers,fsdate,items7,title_txt, \
1483
+ facecolor=facecolor,font_size=font_size)
1484
+
1485
+ ### 存货
1486
+ #存货占比变动分析
1487
+ items8=["存货","资产总计"]
1488
+ title_txt=title_head+"存货占比变动情况"
1489
+ dfp8=fs_item_analysis_2(df,ticker,fsdates1,items8,title_txt, \
1490
+ facecolor=facecolor,font_size=font_size)
1491
+ """
1492
+ items9=["存货","营业总收入"]
1493
+ dfp9=fs_item_analysis_6(df,ticker,fsdates2,items9)
1494
+ """
1495
+ #存货与营业收入增幅对比分析
1496
+ items10=['存货','流动资产合计',"速动资产合计","资产总计"]
1497
+ title_txt=title_head+"存货与资产项目增幅对比"
1498
+ dfp10=fs_item_analysis_6(df,ticker,fsdates2,items10,title_txt, \
1499
+ facecolor=facecolor,font_size=font_size)
1500
+
1501
+ #存货占比与行业对比
1502
+ items11=['存货','资产总计','存货占比%']
1503
+ #title_txt=title_head+"存货占比情况同行对比"
1504
+ title_txt="存货占比情况同行对比:"+fsdate
1505
+ dfp11=fs_item_analysis_7(df,tickers,fsdate,items11,title_txt, \
1506
+ facecolor=facecolor,font_size=font_size)
1507
+
1508
+ ### 偿债能力
1509
+ #流动比率变动分析
1510
+ title_txt=title_head+"流动比率变动情况"
1511
+ dfp12=fs_item_analysis_3(df,ticker,fsdates1,title_txt, \
1512
+ facecolor=facecolor,font_size=font_size)
1513
+
1514
+ #速动比率变动分析
1515
+ title_txt=title_head+"速动比率变动情况"
1516
+ dfp13=fs_item_analysis_4(df,ticker,fsdates1,title_txt, \
1517
+ facecolor=facecolor,font_size=font_size)
1518
+
1519
+ #资产负债率变动分析
1520
+ title_txt=title_head+"资产负债率变动情况"
1521
+ dfp14=fs_item_analysis_5(df,ticker,fsdates1,title_txt, \
1522
+ facecolor=facecolor,font_size=font_size)
1523
+
1524
+ #资产负债率同行比较
1525
+ #title_txt=title_head+"资产负债率同行比较"
1526
+ title_txt="资产负债率同行比较:"+fsdate
1527
+ items15=['资产总计','资产负债率%','流动比率%','速动比率%']
1528
+ dfp15=fs_item_analysis_8(df,tickers,fsdate,items15,title_txt, \
1529
+ facecolor=facecolor,font_size=font_size)
1530
+
1531
+ return
1532
+
1533
+ #==============================================================================
1534
+ if __name__=='__main__':
1535
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1536
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
1537
+ income_cost_structure_china(tickers,fsdates)
1538
+
1539
+ def income_cost_china(tickers,fsdates,facecolor='papayawhip',font_size='16px'):
1540
+ """
1541
+ 套壳函数income_cost_structure_china
1542
+ """
1543
+ income_cost_structure_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
1544
+
1545
+ return
1546
+
1547
+ def income_cost_structure_china(tickers,fsdates,facecolor='papayawhip',font_size='16px'):
1548
+ """
1549
+ 功能:分析上市公司的收入成本基本结构,并与同业公司对比。
1550
+ 注意1:分析近三期情况,fsdates要给出四个报表日期,以便获得期初数。
1551
+ 注意2:可以分析连续的年报或季报,但不能混个年报和季报。
1552
+ 注意3:tickers中的第一家公司为主要分析对象。
1553
+ 注意4:fsdates中的日期要降序排列,第一个日期建议为最近的财报日。
1554
+ """
1555
+ # 检查证券个数
1556
+ if isinstance(tickers,str):
1557
+ print(" #Warning(income_cost_structure_china): expecting multiple tickers in a list for",tickers)
1558
+ return
1559
+
1560
+ # 检查财报日期个数
1561
+ if isinstance(fsdates,str):
1562
+ fsdateslist=[fsdates]
1563
+ y4int=int(fsdates[0:4])
1564
+ mmddstr=fsdates[4:len(fsdates)]
1565
+ for y in range(1,4):
1566
+ y4next=y4int - y
1567
+ fsdateslist=fsdateslist+[str(y4next)+mmddstr]
1568
+ print(" #Warning(income_cost_structure_china): extended to 4 dates for financial statements")
1569
+ fsdates=fsdateslist
1570
+
1571
+ # 检查日期个数是否为4个,最后一个作为上期对比。最终列示前3项的结果
1572
+ if len(fsdates) <= 3:
1573
+ print(" #Warning(income_cost_structure_china): expecting 4 consecutive dates for financial statements")
1574
+ return
1575
+
1576
+ #将日期规范化,以便排序正确
1577
+ fsdates1=[]
1578
+ for d in fsdates:
1579
+ result,fd=check_date2(d)
1580
+ if not result:
1581
+ print(" #Warning(income_cost_structure_china): invalid date",d)
1582
+ return
1583
+ fsdates1=fsdates1+[fd]
1584
+ fsdates=fsdates1
1585
+
1586
+ comparator=tickers[0]
1587
+ comparee=tickers[1:]
1588
+ print(" Conducting income-cost analysis ...")
1589
+ print(" Focus on:",ticker_name(comparator,'stock'))
1590
+ #print(" Comparee :",ticker_name(comparee))
1591
+ print(" Peers:",end='')
1592
+ if comparee != []:
1593
+ print_list(ticker_name(comparee,'stock'))
1594
+ else:
1595
+ print(" N/A")
1596
+
1597
+ #主要分析对象
1598
+ ticker=tickers[0]
1599
+ #最近的财报日
1600
+ fsdates=sorted(fsdates,reverse=True)
1601
+ fsdate=fsdates[0]
1602
+
1603
+ #获取所有比较公司tickers的所有财报fsdates
1604
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
1605
+ if df is None:
1606
+ print(" #Warning(income_cost_structure_china): failed to retrieve info for the tickers in the dates")
1607
+ #print(" Possible reasons: no access to data source or invalid tickers")
1608
+ return
1609
+
1610
+ title_head=ticker_name(comparator,'stock')+":"
1611
+
1612
+ #收入成本总体变动趋势
1613
+ title_txt=title_head+"主要利润表项目,"+fsdate
1614
+ items1=["营业总收入","营业总成本","营业成本","毛利润","营业利润","营业外收支","税前利润","所得税费用","净利润","归母净利润"]
1615
+ dfp1=fs_item_analysis_1(df,ticker,fsdate,items1,title_txt, \
1616
+ facecolor=facecolor,font_size=font_size)
1617
+
1618
+ #成本变动趋势
1619
+ title_txt=title_head+"主要成本费用项目,"+fsdate
1620
+ print('')
1621
+ """
1622
+ items2=["营业总成本","营业成本","营业税金及附加","销售费用","管理费用","研发费用",
1623
+ "应付利息","公允价值变动损失","非流动资产处置损失",
1624
+ "资产减值损失","营业外支出"]
1625
+ """
1626
+ items2=["营业总成本","营业成本","营业税金及附加","销售费用","管理费用","研发费用",
1627
+ "应付利息","非流动资产处置损失",
1628
+ "资产减值损失","营业外支出"]
1629
+ dfp2=fs_item_analysis_1(df,ticker,'2021-12-31',items2,title_txt, \
1630
+ facecolor=facecolor,font_size=font_size)
1631
+
1632
+ #占比变动分析:近三年
1633
+ title_txt=title_head+"营业总成本占营业总收入比例情况"
1634
+ fsdates1=fsdates[:3]
1635
+ items3=["营业总成本","营业总收入"]
1636
+ """
1637
+ notes1="注1:营业总成本包括营业成本、营业税金及附加、三大费用和资产减值损失"
1638
+ notes2="注2:营业收入=主营业务收入和其他非主营业务收入"
1639
+ notes3="注3:营业总收入=营业收入+非营业收入(投资收益、营业外收入等)"
1640
+ """
1641
+ notes1="注:\n营业总成本包括营业成本、营业税金及附加、三大费用和资产减值损失"
1642
+ notes2="营业收入=主营业务收入和其他非主营业务收入"
1643
+ notes3="营业总收入=营业收入+非营业收入(投资收益、营业外收入等)"
1644
+
1645
+ notes=notes1+'\n'+notes2+'\n'+notes3
1646
+ dfp3=fs_item_analysis_2(df,ticker,fsdates1,items3,title_txt,notes, \
1647
+ facecolor=facecolor,font_size=font_size)
1648
+ #====================================================================
1649
+ title_txt=title_head+"营业成本占营业总成本比例情况"
1650
+ items4=["营业成本","营业总成本"]
1651
+ """
1652
+ notes1="注1:营业成本是经营活动中发生的可归属于产品/劳务成本等的费用"
1653
+ notes2="注2:营业总成本包括营业成本、营业税金及附加、三大费用和资产减值损失"
1654
+ """
1655
+ notes1="注:\n营业成本是经营活动中发生的可归属于产品/劳务成本等的费用"
1656
+ notes2="营业总成本包括营业成本、营业税金及附加、三大费用和资产减值损失"
1657
+
1658
+ notes=notes1+'\n'+notes2
1659
+ dfp4=fs_item_analysis_2(df,ticker,fsdates1,items4,title_txt,notes, \
1660
+ facecolor=facecolor,font_size=font_size)
1661
+
1662
+ title_txt=title_head+"营业成本占营业总收入比例情况"
1663
+ items5=["营业成本","营业总收入"]
1664
+ dfp5=fs_item_analysis_2(df,ticker,fsdates1,items5,title_txt, \
1665
+ facecolor=facecolor,font_size=font_size)
1666
+
1667
+ title_txt=title_head+"营业成本增幅分析"
1668
+ fsdates2=fsdates[:2]
1669
+ items12=['营业成本','营业总成本','营业总收入']
1670
+ dfp12=fs_item_analysis_6(df,ticker,fsdates2,items12,title_txt, \
1671
+ facecolor=facecolor,font_size=font_size)
1672
+
1673
+ #====================================================================
1674
+ title_txt=title_head+"销售费用占营业总收入比例情况"
1675
+ items6=["销售费用","营业总收入"]
1676
+
1677
+ notes="注:销售费用是企业销售过程中发生的各种费用"
1678
+ dfp6=fs_item_analysis_2(df,ticker,fsdates1,items6,title_txt,notes, \
1679
+ facecolor=facecolor,font_size=font_size)
1680
+ #====================================================================
1681
+ title_txt=title_head+"管理费用占营业总收入比例情况"
1682
+ items7=["管理费用","营业总收入"]
1683
+
1684
+ notes="注:管理费用是行政管理部门为组织生产/经营活动发生的各种费用"
1685
+ dfp7=fs_item_analysis_2(df,ticker,fsdates1,items7,title_txt,notes, \
1686
+ facecolor=facecolor,font_size=font_size)
1687
+
1688
+ #title_txt=title_head+"三项费用率同行对比"
1689
+ title_txt="三项费用率同行对比:"+fsdate
1690
+ items14=['营业总收入','销售费用率%','管理费用率%','研发费用率%']
1691
+ """
1692
+ notes1="注1:销售费用率 = 销售费用 / 营业总收入"
1693
+ notes2="注2:管理费用率 = 管理费用 / 营业总收入"
1694
+ notes3="注3:研发费用率 = 研发费用 / 营业总收入"
1695
+ """
1696
+ notes1="注:\n销售费用率 = 销售费用 / 营业总收入"
1697
+ notes2="管理费用率 = 管理费用 / 营业总收入"
1698
+ notes3="研发费用率 = 研发费用 / 营业总收入"
1699
+
1700
+ notes=notes1+'\n'+notes2+'\n'+notes3
1701
+
1702
+ dfp12=fs_item_analysis_8(df,tickers,fsdate,items14,title_txt,notes, \
1703
+ facecolor=facecolor,font_size=font_size)
1704
+ #====================================================================
1705
+ title_txt=title_head+"毛利润占营业总收入比例情况"
1706
+ items8=["毛利润","营业总收入"]
1707
+ dfp8=fs_item_analysis_2(df,ticker,fsdates1,items8,title_txt, \
1708
+ facecolor=facecolor,font_size=font_size)
1709
+ #====================================================================
1710
+ title_txt=title_head+"营业利润占营业总收入比例情况"
1711
+ items9=["营业利润","营业总收入"]
1712
+ dfp8=fs_item_analysis_2(df,ticker,fsdates1,items9,title_txt, \
1713
+ facecolor=facecolor,font_size=font_size)
1714
+ #====================================================================
1715
+ title_txt=title_head+"税前利润占营业总收入比例情况"
1716
+ items10=["税前利润","营业总收入"]
1717
+ dfp9=fs_item_analysis_2(df,ticker,fsdates1,items10,title_txt, \
1718
+ facecolor=facecolor,font_size=font_size)
1719
+ #====================================================================
1720
+ title_txt=title_head+"净利润占营业总收入比例情况"
1721
+ items11=["净利润","营业总收入"]
1722
+ dfp9=fs_item_analysis_2(df,ticker,fsdates1,items11,title_txt, \
1723
+ facecolor=facecolor,font_size=font_size)
1724
+
1725
+ #增幅分析:近两年
1726
+ title_txt=title_head+"四种利润对比"
1727
+ items13=['毛利润','营业利润','税前利润','净利润']
1728
+ dfp11=fs_item_analysis_6(df,ticker,fsdates2,items13,title_txt, \
1729
+ facecolor=facecolor,font_size=font_size)
1730
+
1731
+ #同行比较
1732
+ #title_txt=title_head+"利润率同行对比"
1733
+ title_txt="利润率同行对比:"+fsdate
1734
+ #items15=['营业利润','营业利润率%','税前利润率%','实际所得税率%','净利润','净利润率%']
1735
+ #items15=['毛利润率%','营业利润率%','税前利润率%','净利润率%']
1736
+ items15=['净利润率%','税前利润率%','营业利润率%','毛利润率%']
1737
+ dfp12=fs_item_analysis_8(df,tickers,fsdate,items15,title_txt, \
1738
+ facecolor=facecolor,font_size=font_size)
1739
+
1740
+ return
1741
+
1742
+ #==============================================================================
1743
+ if __name__=='__main__':
1744
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1745
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
1746
+ cash_flow_structure_china(tickers,fsdates)
1747
+
1748
+ def cash_flow_china(tickers,fsdates,facecolor='papayawhip',font_size='16px'):
1749
+ """
1750
+ 套壳函数cash_flow_structure_china
1751
+ """
1752
+ cash_flow_structure_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
1753
+
1754
+ return
1755
+
1756
+
1757
+ def cash_flow_structure_china(tickers,fsdates,facecolor='papayawhip',font_size='16px'):
1758
+ """
1759
+ 功能:分析上市公司的现金流量基本结构,并与同业公司对比。
1760
+ 注意1:分析近三期情况,fsdates要给出四个报表日期,以便获得期初数。
1761
+ 注意2:可以分析连续的年报或季报,但不能混个年报和季报。
1762
+ 注意3:tickers中的第一家公司为主要分析对象。
1763
+ 注意4:fsdates中的日期要降序排列,第一个日期建议为最近的财报日。
1764
+ """
1765
+ if isinstance(tickers,str):
1766
+ print(" #Warning(cash_flow_structure_china): expecting multiple tickers in a list for",tickers)
1767
+ return
1768
+
1769
+ # 检查财报日期个数
1770
+ if isinstance(fsdates,str):
1771
+ fsdateslist=[fsdates]
1772
+ y4int=int(fsdates[0:4])
1773
+ mmddstr=fsdates[4:len(fsdates)]
1774
+ for y in range(1,4):
1775
+ y4next=y4int - y
1776
+ fsdateslist=fsdateslist+[str(y4next)+mmddstr]
1777
+ print(" #Warning(cash_flow_structure_china): extended to 4 dates for financial statements")
1778
+ fsdates=fsdateslist
1779
+
1780
+ # 检查日期个数是否为4个,最后一个作为上期对比。最终列示前3项的结果
1781
+ if len(fsdates) <= 3:
1782
+ print(" #Warning(cash_flow_structure_china): expecting 4 consecutive dates for financial statements")
1783
+ return
1784
+
1785
+ #将日期规范化,以便排序正确
1786
+ fsdates1=[]
1787
+ for d in fsdates:
1788
+ result,fd=check_date2(d)
1789
+ if not result:
1790
+ print(" #Warning(cash_flow_structure_china): invalid date",d)
1791
+ return
1792
+ fsdates1=fsdates1+[fd]
1793
+ fsdates=fsdates1
1794
+
1795
+ comparator=tickers[0]
1796
+ comparee=tickers[1:]
1797
+ print(" Conducting cash flow analysis ...")
1798
+ print(" Focus on:",ticker_name(comparator,'stock'))
1799
+ print(" Peers:",end='')
1800
+ if comparee != []:
1801
+ print_list(ticker_name(comparee,'stock'))
1802
+ else:
1803
+ print(" N/A")
1804
+
1805
+ #主要分析对象
1806
+ ticker=tickers[0]
1807
+ #最近的财报日
1808
+ fsdates=sorted(fsdates,reverse=True)
1809
+ fsdate=fsdates[0]
1810
+
1811
+ #获取所有比较公司tickers的所有财报fsdates
1812
+ df=get_fin_stmt_ak_multi(tickers,fsdates)
1813
+ if df is None:
1814
+ print(" #Warning(cash_flow_structure_china): failed to retrieve info for the tickers in the dates")
1815
+ #print(" Possible reasons: no access to data source or invalid tickers")
1816
+ return
1817
+
1818
+ title_head=ticker_name(comparator,'stock')+":"
1819
+
1820
+ #总体变动趋势
1821
+ title_txt=title_head+"主要现金流项目,"+fsdate
1822
+ items1=["经营活动现金流净额","经营活动现金流入","经营活动现金流出",
1823
+ "投资活动现金流净额","投资活动现金流入","投资活动现金流出",
1824
+ "筹资活动现金流净额","筹资活动现金流入","筹资活动现金流出",
1825
+ "汇率对现金流的影响","现金流量净增加额"]
1826
+ dfp1=fs_item_analysis_1(df,ticker,fsdate,items1,title_txt, \
1827
+ facecolor=facecolor,font_size=font_size)
1828
+
1829
+ #占比变动分析:近三年
1830
+ title_txt=title_head+"经营活动现金流入占比情况"
1831
+ fsdates1=fsdates[:3]
1832
+ items3=["经营活动现金流入","营业总收入"]
1833
+ dfp3=fs_item_analysis_2(df,ticker,fsdates1,items3,title_txt, \
1834
+ facecolor=facecolor,font_size=font_size)
1835
+
1836
+ title_txt=title_head+"经营活动现金流净额占比情况"
1837
+ items4=["经营活动现金流净额","营业利润"]
1838
+ dfp3=fs_item_analysis_2(df,ticker,fsdates1,items4,title_txt, \
1839
+ facecolor=facecolor,font_size=font_size)
1840
+
1841
+ #增幅分析:近两年
1842
+ title_txt=title_head+"经营活动现金流增幅情况"
1843
+ fsdates2=fsdates[:2]
1844
+ items12=['经营活动现金流入','经营活动现金流出','经营活动现金流净额']
1845
+ dfp12=fs_item_analysis_6(df,ticker,fsdates2,items12,title_txt, \
1846
+ facecolor=facecolor,font_size=font_size)
1847
+
1848
+ #同行比较
1849
+ title_txt=title_head+"现金收入能力同行比较,"+fsdate
1850
+ items16=['销售现金比率%','现金购销比率%','营业现金回笼率%']
1851
+ """
1852
+ notes1="注1:销售现金比率 = 经营活动现金流入 / 营业总收入"
1853
+ notes2="注2:现金购销比率 = 经营活动现金流出 / 经营活动现金流入"
1854
+ notes3="注3:营业现金回笼率 = 经营活动现金流入 / 营业总收入"
1855
+ """
1856
+ notes1="注:\n销售现金比率 = 经营活动现金流入 / 营业总收入"
1857
+ notes2="现金购销比率 = 经营活动现金流出 / 经营活动现金流入"
1858
+ notes3="营业现金回笼率 = 经营活动现金流入 / 营业总收入"
1859
+
1860
+ notes=notes1+'\n'+notes2+'\n'+notes3
1861
+ dfp12=fs_item_analysis_8(df,tickers,fsdate,items16,title_txt,notes, \
1862
+ facecolor=facecolor,font_size=font_size)
1863
+
1864
+ title_txt=title_head+"现金偿债能力同行比较,"+fsdate
1865
+ items14=['短期现金偿债能力%','长期现金偿债能力%']
1866
+ """
1867
+ notes1="注1:短期现金偿债能力 = 经营活动现金流净额 / 流动负债合计"
1868
+ notes2="注2:长期现金偿债能力 = 经营活动现金流净额 / 负债合计"
1869
+ """
1870
+ notes1="注:\n短期现金偿债能力 = 经营活动现金流净额 / 流动负债合计"
1871
+ notes2="长期现金偿债能力 = 经营活动现金流净额 / 负债合计"
1872
+
1873
+ notes=notes1+'\n'+notes2
1874
+ dfp12=fs_item_analysis_8(df,tickers,fsdate,items14,title_txt,notes, \
1875
+ facecolor=facecolor,font_size=font_size)
1876
+
1877
+ title_txt=title_head+"现金支付能力同行比较,"+fsdate
1878
+ items15=['现金支付股利能力(元)','现金综合支付能力%','支付给职工的现金比率%']
1879
+ """
1880
+ notes1="注1:现金支付股利能力 = 经营活动现金流净额 / 流通股股数"
1881
+ notes2="注2:现金综合支付能力 = 经营活动现金流净额 / 所有者权益合计"
1882
+ notes3="注3:支付给职工的现金比率 = 支付给(为)职工支付的现金 / 经营活动现金流入"
1883
+ """
1884
+ notes1="注:\n现金支付股利能力 = 经营活动现金流净额 / 流通股股数"
1885
+ notes2="现金综合支付能力 = 经营活动现金流净额 / 所有者权益合计"
1886
+ notes3="支付给职工的现金比率 = 支付给(为)职工支付的现金 / 经营活动现金流入"
1887
+
1888
+ notes=notes1+'\n'+notes2+'\n'+notes3
1889
+ dfp12=fs_item_analysis_8(df,tickers,fsdate,items15,title_txt,notes, \
1890
+ facecolor=facecolor,font_size=font_size)
1891
+
1892
+ title_txt=title_head+"财务指标含金量同行比较,"+fsdate
1893
+ items17=['盈利现金比率%','现金流入流出比率%','资产现金回收率%']
1894
+ """
1895
+ notes1="注1:盈利现金比率 = 经营活动现金流净额 / 净利润"
1896
+ notes2="注2:现金流入流出比率 = 经营活动现金流入 / 经营活动现金流出"
1897
+ notes3="注3:资产现金回收率 = 经营活动现金流净额 / 资产总计"
1898
+ """
1899
+ notes1="注:\n盈利现金比率 = 经营活动现金流净额 / 净利润"
1900
+ notes2="现金流入流出比率 = 经营活动现金流入 / 经营活动现金流出"
1901
+ notes3="资产现金回收率 = 经营活动现金流净额 / 资产总计"
1902
+
1903
+ notes=notes1+'\n'+notes2+'\n'+notes3
1904
+ dfp12=fs_item_analysis_8(df,tickers,fsdate,items17,title_txt,notes, \
1905
+ facecolor=facecolor,font_size=font_size)
1906
+
1907
+ return
1908
+
1909
+ #==============================================================================
1910
+ if __name__=='__main__':
1911
+ date1='2022-12-31'
1912
+ num=4
1913
+ gen_yoy_dates(date1,4)
1914
+
1915
+ def gen_yoy_dates(date1,num=4):
1916
+ """
1917
+ 功能:生成date1的num个同比的日期
1918
+ """
1919
+ if not isinstance(date1,str):
1920
+ print(" #Error(gen_yoy_dates): invalid date",date1)
1921
+ return date1
1922
+
1923
+ y4=int(date1[:4])
1924
+ mmdd=date1[4:]
1925
+
1926
+ datelist=[]
1927
+ for i in range(0,num):
1928
+ date_tmp=str(y4-i)+mmdd
1929
+ datelist=datelist+[date_tmp]
1930
+
1931
+ return datelist
1932
+
1933
+
1934
+
1935
+ if __name__=='__main__':
1936
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1937
+ fsdates='2021-12-31'
1938
+ analysis_type='Balance Sheet'
1939
+ analysis_type='Income Statement'
1940
+ analysis_type='Cash Flow Statement'
1941
+
1942
+ fs_analysis_china(tickers,fsdates,analysis_type='balance sheet')
1943
+ fs_analysis_china(tickers,fsdates,analysis_type='income statement')
1944
+ fs_analysis_china(tickers,fsdates,analysis_type='cash flow statement')
1945
+
1946
+ tickers=["000002.SZ","600266.SS",'600383.SS','600048.SS']
1947
+ fsdates=['2021-12-31','2020-12-31','2019-12-31','2018-12-31']
1948
+ fs_analysis_china(tickers,fsdates,analysis_type='fs summary')
1949
+ fs_analysis_china(tickers,fsdates,analysis_type='financial indicator')
1950
+
1951
+ tickers='000001.SZ'
1952
+ fs_analysis_china(tickers,fsdates,analysis_type='profile')
1953
+ fs_analysis_china(tickers,fsdates,analysis_type='profile',category='shareholder')
1954
+ fs_analysis_china(tickers,fsdates,analysis_type='profile',category='dividend')
1955
+ fs_analysis_china(tickers,fsdates,analysis_type='profile',category='business')
1956
+ fs_analysis_china(tickers,fsdates,analysis_type='profile',category='business',business_period='annual')
1957
+ fs_analysis_china(tickers,fsdates,analysis_type='profile',category='valuation')
1958
+ fs_analysis_china(tickers,fsdates,analysis_type='profile',category='financial')
1959
+
1960
+ def fs_analysis_china(tickers,fsdates=[],analysis_type='balance sheet', \
1961
+ category='profile',business_period='recent', \
1962
+ sort='PM',printout=False,gview=False, \
1963
+ loc1='best',loc2='best', \
1964
+ facecolor='papayawhip',font_size='16px'):
1965
+ """
1966
+ ===========================================================================
1967
+ 功能:财务报表分析,仅适用于中国A股,注意不适用于港股和美股(含中概股)
1968
+
1969
+ 选项tickers:必选
1970
+ 单只股票:用于单只股票历史财报对比
1971
+ 股票列表:用于股票之间同期财报横向对比
1972
+
1973
+ 选项fsdates:必选
1974
+ 单个财报日期:适用于选项tickers为股票列表时
1975
+ 财报日期列表:适用于选项tickers为单只股票时,至少四个财报日期,便于对比
1976
+
1977
+ 选项analysis_type:
1978
+ 资产负债表分析(默认):balance sheet, asset liability
1979
+ 利润表分析:income statement, cost, expense, earning
1980
+ 现金流量表分析:cash flow, cashflow statement
1981
+ 财报概述:financial summary
1982
+ 财务指标:financial indicator
1983
+ 股票画像:stock profile, 下面还可分别选择不同的category项目
1984
+ 杜邦分析:dupont identify, dupont analysis
1985
+ 杜邦分解:dupont decompose,需要安装graphviz插件
1986
+
1987
+ 选项category:
1988
+ 基本信息(默认):profile
1989
+ 股东信息:shareholder
1990
+ 历史分红:dividend
1991
+ 主营业务:business,目前无法获取数据!
1992
+ 市场估值:valuation
1993
+ 财务概况:financial
1994
+
1995
+ 选项business_period:
1996
+ 最新(默认):recent,可能为最新可获得的季报或中报或年报
1997
+ 最新的季报:quarterly
1998
+ 最新的中报:semiannual
1999
+ 最新的年报:annual
2000
+
2001
+ 选项loc1/loc2:适用于需要绘图时指定图例的位置,仅在双图例重叠时手动调整
2002
+
2003
+ 选项facecolor:指定表格/绘图的背景颜色
2004
+ 烟白色(默认):whitesmoke
2005
+ 其他颜色:参见matplotlib颜色列表,例如淡雅小麦色papayawhip
2006
+
2007
+ 示例:
2008
+ 千方科技='002373.SZ'
2009
+ # 企业快照1:大股东
2010
+ sp1=fs_analysis_china(千方科技,analysis_type='profile',category='shareholder')
2011
+ # 企业快照2:主营业务
2012
+ sp2 = fs_analysis_china(千方科技, analysis_type='profile', category='business')
2013
+ # 企业快照3:股利分红
2014
+ sp3=fs_analysis_china(千方科技,analysis_type='profile',category='dividend')
2015
+ # 企业快照4:财务概况
2016
+ sp4 = fs_analysis_china(千方科技, analysis_type='profile', category='financial')
2017
+ # 同行业绩对比
2018
+ # 主要竞争对手:并非所有业务重叠
2019
+ peers=[ #定义主要竞争对手
2020
+ '002279.SZ',#久其软件
2021
+ '002368.SZ',#太极股份
2022
+ '600410.SS',#华胜天成
2023
+ '603927.SS',#中科软
2024
+ '002405.SZ',#四维图新
2025
+ ]
2026
+ players=[千方科技]+peers
2027
+ competitors = fs_analysis_china(players, fsdates='2023-12-31', analysis_type='summary')
2028
+ # 资产负债表分析
2029
+ fsdates=['2023-12-31','2022-12-31','2021-12-31','2020-12-31','2019-12-31']
2030
+ fs_analysis_china(千方科技,fsdates,analysis_type='balance sheet')
2031
+ # 利润表分析
2032
+ fs_analysis_china(千方科技,fsdates,analysis_type='income statement')
2033
+ # 现金流量表分析
2034
+ fs_analysis_china(千方科技,fsdates,analysis_type='cashflow statement')
2035
+ # 杜邦分析
2036
+ dd = fs_analysis_china(千方科技, fsdates='2023-12-31', analysis_type='dupont decompose')
2037
+ # 投资-风险性价比分析
2038
+ # 以一年期国债收益率作为无风险收益率
2039
+ RF=0.01657
2040
+ # 短期分析
2041
+ rar1=security_trend(players,indicator='sharpe',ret_type='Exp Ret%',start='MRM',RF=RF,loc1='lower left')
2042
+ rar2 = security_trend(players, indicator='alpha', ret_type='Exp Ret%', start='MRM', RF=RF, loc1='lower left')
2043
+ # 中长期分析
2044
+ rar3=security_trend(players,indicator='sharpe',ret_type='Exp Ret%',start='L3Y',RF=RF,loc1='lower left')
2045
+
2046
+ 备注:封装说明
2047
+ 套壳函数1:tickers为股票列表,fsdates为财报日期,可为单个日期或日期列表
2048
+ asset_liab_china, income_cost_china, cash_flow_china
2049
+
2050
+ 套壳函数2:tickers为股票列表,fsdates为财报日期,可为单个日期或日期列表
2051
+ compare_fin_summary_china
2052
+
2053
+ 套壳函数3:tickers为股票代码或股票列表,fsdates为财报日期列表
2054
+ compare_fin_indicator_china
2055
+
2056
+ 套壳函数4:tickers为股票代码,fsdates不需要,
2057
+ stock_profile_china
2058
+
2059
+ 套壳函数5/6:杜邦分析compare_dupont_china / 杜邦分解dupont_decompose
2060
+ """
2061
+
2062
+ # 统一转小写,便于判断
2063
+ analysis_type1=analysis_type.lower()
2064
+
2065
+ if ('balance' in analysis_type1) or ('sheet' in analysis_type1) \
2066
+ or ('asset' in analysis_type1) or ('liability' in analysis_type1):
2067
+ # 检查股票列表
2068
+ if not isinstance(tickers,list):
2069
+ tickers=[tickers]
2070
+
2071
+ if not isinstance(fsdates,list):
2072
+ fsdates=gen_yoy_dates(fsdates,num=4)
2073
+
2074
+ # 分析资产负债表
2075
+ asset_liab_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
2076
+ return
2077
+
2078
+ elif ('income' in analysis_type1) or ('cost' in analysis_type1) \
2079
+ or ('expense' in analysis_type1) or ('earning' in analysis_type1):
2080
+ # 检查股票列表
2081
+ if not isinstance(tickers,list):
2082
+ tickers=[tickers]
2083
+
2084
+ if not isinstance(fsdates,list):
2085
+ fsdates=gen_yoy_dates(fsdates,num=4)
2086
+
2087
+ # 分析利润表
2088
+ income_cost_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
2089
+ return
2090
+
2091
+ elif ('cash' in analysis_type1) or ('flow' in analysis_type1):
2092
+ # 检查股票列表
2093
+ if not isinstance(tickers,list):
2094
+ tickers=[tickers]
2095
+
2096
+ if not isinstance(fsdates,list):
2097
+ fsdates=gen_yoy_dates(fsdates,num=4)
2098
+
2099
+ # 分析现金流量表
2100
+ cash_flow_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
2101
+ return
2102
+
2103
+ elif ('summary' in analysis_type1):
2104
+ # 股票可为单只股票(单只股票深度分析)或股票列表(多只股票对比)
2105
+ # 检查股票
2106
+ if isinstance(tickers,str):
2107
+ if not isinstance(fsdates,list):
2108
+ fsdates=gen_yoy_dates(fsdates,num=4)
2109
+ """
2110
+ print(" #Warning(fs_analysis_china): must be date list for",fsdates)
2111
+ return
2112
+ """
2113
+
2114
+ # 检查股票列表
2115
+ if isinstance(tickers,list):
2116
+ if not isinstance(fsdates,str):
2117
+ fsdates=fsdates[0]
2118
+ """
2119
+ print(" #Warning(fs_analysis_china): must be a date for",fsdates)
2120
+ return
2121
+ """
2122
+
2123
+ # 分析财报摘要
2124
+ from siat.financials_china import compare_fin_summary_china
2125
+ df_summary=compare_fin_summary_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
2126
+ return
2127
+
2128
+ elif ('indicator' in analysis_type1):
2129
+ # 股票可为单只股票(单只股票深度分析)或股票列表(多只股票对比)
2130
+ # 检查股票
2131
+ if isinstance(tickers,str):
2132
+ if not isinstance(fsdates,list):
2133
+ fsdates=gen_yoy_dates(fsdates,num=4)
2134
+ """
2135
+ print(" #Warning(fs_analysis_china): must be date list for",fsdates)
2136
+ return
2137
+ """
2138
+
2139
+ # 检查股票列表
2140
+ if isinstance(tickers,list):
2141
+ if not isinstance(fsdates,str):
2142
+ fsdates=fsdates[0]
2143
+ """
2144
+ print(" #Warning(fs_analysis_china): must be a date for",fsdates)
2145
+ return
2146
+ """
2147
+
2148
+ # 分析主要财务指标和比率
2149
+ from siat.financials_china import compare_fin_indicator_china
2150
+ df_ind=compare_fin_indicator_china(tickers,fsdates,facecolor=facecolor,font_size=font_size)
2151
+ return
2152
+
2153
+ elif ('profile' in analysis_type1):
2154
+ # 股票需为单只股票
2155
+ if not isinstance(tickers,str):
2156
+ print(" #Warning(fs_analysis_china): must be one ticker for",tickers)
2157
+ return
2158
+
2159
+ # 分析单只股票的全方位概况
2160
+ stock_profile_china(tickers,category,business_period,loc1=loc1,loc2=loc2, \
2161
+ facecolor=facecolor,font_size=font_size)
2162
+ return
2163
+
2164
+ elif ('dupont' in analysis_type1) and (('identity' in analysis_type1) or ('analysis' in analysis_type1)):
2165
+ # 股票需为股票列表
2166
+ if not isinstance(tickers,list):
2167
+ print(" #Warning(fs_analysis_china): must be ticker list for",tickers)
2168
+ return
2169
+ # 日期需为一个日期
2170
+ if not isinstance(fsdates,str):
2171
+ fsdates=fsdates[0]
2172
+ """
2173
+ print(" #Warning(fs_analysis_china): must one date for",fsdates)
2174
+ return
2175
+ """
2176
+
2177
+ # 多只股票的杜邦分析对比
2178
+ from siat.financials_china import compare_dupont_china
2179
+ df_db=compare_dupont_china(tickers,fsdate=fsdates,sort=sort,printout=printout, \
2180
+ facecolor=facecolor,font_size=font_size,loc=loc1)
2181
+ return
2182
+
2183
+ elif ('dupont' in analysis_type1) and ('decompose' in analysis_type1):
2184
+ # 股票需为单只股票列表
2185
+ if not isinstance(tickers,str):
2186
+ if isinstance(tickers,list):
2187
+ tickers=tickers[0]
2188
+ else:
2189
+ print(" #Warning(fs_analysis_china): must be one ticker for",tickers)
2190
+ return
2191
+ # 日期需为一个日期
2192
+ if not isinstance(fsdates,str):
2193
+ if isinstance(fsdates,list):
2194
+ fsdates=fsdates[0]
2195
+ else:
2196
+ print(" #Warning(fs_analysis_china): must one date for",fsdates)
2197
+ return
2198
+
2199
+ # 单只股票的多层杜邦分解
2200
+ from siat.financials_china import dupont_decompose_china
2201
+ df_dbd=dupont_decompose_china(ticker=tickers,fsdate=fsdates,gview=gview,facecolor=facecolor)
2202
+ return
2203
+
2204
+ else:
2205
+ print(" #Warning(fs_analysis_china): sorry, no idea on what to do for",analysis_type)
2206
+
2207
+ return
2208
+
2209
+
2210
+ #==============================================================================
2211
+ #==============================================================================
2212
+ #==============================================================================