neurostats-API 0.0.6__py3-none-any.whl → 0.0.8__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,6 @@
1
1
  from .base import StatsFetcher, StatsDateTime
2
2
  import json
3
+ import numpy as np
3
4
  import pandas as pd
4
5
  from ..utils import StatsDateTime, StatsProcessor
5
6
  import importlib.resources as pkg_resources
@@ -14,8 +15,10 @@ class FinanceOverviewFetcher(StatsFetcher):
14
15
  def __init__(self, ticker, db_client):
15
16
  super().__init__(ticker, db_client)
16
17
 
17
- self.target_fields = StatsProcessor.load_yaml("finance_overview_dict.yaml")
18
- self.inverse_dict = StatsProcessor.load_txt("seasonal_data_field_dict.txt", json_load=True)
18
+ self.target_fields = StatsProcessor.load_yaml(
19
+ "finance_overview_dict.yaml")
20
+ self.inverse_dict = StatsProcessor.load_txt(
21
+ "seasonal_data_field_dict.txt", json_load=True)
19
22
 
20
23
  def prepare_query(self, target_year, target_season):
21
24
 
@@ -82,8 +85,11 @@ class FinanceOverviewFetcher(StatsFetcher):
82
85
  def query_data(self):
83
86
  today = StatsDateTime.get_today()
84
87
 
85
- fetched_data = self.collect_data(2024, 2)
88
+ year = today.year - 1 if (today.season == 1) else today.year
89
+ season = 4 if (today.season == 1) else today.season - 1
90
+ fetched_data = self.collect_data(year, season)
86
91
  finance_dict = fetched_data['seasonal_data'][0]
92
+ FinanceOverviewProcessor.process_rate(finance_dict)
87
93
  FinanceOverviewProcessor.process_all(finance_dict)
88
94
  fetched_data['seasonal_data'] = finance_dict
89
95
  return fetched_data
@@ -91,41 +97,38 @@ class FinanceOverviewFetcher(StatsFetcher):
91
97
 
92
98
  class FinanceOverviewProcessor(StatsProcessor):
93
99
 
100
+ @classmethod
101
+ def process_rate(cls, finance_dict):
102
+ for key in finance_dict:
103
+ if ('YoY' in key):
104
+ finance_dict[key] = StatsProcessor.cal_percentage(
105
+ finance_dict[key])
106
+ elif ("rate" in key or 'ratio' in key):
107
+ finance_dict[key] = StatsProcessor.cal_non_percentage(
108
+ finance_dict[key], to_str=True, postfix='%')
109
+ else:
110
+ finance_dict[key] = StatsProcessor.cal_non_percentage(
111
+ finance_dict[key])
112
+
94
113
  @classmethod
95
114
  def process_all(cls, finance_dict):
96
115
  methods = [
97
- cls.cal_EBIT,
98
- cls.cal_share_outstanding,
99
- cls.cal_fcf,
100
- cls.cal_revenue_per_share,
101
- cls.cal_gross_per_share,
102
- cls.cal_operating_income_per_share,
103
- cls.cal_operating_cash_flow_per_share,
104
- cls.fcf_per_share,
105
- cls.cal_roa,
106
- cls.cal_roe,
107
- cls.cal_gross_over_asset,
108
- cls.cal_roce,
109
- cls.cal_gross_profit_marginal,
110
- cls.cal_operation_profit_rate,
111
- cls.cal_operating_cash_flow_profit_rate,
112
- cls.cal_dso,
113
- cls.cal_account_receive_over_revenue,
114
- cls.cal_dpo,
115
- cls.cal_inventories_cycle_ratio,
116
- cls.cal_dio,
116
+ cls.cal_EBIT, cls.cal_share_outstanding, cls.cal_fcf,
117
+ cls.cal_interest_bearing_debt, cls.cal_revenue_per_share,
118
+ cls.cal_gross_per_share, cls.cal_operating_income_per_share,
119
+ cls.cal_operating_cash_flow_per_share, cls.fcf_per_share,
120
+ cls.cal_roa, cls.cal_roe, cls.cal_gross_over_asset, cls.cal_roce,
121
+ cls.cal_gross_profit_marginal, cls.cal_operation_profit_rate,
122
+ cls.cal_operating_cash_flow_profit_rate, cls.cal_dso,
123
+ cls.cal_account_receive_over_revenue, cls.cal_dpo,
124
+ cls.cal_inventories_cycle_ratio, cls.cal_dio,
117
125
  cls.cal_inventories_revenue_ratio,
118
- cls.cal_cash_of_conversion_cycle,
119
- cls.cal_asset_turnover,
120
- cls.cal_application_turnover,
121
- cls.cal_current_ratio,
122
- cls.cal_quick_ratio,
123
- cls.cal_debt_to_equity_ratio,
124
- cls.cal_net_debt_to_equity_ratio,
125
- cls.cal_interest_coverage_ratio,
126
+ cls.cal_cash_of_conversion_cycle, cls.cal_asset_turnover,
127
+ cls.cal_application_turnover, cls.cal_current_ratio,
128
+ cls.cal_quick_ratio, cls.cal_debt_to_equity_ratio,
129
+ cls.cal_net_debt_to_equity_ratio, cls.cal_interest_coverage_ratio,
126
130
  cls.cal_debt_to_operating_cash_flow,
127
- cls.cal_debt_to_free_cash_flow,
128
- cls.cal_cash_flow_ratio
131
+ cls.cal_debt_to_free_cash_flow, cls.cal_cash_flow_ratio
129
132
  ]
130
133
 
131
134
  for method in methods:
@@ -135,13 +138,13 @@ class FinanceOverviewProcessor(StatsProcessor):
135
138
  def cal_EBIT(cls, finance_dict):
136
139
  """
137
140
  計算EBIT
138
- EBIT = 營業收入 - 營業成本 - 營業費用
141
+ EBIT = 營業收入 - 營業成本 - 營業費用 - 所得稅費用
139
142
  """
140
143
  try:
141
- finance_dict['EBIT'] = (finance_dict['revenue'] -
142
- finance_dict['operating_cost'] -
143
- finance_dict['operating_expenses'])
144
- except (KeyError, TypeError) as e:
144
+ EBIT = (finance_dict['revenue'] - finance_dict['operating_cost'] -
145
+ finance_dict['operating_expenses'] - finance_dict['tax_fee'])
146
+ finance_dict['EBIT'] = StatsProcessor.cal_non_percentage(EBIT)
147
+ except (KeyError, ZeroDivisionError, TypeError) as e:
145
148
  finance_dict['EBIT'] = None
146
149
  print(f"Error calculating EBIT: {e}")
147
150
 
@@ -152,12 +155,32 @@ class FinanceOverviewProcessor(StatsProcessor):
152
155
  自由現金流 = 營業現金流 + 投資現金流
153
156
  """
154
157
  try:
155
- finance_dict["fcf"] = (finance_dict["operating_cash_flow"] +
156
- finance_dict["financing_cash_flow"])
157
- except Exception as e:
158
+ fcf = (finance_dict["operating_cash_flow"] +
159
+ finance_dict["financing_cash_flow"])
160
+ finance_dict["fcf"] = StatsProcessor.cal_non_percentage(fcf)
161
+ except (KeyError, ZeroDivisionError, TypeError) as e:
158
162
  finance_dict['fcf'] = None
159
163
  print(f"Error calculating FCF: {e}")
160
164
 
165
+ @classmethod
166
+ def cal_interest_bearing_debt(cls, finance_dict):
167
+ """
168
+ 計算有息負債
169
+ 短期借款+長期借款
170
+ """
171
+ finance_dict['interest_bearing_debt'] = 0.0
172
+
173
+ try:
174
+ finance_dict['interest_bearing_debt'] += finance_dict[
175
+ 'short_term_liabilities']
176
+ except (KeyError, ZeroDivisionError, TypeError) as e:
177
+ finance_dict['interest_bearing_debt'] += 0.0
178
+ try:
179
+ finance_dict['interest_bearing_debt'] += finance_dict[
180
+ 'long_term_liabilities']
181
+ except (KeyError, ZeroDivisionError, TypeError) as e:
182
+ finance_dict['interest_bearing_debt'] += 0.0
183
+
161
184
  @classmethod
162
185
  def cal_share_outstanding(cls, finance_dict):
163
186
  """
@@ -167,7 +190,7 @@ class FinanceOverviewProcessor(StatsProcessor):
167
190
  try:
168
191
  finance_dict["share_outstanding"] = (finance_dict['net_income'] /
169
192
  finance_dict['eps'])
170
- except KeyError as e:
193
+ except (KeyError, ZeroDivisionError, TypeError) as e:
171
194
  finance_dict['share_outstanding'] = None
172
195
  print(f"share_outstanding failed because of {str(e)}")
173
196
 
@@ -178,9 +201,12 @@ class FinanceOverviewProcessor(StatsProcessor):
178
201
  每股營收 = 營業收入 / 在外流通股數
179
202
  """
180
203
  try:
181
- finance_dict['revenue_per_share'] = (
182
- finance_dict['revenue'] / finance_dict['share_outstanding'])
183
- except KeyError as e:
204
+ revenue_per_share = (finance_dict['revenue'] /
205
+ finance_dict['share_outstanding'])
206
+ finance_dict[
207
+ 'revenue_per_share'] = StatsProcessor.cal_non_percentage(
208
+ revenue_per_share, False)
209
+ except (KeyError, ZeroDivisionError, TypeError) as e:
184
210
  finance_dict['revenue_per_share'] = None
185
211
  print(f"revenue_per_share failed because of {str(e)}")
186
212
 
@@ -192,10 +218,13 @@ class FinanceOverviewProcessor(StatsProcessor):
192
218
  """
193
219
 
194
220
  try:
195
- finance_dict['gross_per_share'] = (
196
- finance_dict['gross_profit'] /
197
- finance_dict['share_outstanding'])
198
- except KeyError as e:
221
+ gross_per_share = (finance_dict['gross_profit'] /
222
+ finance_dict['share_outstanding'])
223
+ finance_dict[
224
+ 'gross_per_share'] = StatsProcessor.cal_non_percentage(
225
+ gross_per_share, False)
226
+
227
+ except (KeyError, ZeroDivisionError, TypeError) as e:
199
228
  finance_dict['gross_per_share'] = None
200
229
  print(f"gross_per_share failed because of {str(e)}")
201
230
 
@@ -206,10 +235,12 @@ class FinanceOverviewProcessor(StatsProcessor):
206
235
  每股營業利益= (當期營業利益)÷(當期在外流通股數)
207
236
  """
208
237
  try:
209
- finance_dict['operating_income_per_share'] = (
210
- finance_dict['operating_income'] /
211
- finance_dict['share_outstanding'])
212
- except KeyError as e:
238
+ operating_income_per_share = (finance_dict['operating_income'] /
239
+ finance_dict['share_outstanding'])
240
+ finance_dict[
241
+ 'operating_income_per_share'] = StatsProcessor.cal_non_percentage(
242
+ operating_income_per_share)
243
+ except (KeyError, ZeroDivisionError, TypeError) as e:
213
244
  finance_dict['operating_income_per_share'] = None
214
245
  print(f"operating_income_per_share failed because of {str(e)}")
215
246
 
@@ -220,10 +251,13 @@ class FinanceOverviewProcessor(StatsProcessor):
220
251
  = (當期營業現金流) ÷(當期在外流通股數)
221
252
  """
222
253
  try:
223
- finance_dict["operating_cash_flow_per_share"] = (
254
+ operating_cash_flow_per_share = (
224
255
  finance_dict["operating_cash_flow"] /
225
256
  finance_dict['share_outstanding'])
226
- except KeyError as e:
257
+ finance_dict[
258
+ "operating_cash_flow_per_share"] = StatsProcessor.cal_non_percentage(
259
+ operating_cash_flow_per_share)
260
+ except (KeyError, ZeroDivisionError, TypeError) as e:
227
261
  finance_dict['operating_cash_flow_per_share'] = None
228
262
  print(f'operating_cash_flow_per_share because of {str(e)}')
229
263
 
@@ -234,9 +268,11 @@ class FinanceOverviewProcessor(StatsProcessor):
234
268
  每股自由現金流 = (當期自由現金流) ÷(當期在外流通股數)
235
269
  """
236
270
  try:
237
- finance_dict['fcf_per_share'] = (finance_dict['fcf'] /
238
- finance_dict['share_outstanding'])
239
- except KeyError as e:
271
+ fcf_per_share = (finance_dict['fcf'] /
272
+ finance_dict['share_outstanding'])
273
+ finance_dict['fcf_per_share'] = StatsProcessor.cal_non_percentage(
274
+ fcf_per_share)
275
+ except (KeyError, ZeroDivisionError, TypeError) as e:
240
276
  finance_dict['fcf_per_share'] = None
241
277
  print(f"fcf_per_share failed because of {str(e)}")
242
278
 
@@ -248,27 +284,35 @@ class FinanceOverviewProcessor(StatsProcessor):
248
284
  計算資產報酬率(ROA)
249
285
  ROA = [ 本期淨利 + 利息費用 × (1-有效稅率) ] ÷(資產總額)
250
286
  """
251
- finance_dict["roa"] = (
287
+ roa = (
252
288
  finance_dict['net_income'] + finance_dict['interest'] +
253
289
  (1 * 0.1) # 有效稅率需要改,這裡先設0.1
254
290
  ) / finance_dict['inventories']
255
291
 
292
+ finance_dict["roa"] = StatsProcessor.cal_percentage(roa)
293
+
256
294
  @classmethod
257
295
  def cal_roe(cls, finance_dict):
258
296
  """
259
297
  計算股東權益報酬率(ROE)
260
298
  ROE = (本期淨利) ÷(權益總額)
261
299
  """
262
- finance_dict['roe'] = (finance_dict['net_income'] /
263
- finance_dict['equity'])
300
+ roe = (finance_dict['net_income'] / finance_dict['equity'])
301
+ finance_dict['roe'] = StatsProcessor.cal_percentage(roe)
264
302
 
265
303
  @classmethod
266
304
  def cal_gross_over_asset(cls, finance_dict):
267
305
  """
268
306
  計算營業毛利/總資產
269
307
  """
270
- finance_dict['gross_over_asset'] = (finance_dict['gross_profit'] /
271
- finance_dict['total_asset'])
308
+ try:
309
+ gross_over_asset = (finance_dict['gross_profit'] /
310
+ finance_dict['total_asset'])
311
+ finance_dict['gross_over_asset'] = StatsProcessor.cal_percentage(
312
+ gross_over_asset)
313
+ except (KeyError, ZeroDivisionError, TypeError) as e:
314
+ finance_dict['gross_over_asset'] = None
315
+ print(f"營業毛利/總資產 failed because of {str(e)}")
272
316
 
273
317
  @classmethod
274
318
  def cal_roce(cls, finance_dict):
@@ -277,11 +321,13 @@ class FinanceOverviewProcessor(StatsProcessor):
277
321
  ROCE = (稅前淨利+利息費用) / (資產總額-流動負債)
278
322
  """
279
323
  try:
280
- finance_dict['roce'] = (
281
- (finance_dict['net_income_before_tax'] +
282
- finance_dict['interest']) /
283
- (finance_dict['asset'] - finance_dict['current_liabilities']))
284
- except KeyError as e:
324
+ roce = ((finance_dict['net_income_before_tax'] +
325
+ finance_dict['interest']) /
326
+ (finance_dict['total_asset'] -
327
+ finance_dict['current_liabilities']))
328
+ finance_dict['roce'] = StatsProcessor.cal_percentage(roce)
329
+
330
+ except (KeyError, ZeroDivisionError, TypeError) as e:
285
331
  finance_dict['roce'] = None
286
332
  print(f"ROCE failed because of {str(e)}")
287
333
 
@@ -292,8 +338,11 @@ class FinanceOverviewProcessor(StatsProcessor):
292
338
  營業毛利率 = 營業毛利 ÷ 營業收入
293
339
  """
294
340
  try:
295
- finance_dict['gross_profit_margin'] = (
296
- finance_dict['gross_profit'] / finance_dict['revenue'])
341
+ gross_profit_margin = (finance_dict['gross_profit'] /
342
+ finance_dict['revenue'])
343
+ finance_dict[
344
+ 'gross_profit_margin'] = StatsProcessor.cal_percentage(
345
+ gross_profit_margin)
297
346
  except:
298
347
  finance_dict['gross_profit_margin'] = None
299
348
  print(f"gross_profit_margin failed because of {str(e)}")
@@ -305,10 +354,13 @@ class FinanceOverviewProcessor(StatsProcessor):
305
354
  營業利益率 = ( 營業收入-營業成本-營業費用)÷ 營業收入
306
355
  """
307
356
  try:
308
- finance_dict["operation_profit_rate"] = (
357
+ operation_profit_rate = (
309
358
  finance_dict['revenue'] - finance_dict['operating_cost'] -
310
- finance_dict['operating_price']) / finance_dict['revenue']
311
- except KeyError as e:
359
+ finance_dict['operating_expenses']) / finance_dict['revenue']
360
+ finance_dict[
361
+ "operation_profit_rate"] = StatsProcessor.cal_percentage(
362
+ operation_profit_rate)
363
+ except (KeyError, ZeroDivisionError, TypeError) as e:
312
364
  finance_dict["operation_profit_rate"] = None
313
365
  print(f"operation_profit failed because of {str(e)}")
314
366
 
@@ -319,11 +371,13 @@ class FinanceOverviewProcessor(StatsProcessor):
319
371
  營業現金流利潤率 = 營業活動現金流 ÷ 營業收入
320
372
  """
321
373
  try:
322
- finance_dict["operating_cash_flow_profit_rate"] = (
374
+ operating_cash_flow_profit_rate = (
323
375
  finance_dict["operating_cash_flow"] / finance_dict["revenue"])
324
- except KeyError:
376
+ finance_dict[
377
+ "operating_cash_flow_profit_rate"] = StatsProcessor.cal_percentage(
378
+ operating_cash_flow_profit_rate)
379
+ except (KeyError, ZeroDivisionError, TypeError) as e:
325
380
  finance_dict["operating_cash_flow_profit_rate"] = None
326
-
327
381
  print(
328
382
  f"operating_cash_flow_profit_rate failed because of {str(e)}")
329
383
 
@@ -340,10 +394,16 @@ class FinanceOverviewProcessor(StatsProcessor):
340
394
  def cal_dso(cls, finance_dict):
341
395
  """
342
396
  計算應收帳款收現天數(DSO)
343
- DSO = 365 × (營業收入 ÷ 應收帳款平均餘額)
397
+ DSO = 365 × (應收帳款平均餘額 ÷ 營業收入)
344
398
  """
345
- finance_dict['dso'] = (
346
- 365 * (finance_dict['revenue'] / finance_dict['account_pay']))
399
+ try:
400
+ dso = (365 *
401
+ (finance_dict['account_pay'] / finance_dict['revenue']))
402
+ finance_dict['dso'] = StatsProcessor.cal_non_percentage(
403
+ dso, to_str=True, postfix="日")
404
+ except:
405
+ finance_dict['dso'] = None
406
+ print(f"Error calculating 應收帳款收現天數 because of {str(e)}")
347
407
 
348
408
  @classmethod
349
409
  def cal_account_receive_over_revenue(cls, finance_dict):
@@ -351,8 +411,11 @@ class FinanceOverviewProcessor(StatsProcessor):
351
411
  計算應收帳款佔營收比率
352
412
  = 應收帳款平均餘額 ÷ 營業收入
353
413
  """
354
- finance_dict["account_receive_over_revenue"] = (
355
- finance_dict['account_receive'] / finance_dict['revenue'])
414
+ account_receive_over_revenue = (finance_dict['account_receive'] /
415
+ finance_dict['revenue'])
416
+ finance_dict[
417
+ "account_receive_over_revenue"] = StatsProcessor.cal_percentage(
418
+ account_receive_over_revenue)
356
419
 
357
420
  @classmethod
358
421
  def cal_dpo(cls, finance_dict):
@@ -360,9 +423,15 @@ class FinanceOverviewProcessor(StatsProcessor):
360
423
  計算應付帳款週轉天數
361
424
  DPO = 365天 ÷ (銷貨成本÷平均應付帳款)
362
425
  """
363
- finance_dict["dpo"] = (
364
- 365 *
365
- (finance_dict['operating_cost'] / finance_dict['account_pay']))
426
+ try:
427
+ dpo = (
428
+ 365 *
429
+ (finance_dict['account_pay'] / finance_dict['operating_cost']))
430
+ finance_dict["dpo"] = StatsProcessor.cal_non_percentage(
431
+ dpo, to_str=True, postfix="日")
432
+ except (KeyError, ZeroDivisionError, TypeError) as e:
433
+ finance_dict["dpo"] = None
434
+ print(f"應付帳款週轉天數 failed because of {str(e)}")
366
435
 
367
436
  @classmethod
368
437
  def cal_inventories_cycle_ratio(cls, finance_dict):
@@ -370,19 +439,32 @@ class FinanceOverviewProcessor(StatsProcessor):
370
439
  計算存貨周轉率
371
440
  = 銷貨成本 ÷ 存貨
372
441
  """
442
+ try:
443
+ inventories_cycle_ratio = (finance_dict['operating_cost'] /
444
+ finance_dict['inventories'])
373
445
 
374
- finance_dict["inventories_cycle_ratio"] = (
375
- finance_dict['operating_cost'] / finance_dict['inventories'])
446
+ finance_dict[
447
+ "inventories_cycle_ratio"] = StatsProcessor.cal_percentage(
448
+ inventories_cycle_ratio)
449
+ except (KeyError, ZeroDivisionError, TypeError) as e:
450
+ finance_dict["inventories_cycle_ratio"] = None
451
+ print(f"Error calculating 存貨周轉率 because of {str(e)}")
376
452
 
377
453
  @classmethod
378
454
  def cal_dio(cls, finance_dict):
379
455
  """
380
- 計算 存貨週轉天數
381
- DIO = 365天 ÷ (銷貨成本 ÷ 存貨)
382
- MUDA MUDA MUDA MUDA !!!
456
+ 計算 存貨週轉天數 or 平均售貨天數
457
+ DIO = 365天 * (存貨 ÷ 銷貨成本)
458
+ MUDA MUDA MUDA !!!
383
459
  """
384
- finance_dict["dio"] = (finance_dict["operating_cost"] /
385
- finance_dict["inventories"])
460
+ try:
461
+ dio = 365 * (finance_dict["inventories"] /
462
+ finance_dict["operating_cost"])
463
+ finance_dict["dio"] = StatsProcessor.cal_non_percentage(
464
+ dio, to_str=True, postfix="日")
465
+ except (KeyError, ZeroDivisionError, TypeError) as e:
466
+ finance_dict["dio"] = None
467
+ print(f"Error calculating 存貨週轉天數 because of {str(e)}")
386
468
 
387
469
  @classmethod
388
470
  def cal_inventories_revenue_ratio(cls, finance_dict):
@@ -390,8 +472,16 @@ class FinanceOverviewProcessor(StatsProcessor):
390
472
  計算存貨佔營收比率
391
473
  存貨佔營收比= 存貨 ÷ 營業收入
392
474
  """
393
- finance_dict["inventories_revenue_ratio"] = (
394
- finance_dict['inventories'] / finance_dict['revenue'])
475
+ try:
476
+ inventories_revenue_ratio = (finance_dict['inventories'] /
477
+ finance_dict['revenue'])
478
+
479
+ finance_dict[
480
+ "inventories_revenue_ratio"] = StatsProcessor.cal_percentage(
481
+ inventories_revenue_ratio)
482
+ except (KeyError, ZeroDivisionError, TypeError) as e:
483
+ finance_dict["inventories_revenue_ratio"] = None
484
+ print(f"Error calculating 存貨佔營收比率 because of {str(e)}")
395
485
 
396
486
  @classmethod
397
487
  def cal_cash_of_conversion_cycle(cls, finance_dict):
@@ -399,19 +489,42 @@ class FinanceOverviewProcessor(StatsProcessor):
399
489
  計算現金循環週期
400
490
  存貨週轉天數 + 應收帳款週轉天數 - 應付帳款週轉天數
401
491
  """
402
- finance_dict["cash_of_conversion_cycle"] = (finance_dict["dio"] +
403
- finance_dict["dso"] -
404
- finance_dict['dpo'])
492
+ try:
493
+ cash_of_conversion_cycle = (finance_dict["dio"] +
494
+ finance_dict["dso"] -
495
+ finance_dict['dpo'])
496
+ finance_dict[
497
+ "cash_of_conversion_cycle"] = StatsProcessor.cal_non_percentage(
498
+ cash_of_conversion_cycle, to_str=True, postfix="日")
499
+ except (KeyError, ZeroDivisionError, TypeError) as e:
500
+ finance_dict["cash_of_conversion_cycle"] = None
405
501
 
406
502
  @classmethod
407
503
  def cal_asset_turnover(cls, finance_dict):
408
- finance_dict["asset_turnover"] = (finance_dict["revenue"] /
409
- finance_dict["inventories"])
504
+ """
505
+ 計算資產周轉率
506
+ 營業收入 ÷ 資產總額
507
+ """
508
+ asset_turnover = (finance_dict["revenue"] /
509
+ finance_dict["inventories"])
510
+ finance_dict["asset_turnover"] = StatsProcessor.cal_percentage(
511
+ asset_turnover)
410
512
 
411
513
  @classmethod
412
514
  def cal_application_turnover(cls, finance_dict):
413
- finance_dict['applcation_turnover'] = (finance_dict['revenue'] /
414
- finance_dict["application"])
515
+ """
516
+ 不動產、廠房及設備週轉率
517
+ 營業收入 ÷ 不動產、廠房與設備平均餘額
518
+ """
519
+ try:
520
+ applcation_turnover = (finance_dict['revenue'] /
521
+ finance_dict["application"])
522
+ finance_dict[
523
+ 'applcation_turnover'] = StatsProcessor.cal_percentage(
524
+ applcation_turnover)
525
+
526
+ except (KeyError, ZeroDivisionError, TypeError) as e:
527
+ finance_dict['application_turnover'] = None
415
528
 
416
529
  @classmethod
417
530
  def cal_current_ratio(cls, finance_dict):
@@ -419,81 +532,117 @@ class FinanceOverviewProcessor(StatsProcessor):
419
532
  計算流動比率 = 流動資產 / 流動負債
420
533
  """
421
534
  try:
422
- finance_dict['current_ratio'] = finance_dict[
423
- 'current_assets'] / finance_dict['current_liabilities']
535
+ current_ratio = (finance_dict['current_assets'] /
536
+ finance_dict['current_liabilities'])
537
+ finance_dict['current_ratio'] = StatsProcessor.cal_percentage(
538
+ current_ratio)
424
539
  except (KeyError, ZeroDivisionError, TypeError) as e:
425
540
  finance_dict['current_ratio'] = None
426
541
  print(f"Error calculating current ratio: {e}")
427
542
 
428
543
  @classmethod
429
544
  def cal_quick_ratio(cls, finance_dict):
545
+ """
546
+ 速動比率
547
+ (流動資產 - 存貨) / 流動負債
548
+ """
430
549
  try:
431
- # 速動比率 = (流動資產 - 存貨) / 流動負債
432
- finance_dict['quick_ratio'] = (
433
- finance_dict['current_assets'] - finance_dict['inventories']
434
- ) / finance_dict['current_liabilities']
550
+ quick_ratio = (finance_dict['current_assets'] -
551
+ finance_dict['inventories']
552
+ ) / finance_dict['current_liabilities']
553
+ finance_dict['quick_ratio'] = StatsProcessor.cal_percentage(
554
+ quick_ratio)
435
555
  except (KeyError, ZeroDivisionError, TypeError) as e:
436
556
  finance_dict['quick_ratio'] = None
437
557
  print(f"Error calculating quick ratio: {e}")
438
558
 
439
559
  @classmethod
440
560
  def cal_debt_to_equity_ratio(cls, finance_dict):
561
+ """
562
+ # 負債權益比率 = 總負債 / 股東權益
563
+ """
441
564
  try:
442
- # 負債權益比率 = 總負債 / 股東權益
443
- finance_dict['debt_to_equity_ratio'] = finance_dict[
565
+ debt_to_equity_ratio = finance_dict[
444
566
  'total_liabilities'] / finance_dict['equity']
567
+ finance_dict[
568
+ 'debt_to_equity_ratio'] = StatsProcessor.cal_percentage(
569
+ debt_to_equity_ratio)
445
570
  except (KeyError, ZeroDivisionError, TypeError) as e:
446
571
  finance_dict['debt_to_equity_ratio'] = None
447
572
  print(f"Error calculating debt to equity ratio: {e}")
448
573
 
449
574
  @classmethod
450
575
  def cal_net_debt_to_equity_ratio(cls, finance_dict):
576
+ """
577
+ # 淨負債權益比率 = (總負債 - 現金及約當現金) / 股東權益
578
+ """
451
579
  try:
452
- # 淨負債權益比率 = (總負債 - 現金及約當現金) / 股東權益
453
- finance_dict['net_debt_to_equity_ratio'] = (
580
+ net_debt_to_equity_ratio = (
454
581
  finance_dict['total_liabilities'] -
455
582
  finance_dict['cash_and_cash_equivalents']
456
583
  ) / finance_dict['equity']
584
+ finance_dict[
585
+ 'net_debt_to_equity_ratio'] = StatsProcessor.cal_percentage(
586
+ net_debt_to_equity_ratio)
457
587
  except (KeyError, ZeroDivisionError, TypeError) as e:
458
588
  finance_dict['net_debt_to_equity_ratio'] = None
459
589
  print(f"Error calculating net debt to equity ratio: {e}")
460
590
 
461
591
  @classmethod
462
592
  def cal_interest_coverage_ratio(cls, finance_dict):
593
+ """
594
+ # 利息保障倍數 = EBIT / 利息費用
595
+ """
463
596
  try:
464
- # 利息保障倍數 = EBIT / 利息費用
465
- finance_dict['interest_coverage_ratio'] = finance_dict[
466
- 'EBIT'] / finance_dict['interest_expense']
597
+ interest_coverage_ratio = finance_dict['EBIT'] / finance_dict[
598
+ 'interest_expense']
599
+ finance_dict[
600
+ 'interest_coverage_ratio'] = StatsProcessor.cal_non_percentage(
601
+ interest_coverage_ratio, to_str=True, postfix="倍")
467
602
  except (KeyError, ZeroDivisionError, TypeError) as e:
468
603
  finance_dict['interest_coverage_ratio'] = None
469
604
  print(f"Error calculating interest coverage ratio: {e}")
470
605
 
471
606
  @classmethod
472
607
  def cal_debt_to_operating_cash_flow(cls, finance_dict):
608
+ """
609
+ 有息負債 / 營業活動現金流
610
+ """
473
611
  try:
474
- # 有息負債 / 營業活動現金流
475
- finance_dict['debt_to_operating_cash_flow'] = finance_dict[
612
+ debt_to_operating_cash_flow = finance_dict[
476
613
  'interest_bearing_debt'] / finance_dict['operating_cash_flow']
614
+ finance_dict[
615
+ 'debt_to_operating_cash_flow'] = StatsProcessor.cal_percentage(
616
+ debt_to_operating_cash_flow)
477
617
  except (KeyError, ZeroDivisionError, TypeError) as e:
478
618
  finance_dict['debt_to_operating_cash_flow'] = None
479
619
  print(f"Error calculating debt to operating cash flow: {e}")
480
620
 
481
621
  @classmethod
482
622
  def cal_debt_to_free_cash_flow(cls, finance_dict):
623
+ """
624
+ # 有息負債 / 自由現金流
625
+ """
483
626
  try:
484
- # 有息負債 / 自由現金流
485
- finance_dict['debt_to_free_cash_flow'] = finance_dict[
627
+ debt_to_free_cash_flow = finance_dict[
486
628
  'interest_bearing_debt'] / finance_dict['fcf']
629
+ finance_dict[
630
+ 'debt_to_free_cash_flow'] = StatsProcessor.cal_percentage(
631
+ debt_to_free_cash_flow)
487
632
  except (KeyError, ZeroDivisionError, TypeError) as e:
488
633
  finance_dict['debt_to_free_cash_flow'] = None
489
634
  print(f"Error calculating debt to free cash flow: {e}")
490
635
 
491
636
  @classmethod
492
637
  def cal_cash_flow_ratio(cls, finance_dict):
638
+ """
639
+ # 現金流量比率 = 營業活動現金流 / 流動負債
640
+ """
493
641
  try:
494
- # 現金流量比率 = 營業活動現金流 / 流動負債
495
- finance_dict['cash_flow_ratio'] = finance_dict[
642
+ cash_flow_ratio = finance_dict[
496
643
  'operating_cash_flow'] / finance_dict['current_liabilities']
644
+ finance_dict['cash_flow_ratio'] = StatsProcessor.cal_percentage(
645
+ cash_flow_ratio)
497
646
  except (KeyError, ZeroDivisionError, TypeError) as e:
498
647
  finance_dict['cash_flow_ratio'] = None
499
648
  print(f"Error calculating cash flow ratio: {e}")