neurostats-API 0.0.6__py3-none-any.whl → 0.0.8__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.
@@ -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}")