neurostats-API 0.0.7__py3-none-any.whl → 0.0.9__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- __version__='0.0.7'
1
+ __version__='0.0.8'
@@ -1,10 +1,12 @@
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
6
7
  import yaml
7
8
 
9
+
8
10
  class BalanceSheetFetcher(StatsFetcher):
9
11
  """
10
12
  對應iFa.ai -> 財務分析 -> 資產負債表
@@ -13,7 +15,7 @@ class BalanceSheetFetcher(StatsFetcher):
13
15
  def __init__(self, ticker, db_client):
14
16
  super().__init__(ticker, db_client)
15
17
  self.table_settings = StatsProcessor.load_yaml("balance_sheet.yaml")
16
-
18
+
17
19
  def prepare_query(self, target_year, target_season):
18
20
  pipeline = super().prepare_query()
19
21
 
@@ -24,36 +26,42 @@ class BalanceSheetFetcher(StatsFetcher):
24
26
  }
25
27
 
26
28
  pipeline.append({
27
- "$project": {
28
- "_id": 0,
29
- "ticker": 1,
30
- "company_name": 1,
31
- "balance_sheets": {
32
- "$sortArray": {
33
- "input": {
34
- "$map": {
35
- "input": {
36
- "$filter": {
37
- "input": "$seasonal_data",
38
- "as": "season",
39
- "cond": {
40
- "$eq": ["$$season.season", target_season]
29
+ "$project": {
30
+ "_id": 0,
31
+ "ticker": 1,
32
+ "company_name": 1,
33
+ "balance_sheets": {
34
+ "$sortArray": {
35
+ "input": {
36
+ "$map": {
37
+ "input": {
38
+ "$filter": {
39
+ "input": "$seasonal_data",
40
+ "as": "season",
41
+ "cond": {
42
+ "$eq":
43
+ ["$$season.season", target_season]
44
+ }
41
45
  }
46
+ },
47
+ "as": "target_season_data",
48
+ "in": {
49
+ "year":
50
+ "$$target_season_data.year",
51
+ "season":
52
+ "$$target_season_data.season",
53
+ "balance_sheet":
54
+ "$$target_season_data.balance_sheet"
42
55
  }
43
- },
44
- "as": "target_season_data",
45
- "in": {
46
- "year": "$$target_season_data.year",
47
- "season": "$$target_season_data.season",
48
- "balance_sheet": "$$target_season_data.balance_sheet"
49
56
  }
50
- }
51
- },
52
- "sortBy": { "year": -1 } # 按 year 降序排序
57
+ },
58
+ "sortBy": {
59
+ "year": -1
60
+ } # 按 year 降序排序
61
+ }
53
62
  }
54
63
  }
55
- }
56
- })
64
+ })
57
65
 
58
66
  return pipeline
59
67
 
@@ -67,10 +75,16 @@ class BalanceSheetFetcher(StatsFetcher):
67
75
  return fetched_data[-1]
68
76
 
69
77
  def query_data(self):
70
- today = StatsDateTime.get_today()
78
+ try:
79
+ latest_time = StatsDateTime.get_latest_time(
80
+ self.ticker, self.collection)['last_update_time']
81
+ year = latest_time['seasonal_data']['latest_year']
82
+ season = latest_time['seasonal_data']['latest_season']
83
+ except Exception as e:
84
+ today = StatsDateTime.get_today()
85
+ year = today.year - 1 if (today.season == 1) else today.year
86
+ season = 4 if (today.season == 1) else today.season - 1
71
87
 
72
- year = today.year - 1 if (today.season == 1) else today.year
73
- season = 4 if (today.season == 1) else today.season - 2
74
88
  fetched_data = self.collect_data(year, season)
75
89
 
76
90
  return self.process_data(season, fetched_data)
@@ -93,20 +107,26 @@ class BalanceSheetFetcher(StatsFetcher):
93
107
 
94
108
  time_index = f"{year}Q{target_season}"
95
109
 
96
- # 蒐集整體的keys
110
+ # 蒐集整體的keys
97
111
  index_names += list(data['balance_sheet'].keys())
98
112
  balance_sheet = data['balance_sheet']
99
113
 
100
114
  for index_name, value_dict in balance_sheet.items():
101
115
  for item_name, item in value_dict.items():
102
- try: # table_dict[項目][(2020Q1, '%')]
103
- table_dict[index_name][(time_index,item_name)] = item
116
+ try: # table_dict[項目][(2020Q1, '%')]
117
+ if (item_name == 'percentage'):
118
+ if (isinstance(item, (float, int))):
119
+ item = np.round(item, 2)
120
+ if ("YoY" in item_name):
121
+ if (isinstance(item, (float, int))):
122
+ item = np.round(item * 100, 2)
123
+ table_dict[index_name][(time_index, item_name)] = item
104
124
 
105
125
  except KeyError:
106
126
  if (index_name not in table_dict.keys()):
107
127
  table_dict[index_name] = dict()
108
128
 
109
- table_dict[index_name][(time_index,item_name)] = item
129
+ table_dict[index_name][(time_index, item_name)] = item
110
130
 
111
131
  total_table = pd.DataFrame.from_dict(table_dict, orient='index')
112
132
  total_table.columns = pd.MultiIndex.from_tuples(total_table.columns)
@@ -118,5 +138,4 @@ class BalanceSheetFetcher(StatsFetcher):
118
138
  target_index=setting['target_index']
119
139
  if "target_index" in setting.keys() else None)
120
140
 
121
- print(f"{name}: {return_dict[name].columns}")
122
141
  return return_dict
@@ -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
@@ -64,9 +65,14 @@ class CashFlowFetcher(StatsFetcher):
64
65
  return list(fetched_data)[0]
65
66
 
66
67
  def query_data(self):
67
- today = StatsDateTime.get_today()
68
-
69
- target_season = today.season - 1 if (today.season > 1) else 4
68
+
69
+ try:
70
+ latest_time = StatsDateTime.get_latest_time(self.ticker, self.collection)['last_update_time']
71
+ target_season = latest_time['seasonal_data']['latest_season']
72
+
73
+ except:
74
+ today = StatsDateTime.get_today()
75
+ target_season = today.season - 1 if (today.season > 1) else 4
70
76
 
71
77
  fetched_data = self.collect_data(target_season)
72
78
 
@@ -127,8 +133,9 @@ class CashFlowFetcher(StatsFetcher):
127
133
  'value']
128
134
  if (value['value']):
129
135
  table_dict[time_index][index_name][
130
- 'percentage'] = value['value'] / cash_flow[
131
- main_cash_flow_name]['value']
136
+ 'percentage'] = np.round(
137
+ (value['value'] / cash_flow[
138
+ main_cash_flow_name]['value']) * 100, 2)
132
139
  else:
133
140
  table_dict[time_index][index_name][
134
141
  'percentage'] = None
@@ -141,8 +148,9 @@ class CashFlowFetcher(StatsFetcher):
141
148
  'value']
142
149
  if (value['value']):
143
150
  table_dict[time_index][index_name][
144
- 'percentage'] = value['value'] / cash_flow[
145
- main_cash_flow_name]['value']
151
+ 'percentage'] = np.round(
152
+ (value['value'] / cash_flow[
153
+ main_cash_flow_name]['value']) * 100, 2)
146
154
  else:
147
155
  table_dict[time_index][index_name][
148
156
  'percentage'] = None
@@ -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
 
@@ -80,12 +83,20 @@ class FinanceOverviewFetcher(StatsFetcher):
80
83
  return fetched_data[0]
81
84
 
82
85
  def query_data(self):
83
- today = StatsDateTime.get_today()
84
86
 
85
- year = today.year - 1 if (today.season == 1) else today.year
86
- season = 4 if (today.season == 1) else today.season - 2
87
+ try:
88
+ latest_time = StatsDateTime.get_latest_time(
89
+ self.ticker, self.collection)['last_update_time']
90
+ year = latest_time['seasonal_data']['latest_year']
91
+ season = latest_time['seasonal_data']['latest_season']
92
+ except Exception as e:
93
+ today = StatsDateTime.get_today()
94
+ year = today.year - 1 if (today.season == 1) else today.year
95
+ season = 4 if (today.season == 1) else today.season - 1
96
+
87
97
  fetched_data = self.collect_data(year, season)
88
98
  finance_dict = fetched_data['seasonal_data'][0]
99
+ FinanceOverviewProcessor.process_rate(finance_dict)
89
100
  FinanceOverviewProcessor.process_all(finance_dict)
90
101
  fetched_data['seasonal_data'] = finance_dict
91
102
  return fetched_data
@@ -93,41 +104,38 @@ class FinanceOverviewFetcher(StatsFetcher):
93
104
 
94
105
  class FinanceOverviewProcessor(StatsProcessor):
95
106
 
107
+ @classmethod
108
+ def process_rate(cls, finance_dict):
109
+ for key in finance_dict:
110
+ if ('YoY' in key):
111
+ finance_dict[key] = StatsProcessor.cal_percentage(
112
+ finance_dict[key])
113
+ elif ("rate" in key or 'ratio' in key):
114
+ finance_dict[key] = StatsProcessor.cal_non_percentage(
115
+ finance_dict[key], to_str=True, postfix='%')
116
+ else:
117
+ finance_dict[key] = StatsProcessor.cal_non_percentage(
118
+ finance_dict[key])
119
+
96
120
  @classmethod
97
121
  def process_all(cls, finance_dict):
98
122
  methods = [
99
- cls.cal_EBIT,
100
- cls.cal_share_outstanding,
101
- cls.cal_fcf,
102
- cls.cal_revenue_per_share,
103
- cls.cal_gross_per_share,
104
- cls.cal_operating_income_per_share,
105
- cls.cal_operating_cash_flow_per_share,
106
- cls.fcf_per_share,
107
- cls.cal_roa,
108
- cls.cal_roe,
109
- cls.cal_gross_over_asset,
110
- cls.cal_roce,
111
- cls.cal_gross_profit_marginal,
112
- cls.cal_operation_profit_rate,
113
- cls.cal_operating_cash_flow_profit_rate,
114
- cls.cal_dso,
115
- cls.cal_account_receive_over_revenue,
116
- cls.cal_dpo,
117
- cls.cal_inventories_cycle_ratio,
118
- cls.cal_dio,
123
+ cls.cal_EBIT, cls.cal_share_outstanding, cls.cal_fcf,
124
+ cls.cal_interest_bearing_debt, cls.cal_revenue_per_share,
125
+ cls.cal_gross_per_share, cls.cal_operating_income_per_share,
126
+ cls.cal_operating_cash_flow_per_share, cls.fcf_per_share,
127
+ cls.cal_roa, cls.cal_roe, cls.cal_gross_over_asset, cls.cal_roce,
128
+ cls.cal_gross_profit_marginal, cls.cal_operation_profit_rate,
129
+ cls.cal_operating_cash_flow_profit_rate, cls.cal_dso,
130
+ cls.cal_account_receive_over_revenue, cls.cal_dpo,
131
+ cls.cal_inventories_cycle_ratio, cls.cal_dio,
119
132
  cls.cal_inventories_revenue_ratio,
120
- cls.cal_cash_of_conversion_cycle,
121
- cls.cal_asset_turnover,
122
- cls.cal_application_turnover,
123
- cls.cal_current_ratio,
124
- cls.cal_quick_ratio,
125
- cls.cal_debt_to_equity_ratio,
126
- cls.cal_net_debt_to_equity_ratio,
127
- cls.cal_interest_coverage_ratio,
133
+ cls.cal_cash_of_conversion_cycle, cls.cal_asset_turnover,
134
+ cls.cal_application_turnover, cls.cal_current_ratio,
135
+ cls.cal_quick_ratio, cls.cal_debt_to_equity_ratio,
136
+ cls.cal_net_debt_to_equity_ratio, cls.cal_interest_coverage_ratio,
128
137
  cls.cal_debt_to_operating_cash_flow,
129
- cls.cal_debt_to_free_cash_flow,
130
- cls.cal_cash_flow_ratio
138
+ cls.cal_debt_to_free_cash_flow, cls.cal_cash_flow_ratio
131
139
  ]
132
140
 
133
141
  for method in methods:
@@ -137,13 +145,14 @@ class FinanceOverviewProcessor(StatsProcessor):
137
145
  def cal_EBIT(cls, finance_dict):
138
146
  """
139
147
  計算EBIT
140
- EBIT = 營業收入 - 營業成本 - 營業費用
148
+ EBIT = 營業收入 - 營業成本 - 營業費用 - 所得稅費用
141
149
  """
142
150
  try:
143
- finance_dict['EBIT'] = (finance_dict['revenue'] -
144
- finance_dict['operating_cost'] -
145
- finance_dict['operating_expenses'])
146
- except (KeyError, TypeError) as e:
151
+ EBIT = (finance_dict['revenue'] - finance_dict['operating_cost'] -
152
+ finance_dict['operating_expenses'] -
153
+ finance_dict['tax_fee'])
154
+ finance_dict['EBIT'] = StatsProcessor.cal_non_percentage(EBIT)
155
+ except (KeyError, ZeroDivisionError, TypeError) as e:
147
156
  finance_dict['EBIT'] = None
148
157
  print(f"Error calculating EBIT: {e}")
149
158
 
@@ -154,12 +163,32 @@ class FinanceOverviewProcessor(StatsProcessor):
154
163
  自由現金流 = 營業現金流 + 投資現金流
155
164
  """
156
165
  try:
157
- finance_dict["fcf"] = (finance_dict["operating_cash_flow"] +
158
- finance_dict["financing_cash_flow"])
159
- except Exception as e:
166
+ fcf = (finance_dict["operating_cash_flow"] +
167
+ finance_dict["financing_cash_flow"])
168
+ finance_dict["fcf"] = StatsProcessor.cal_non_percentage(fcf)
169
+ except (KeyError, ZeroDivisionError, TypeError) as e:
160
170
  finance_dict['fcf'] = None
161
171
  print(f"Error calculating FCF: {e}")
162
172
 
173
+ @classmethod
174
+ def cal_interest_bearing_debt(cls, finance_dict):
175
+ """
176
+ 計算有息負債
177
+ 短期借款+長期借款
178
+ """
179
+ finance_dict['interest_bearing_debt'] = 0.0
180
+
181
+ try:
182
+ finance_dict['interest_bearing_debt'] += finance_dict[
183
+ 'short_term_liabilities']
184
+ except (KeyError, ZeroDivisionError, TypeError) as e:
185
+ finance_dict['interest_bearing_debt'] += 0.0
186
+ try:
187
+ finance_dict['interest_bearing_debt'] += finance_dict[
188
+ 'long_term_liabilities']
189
+ except (KeyError, ZeroDivisionError, TypeError) as e:
190
+ finance_dict['interest_bearing_debt'] += 0.0
191
+
163
192
  @classmethod
164
193
  def cal_share_outstanding(cls, finance_dict):
165
194
  """
@@ -169,7 +198,7 @@ class FinanceOverviewProcessor(StatsProcessor):
169
198
  try:
170
199
  finance_dict["share_outstanding"] = (finance_dict['net_income'] /
171
200
  finance_dict['eps'])
172
- except KeyError as e:
201
+ except (KeyError, ZeroDivisionError, TypeError) as e:
173
202
  finance_dict['share_outstanding'] = None
174
203
  print(f"share_outstanding failed because of {str(e)}")
175
204
 
@@ -180,9 +209,12 @@ class FinanceOverviewProcessor(StatsProcessor):
180
209
  每股營收 = 營業收入 / 在外流通股數
181
210
  """
182
211
  try:
183
- finance_dict['revenue_per_share'] = (
184
- finance_dict['revenue'] / finance_dict['share_outstanding'])
185
- except KeyError as e:
212
+ revenue_per_share = (finance_dict['revenue'] /
213
+ finance_dict['share_outstanding'])
214
+ finance_dict[
215
+ 'revenue_per_share'] = StatsProcessor.cal_non_percentage(
216
+ revenue_per_share, False)
217
+ except (KeyError, ZeroDivisionError, TypeError) as e:
186
218
  finance_dict['revenue_per_share'] = None
187
219
  print(f"revenue_per_share failed because of {str(e)}")
188
220
 
@@ -194,10 +226,13 @@ class FinanceOverviewProcessor(StatsProcessor):
194
226
  """
195
227
 
196
228
  try:
197
- finance_dict['gross_per_share'] = (
198
- finance_dict['gross_profit'] /
199
- finance_dict['share_outstanding'])
200
- except KeyError as e:
229
+ gross_per_share = (finance_dict['gross_profit'] /
230
+ finance_dict['share_outstanding'])
231
+ finance_dict[
232
+ 'gross_per_share'] = StatsProcessor.cal_non_percentage(
233
+ gross_per_share, False)
234
+
235
+ except (KeyError, ZeroDivisionError, TypeError) as e:
201
236
  finance_dict['gross_per_share'] = None
202
237
  print(f"gross_per_share failed because of {str(e)}")
203
238
 
@@ -208,10 +243,12 @@ class FinanceOverviewProcessor(StatsProcessor):
208
243
  每股營業利益= (當期營業利益)÷(當期在外流通股數)
209
244
  """
210
245
  try:
211
- finance_dict['operating_income_per_share'] = (
212
- finance_dict['operating_income'] /
213
- finance_dict['share_outstanding'])
214
- except KeyError as e:
246
+ operating_income_per_share = (finance_dict['operating_income'] /
247
+ finance_dict['share_outstanding'])
248
+ finance_dict[
249
+ 'operating_income_per_share'] = StatsProcessor.cal_non_percentage(
250
+ operating_income_per_share)
251
+ except (KeyError, ZeroDivisionError, TypeError) as e:
215
252
  finance_dict['operating_income_per_share'] = None
216
253
  print(f"operating_income_per_share failed because of {str(e)}")
217
254
 
@@ -222,10 +259,13 @@ class FinanceOverviewProcessor(StatsProcessor):
222
259
  = (當期營業現金流) ÷(當期在外流通股數)
223
260
  """
224
261
  try:
225
- finance_dict["operating_cash_flow_per_share"] = (
262
+ operating_cash_flow_per_share = (
226
263
  finance_dict["operating_cash_flow"] /
227
264
  finance_dict['share_outstanding'])
228
- except KeyError as e:
265
+ finance_dict[
266
+ "operating_cash_flow_per_share"] = StatsProcessor.cal_non_percentage(
267
+ operating_cash_flow_per_share)
268
+ except (KeyError, ZeroDivisionError, TypeError) as e:
229
269
  finance_dict['operating_cash_flow_per_share'] = None
230
270
  print(f'operating_cash_flow_per_share because of {str(e)}')
231
271
 
@@ -236,9 +276,11 @@ class FinanceOverviewProcessor(StatsProcessor):
236
276
  每股自由現金流 = (當期自由現金流) ÷(當期在外流通股數)
237
277
  """
238
278
  try:
239
- finance_dict['fcf_per_share'] = (finance_dict['fcf'] /
240
- finance_dict['share_outstanding'])
241
- except KeyError as e:
279
+ fcf_per_share = (finance_dict['fcf'] /
280
+ finance_dict['share_outstanding'])
281
+ finance_dict['fcf_per_share'] = StatsProcessor.cal_non_percentage(
282
+ fcf_per_share)
283
+ except (KeyError, ZeroDivisionError, TypeError) as e:
242
284
  finance_dict['fcf_per_share'] = None
243
285
  print(f"fcf_per_share failed because of {str(e)}")
244
286
 
@@ -250,27 +292,35 @@ class FinanceOverviewProcessor(StatsProcessor):
250
292
  計算資產報酬率(ROA)
251
293
  ROA = [ 本期淨利 + 利息費用 × (1-有效稅率) ] ÷(資產總額)
252
294
  """
253
- finance_dict["roa"] = (
295
+ roa = (
254
296
  finance_dict['net_income'] + finance_dict['interest'] +
255
297
  (1 * 0.1) # 有效稅率需要改,這裡先設0.1
256
298
  ) / finance_dict['inventories']
257
299
 
300
+ finance_dict["roa"] = StatsProcessor.cal_percentage(roa)
301
+
258
302
  @classmethod
259
303
  def cal_roe(cls, finance_dict):
260
304
  """
261
305
  計算股東權益報酬率(ROE)
262
306
  ROE = (本期淨利) ÷(權益總額)
263
307
  """
264
- finance_dict['roe'] = (finance_dict['net_income'] /
265
- finance_dict['equity'])
308
+ roe = (finance_dict['net_income'] / finance_dict['equity'])
309
+ finance_dict['roe'] = StatsProcessor.cal_percentage(roe)
266
310
 
267
311
  @classmethod
268
312
  def cal_gross_over_asset(cls, finance_dict):
269
313
  """
270
314
  計算營業毛利/總資產
271
315
  """
272
- finance_dict['gross_over_asset'] = (finance_dict['gross_profit'] /
273
- finance_dict['total_asset'])
316
+ try:
317
+ gross_over_asset = (finance_dict['gross_profit'] /
318
+ finance_dict['total_asset'])
319
+ finance_dict['gross_over_asset'] = StatsProcessor.cal_percentage(
320
+ gross_over_asset)
321
+ except (KeyError, ZeroDivisionError, TypeError) as e:
322
+ finance_dict['gross_over_asset'] = None
323
+ print(f"營業毛利/總資產 failed because of {str(e)}")
274
324
 
275
325
  @classmethod
276
326
  def cal_roce(cls, finance_dict):
@@ -279,11 +329,13 @@ class FinanceOverviewProcessor(StatsProcessor):
279
329
  ROCE = (稅前淨利+利息費用) / (資產總額-流動負債)
280
330
  """
281
331
  try:
282
- finance_dict['roce'] = (
283
- (finance_dict['net_income_before_tax'] +
284
- finance_dict['interest']) /
285
- (finance_dict['asset'] - finance_dict['current_liabilities']))
286
- except KeyError as e:
332
+ roce = ((finance_dict['net_income_before_tax'] +
333
+ finance_dict['interest']) /
334
+ (finance_dict['total_asset'] -
335
+ finance_dict['current_liabilities']))
336
+ finance_dict['roce'] = StatsProcessor.cal_percentage(roce)
337
+
338
+ except (KeyError, ZeroDivisionError, TypeError) as e:
287
339
  finance_dict['roce'] = None
288
340
  print(f"ROCE failed because of {str(e)}")
289
341
 
@@ -294,8 +346,11 @@ class FinanceOverviewProcessor(StatsProcessor):
294
346
  營業毛利率 = 營業毛利 ÷ 營業收入
295
347
  """
296
348
  try:
297
- finance_dict['gross_profit_margin'] = (
298
- finance_dict['gross_profit'] / finance_dict['revenue'])
349
+ gross_profit_margin = (finance_dict['gross_profit'] /
350
+ finance_dict['revenue'])
351
+ finance_dict[
352
+ 'gross_profit_margin'] = StatsProcessor.cal_percentage(
353
+ gross_profit_margin)
299
354
  except:
300
355
  finance_dict['gross_profit_margin'] = None
301
356
  print(f"gross_profit_margin failed because of {str(e)}")
@@ -307,10 +362,13 @@ class FinanceOverviewProcessor(StatsProcessor):
307
362
  營業利益率 = ( 營業收入-營業成本-營業費用)÷ 營業收入
308
363
  """
309
364
  try:
310
- finance_dict["operation_profit_rate"] = (
365
+ operation_profit_rate = (
311
366
  finance_dict['revenue'] - finance_dict['operating_cost'] -
312
- finance_dict['operating_price']) / finance_dict['revenue']
313
- except KeyError as e:
367
+ finance_dict['operating_expenses']) / finance_dict['revenue']
368
+ finance_dict[
369
+ "operation_profit_rate"] = StatsProcessor.cal_percentage(
370
+ operation_profit_rate)
371
+ except (KeyError, ZeroDivisionError, TypeError) as e:
314
372
  finance_dict["operation_profit_rate"] = None
315
373
  print(f"operation_profit failed because of {str(e)}")
316
374
 
@@ -321,11 +379,13 @@ class FinanceOverviewProcessor(StatsProcessor):
321
379
  營業現金流利潤率 = 營業活動現金流 ÷ 營業收入
322
380
  """
323
381
  try:
324
- finance_dict["operating_cash_flow_profit_rate"] = (
382
+ operating_cash_flow_profit_rate = (
325
383
  finance_dict["operating_cash_flow"] / finance_dict["revenue"])
326
- except KeyError:
384
+ finance_dict[
385
+ "operating_cash_flow_profit_rate"] = StatsProcessor.cal_percentage(
386
+ operating_cash_flow_profit_rate)
387
+ except (KeyError, ZeroDivisionError, TypeError) as e:
327
388
  finance_dict["operating_cash_flow_profit_rate"] = None
328
-
329
389
  print(
330
390
  f"operating_cash_flow_profit_rate failed because of {str(e)}")
331
391
 
@@ -342,10 +402,16 @@ class FinanceOverviewProcessor(StatsProcessor):
342
402
  def cal_dso(cls, finance_dict):
343
403
  """
344
404
  計算應收帳款收現天數(DSO)
345
- DSO = 365 × (營業收入 ÷ 應收帳款平均餘額)
405
+ DSO = 365 × (應收帳款平均餘額 ÷ 營業收入)
346
406
  """
347
- finance_dict['dso'] = (
348
- 365 * (finance_dict['revenue'] / finance_dict['account_pay']))
407
+ try:
408
+ dso = (365 *
409
+ (finance_dict['account_pay'] / finance_dict['revenue']))
410
+ finance_dict['dso'] = StatsProcessor.cal_non_percentage(
411
+ dso, to_str=True, postfix="日")
412
+ except:
413
+ finance_dict['dso'] = None
414
+ print(f"Error calculating 應收帳款收現天數 because of {str(e)}")
349
415
 
350
416
  @classmethod
351
417
  def cal_account_receive_over_revenue(cls, finance_dict):
@@ -353,8 +419,11 @@ class FinanceOverviewProcessor(StatsProcessor):
353
419
  計算應收帳款佔營收比率
354
420
  = 應收帳款平均餘額 ÷ 營業收入
355
421
  """
356
- finance_dict["account_receive_over_revenue"] = (
357
- finance_dict['account_receive'] / finance_dict['revenue'])
422
+ account_receive_over_revenue = (finance_dict['account_receive'] /
423
+ finance_dict['revenue'])
424
+ finance_dict[
425
+ "account_receive_over_revenue"] = StatsProcessor.cal_percentage(
426
+ account_receive_over_revenue)
358
427
 
359
428
  @classmethod
360
429
  def cal_dpo(cls, finance_dict):
@@ -362,9 +431,15 @@ class FinanceOverviewProcessor(StatsProcessor):
362
431
  計算應付帳款週轉天數
363
432
  DPO = 365天 ÷ (銷貨成本÷平均應付帳款)
364
433
  """
365
- finance_dict["dpo"] = (
366
- 365 *
367
- (finance_dict['operating_cost'] / finance_dict['account_pay']))
434
+ try:
435
+ dpo = (
436
+ 365 *
437
+ (finance_dict['account_pay'] / finance_dict['operating_cost']))
438
+ finance_dict["dpo"] = StatsProcessor.cal_non_percentage(
439
+ dpo, to_str=True, postfix="日")
440
+ except (KeyError, ZeroDivisionError, TypeError) as e:
441
+ finance_dict["dpo"] = None
442
+ print(f"應付帳款週轉天數 failed because of {str(e)}")
368
443
 
369
444
  @classmethod
370
445
  def cal_inventories_cycle_ratio(cls, finance_dict):
@@ -372,19 +447,32 @@ class FinanceOverviewProcessor(StatsProcessor):
372
447
  計算存貨周轉率
373
448
  = 銷貨成本 ÷ 存貨
374
449
  """
450
+ try:
451
+ inventories_cycle_ratio = (finance_dict['operating_cost'] /
452
+ finance_dict['inventories'])
375
453
 
376
- finance_dict["inventories_cycle_ratio"] = (
377
- finance_dict['operating_cost'] / finance_dict['inventories'])
454
+ finance_dict[
455
+ "inventories_cycle_ratio"] = StatsProcessor.cal_percentage(
456
+ inventories_cycle_ratio)
457
+ except (KeyError, ZeroDivisionError, TypeError) as e:
458
+ finance_dict["inventories_cycle_ratio"] = None
459
+ print(f"Error calculating 存貨周轉率 because of {str(e)}")
378
460
 
379
461
  @classmethod
380
462
  def cal_dio(cls, finance_dict):
381
463
  """
382
- 計算 存貨週轉天數
383
- DIO = 365天 ÷ (銷貨成本 ÷ 存貨)
384
- MUDA MUDA MUDA MUDA !!!
464
+ 計算 存貨週轉天數 or 平均售貨天數
465
+ DIO = 365天 * (存貨 ÷ 銷貨成本)
466
+ MUDA MUDA MUDA !!!
385
467
  """
386
- finance_dict["dio"] = (finance_dict["operating_cost"] /
387
- finance_dict["inventories"])
468
+ try:
469
+ dio = 365 * (finance_dict["inventories"] /
470
+ finance_dict["operating_cost"])
471
+ finance_dict["dio"] = StatsProcessor.cal_non_percentage(
472
+ dio, to_str=True, postfix="日")
473
+ except (KeyError, ZeroDivisionError, TypeError) as e:
474
+ finance_dict["dio"] = None
475
+ print(f"Error calculating 存貨週轉天數 because of {str(e)}")
388
476
 
389
477
  @classmethod
390
478
  def cal_inventories_revenue_ratio(cls, finance_dict):
@@ -392,8 +480,16 @@ class FinanceOverviewProcessor(StatsProcessor):
392
480
  計算存貨佔營收比率
393
481
  存貨佔營收比= 存貨 ÷ 營業收入
394
482
  """
395
- finance_dict["inventories_revenue_ratio"] = (
396
- finance_dict['inventories'] / finance_dict['revenue'])
483
+ try:
484
+ inventories_revenue_ratio = (finance_dict['inventories'] /
485
+ finance_dict['revenue'])
486
+
487
+ finance_dict[
488
+ "inventories_revenue_ratio"] = StatsProcessor.cal_percentage(
489
+ inventories_revenue_ratio)
490
+ except (KeyError, ZeroDivisionError, TypeError) as e:
491
+ finance_dict["inventories_revenue_ratio"] = None
492
+ print(f"Error calculating 存貨佔營收比率 because of {str(e)}")
397
493
 
398
494
  @classmethod
399
495
  def cal_cash_of_conversion_cycle(cls, finance_dict):
@@ -401,19 +497,42 @@ class FinanceOverviewProcessor(StatsProcessor):
401
497
  計算現金循環週期
402
498
  存貨週轉天數 + 應收帳款週轉天數 - 應付帳款週轉天數
403
499
  """
404
- finance_dict["cash_of_conversion_cycle"] = (finance_dict["dio"] +
405
- finance_dict["dso"] -
406
- finance_dict['dpo'])
500
+ try:
501
+ cash_of_conversion_cycle = (finance_dict["dio"] +
502
+ finance_dict["dso"] -
503
+ finance_dict['dpo'])
504
+ finance_dict[
505
+ "cash_of_conversion_cycle"] = StatsProcessor.cal_non_percentage(
506
+ cash_of_conversion_cycle, to_str=True, postfix="日")
507
+ except (KeyError, ZeroDivisionError, TypeError) as e:
508
+ finance_dict["cash_of_conversion_cycle"] = None
407
509
 
408
510
  @classmethod
409
511
  def cal_asset_turnover(cls, finance_dict):
410
- finance_dict["asset_turnover"] = (finance_dict["revenue"] /
411
- finance_dict["inventories"])
512
+ """
513
+ 計算資產周轉率
514
+ 營業收入 ÷ 資產總額
515
+ """
516
+ asset_turnover = (finance_dict["revenue"] /
517
+ finance_dict["inventories"])
518
+ finance_dict["asset_turnover"] = StatsProcessor.cal_percentage(
519
+ asset_turnover)
412
520
 
413
521
  @classmethod
414
522
  def cal_application_turnover(cls, finance_dict):
415
- finance_dict['applcation_turnover'] = (finance_dict['revenue'] /
416
- finance_dict["application"])
523
+ """
524
+ 不動產、廠房及設備週轉率
525
+ 營業收入 ÷ 不動產、廠房與設備平均餘額
526
+ """
527
+ try:
528
+ applcation_turnover = (finance_dict['revenue'] /
529
+ finance_dict["application"])
530
+ finance_dict[
531
+ 'applcation_turnover'] = StatsProcessor.cal_percentage(
532
+ applcation_turnover)
533
+
534
+ except (KeyError, ZeroDivisionError, TypeError) as e:
535
+ finance_dict['application_turnover'] = None
417
536
 
418
537
  @classmethod
419
538
  def cal_current_ratio(cls, finance_dict):
@@ -421,81 +540,117 @@ class FinanceOverviewProcessor(StatsProcessor):
421
540
  計算流動比率 = 流動資產 / 流動負債
422
541
  """
423
542
  try:
424
- finance_dict['current_ratio'] = finance_dict[
425
- 'current_assets'] / finance_dict['current_liabilities']
543
+ current_ratio = (finance_dict['current_assets'] /
544
+ finance_dict['current_liabilities'])
545
+ finance_dict['current_ratio'] = StatsProcessor.cal_percentage(
546
+ current_ratio)
426
547
  except (KeyError, ZeroDivisionError, TypeError) as e:
427
548
  finance_dict['current_ratio'] = None
428
549
  print(f"Error calculating current ratio: {e}")
429
550
 
430
551
  @classmethod
431
552
  def cal_quick_ratio(cls, finance_dict):
553
+ """
554
+ 速動比率
555
+ (流動資產 - 存貨) / 流動負債
556
+ """
432
557
  try:
433
- # 速動比率 = (流動資產 - 存貨) / 流動負債
434
- finance_dict['quick_ratio'] = (
435
- finance_dict['current_assets'] - finance_dict['inventories']
436
- ) / finance_dict['current_liabilities']
558
+ quick_ratio = (finance_dict['current_assets'] -
559
+ finance_dict['inventories']
560
+ ) / finance_dict['current_liabilities']
561
+ finance_dict['quick_ratio'] = StatsProcessor.cal_percentage(
562
+ quick_ratio)
437
563
  except (KeyError, ZeroDivisionError, TypeError) as e:
438
564
  finance_dict['quick_ratio'] = None
439
565
  print(f"Error calculating quick ratio: {e}")
440
566
 
441
567
  @classmethod
442
568
  def cal_debt_to_equity_ratio(cls, finance_dict):
569
+ """
570
+ # 負債權益比率 = 總負債 / 股東權益
571
+ """
443
572
  try:
444
- # 負債權益比率 = 總負債 / 股東權益
445
- finance_dict['debt_to_equity_ratio'] = finance_dict[
573
+ debt_to_equity_ratio = finance_dict[
446
574
  'total_liabilities'] / finance_dict['equity']
575
+ finance_dict[
576
+ 'debt_to_equity_ratio'] = StatsProcessor.cal_percentage(
577
+ debt_to_equity_ratio)
447
578
  except (KeyError, ZeroDivisionError, TypeError) as e:
448
579
  finance_dict['debt_to_equity_ratio'] = None
449
580
  print(f"Error calculating debt to equity ratio: {e}")
450
581
 
451
582
  @classmethod
452
583
  def cal_net_debt_to_equity_ratio(cls, finance_dict):
584
+ """
585
+ # 淨負債權益比率 = (總負債 - 現金及約當現金) / 股東權益
586
+ """
453
587
  try:
454
- # 淨負債權益比率 = (總負債 - 現金及約當現金) / 股東權益
455
- finance_dict['net_debt_to_equity_ratio'] = (
588
+ net_debt_to_equity_ratio = (
456
589
  finance_dict['total_liabilities'] -
457
590
  finance_dict['cash_and_cash_equivalents']
458
591
  ) / finance_dict['equity']
592
+ finance_dict[
593
+ 'net_debt_to_equity_ratio'] = StatsProcessor.cal_percentage(
594
+ net_debt_to_equity_ratio)
459
595
  except (KeyError, ZeroDivisionError, TypeError) as e:
460
596
  finance_dict['net_debt_to_equity_ratio'] = None
461
597
  print(f"Error calculating net debt to equity ratio: {e}")
462
598
 
463
599
  @classmethod
464
600
  def cal_interest_coverage_ratio(cls, finance_dict):
601
+ """
602
+ # 利息保障倍數 = EBIT / 利息費用
603
+ """
465
604
  try:
466
- # 利息保障倍數 = EBIT / 利息費用
467
- finance_dict['interest_coverage_ratio'] = finance_dict[
468
- 'EBIT'] / finance_dict['interest_expense']
605
+ interest_coverage_ratio = finance_dict['EBIT'] / finance_dict[
606
+ 'interest_expense']
607
+ finance_dict[
608
+ 'interest_coverage_ratio'] = StatsProcessor.cal_non_percentage(
609
+ interest_coverage_ratio, to_str=True, postfix="倍")
469
610
  except (KeyError, ZeroDivisionError, TypeError) as e:
470
611
  finance_dict['interest_coverage_ratio'] = None
471
612
  print(f"Error calculating interest coverage ratio: {e}")
472
613
 
473
614
  @classmethod
474
615
  def cal_debt_to_operating_cash_flow(cls, finance_dict):
616
+ """
617
+ 有息負債 / 營業活動現金流
618
+ """
475
619
  try:
476
- # 有息負債 / 營業活動現金流
477
- finance_dict['debt_to_operating_cash_flow'] = finance_dict[
620
+ debt_to_operating_cash_flow = finance_dict[
478
621
  'interest_bearing_debt'] / finance_dict['operating_cash_flow']
622
+ finance_dict[
623
+ 'debt_to_operating_cash_flow'] = StatsProcessor.cal_percentage(
624
+ debt_to_operating_cash_flow)
479
625
  except (KeyError, ZeroDivisionError, TypeError) as e:
480
626
  finance_dict['debt_to_operating_cash_flow'] = None
481
627
  print(f"Error calculating debt to operating cash flow: {e}")
482
628
 
483
629
  @classmethod
484
630
  def cal_debt_to_free_cash_flow(cls, finance_dict):
631
+ """
632
+ # 有息負債 / 自由現金流
633
+ """
485
634
  try:
486
- # 有息負債 / 自由現金流
487
- finance_dict['debt_to_free_cash_flow'] = finance_dict[
635
+ debt_to_free_cash_flow = finance_dict[
488
636
  'interest_bearing_debt'] / finance_dict['fcf']
637
+ finance_dict[
638
+ 'debt_to_free_cash_flow'] = StatsProcessor.cal_percentage(
639
+ debt_to_free_cash_flow)
489
640
  except (KeyError, ZeroDivisionError, TypeError) as e:
490
641
  finance_dict['debt_to_free_cash_flow'] = None
491
642
  print(f"Error calculating debt to free cash flow: {e}")
492
643
 
493
644
  @classmethod
494
645
  def cal_cash_flow_ratio(cls, finance_dict):
646
+ """
647
+ # 現金流量比率 = 營業活動現金流 / 流動負債
648
+ """
495
649
  try:
496
- # 現金流量比率 = 營業活動現金流 / 流動負債
497
- finance_dict['cash_flow_ratio'] = finance_dict[
650
+ cash_flow_ratio = finance_dict[
498
651
  'operating_cash_flow'] / finance_dict['current_liabilities']
652
+ finance_dict['cash_flow_ratio'] = StatsProcessor.cal_percentage(
653
+ cash_flow_ratio)
499
654
  except (KeyError, ZeroDivisionError, TypeError) as e:
500
655
  finance_dict['cash_flow_ratio'] = None
501
656
  print(f"Error calculating cash flow ratio: {e}")
@@ -46,9 +46,15 @@ class MonthRevenueFetcher(StatsFetcher):
46
46
  return fetched_data[-1]
47
47
 
48
48
  def query_data(self):
49
- today = StatsDateTime.get_today()
50
- target_month = today.month
51
- target_year = today.year
49
+ try:
50
+ latest_time = StatsDateTime.get_latest_time(
51
+ self.ticker, self.collection)['last_update_time']
52
+ target_year = latest_time['monthly_data']['latest_year']
53
+ target_month = latest_time['monthly_data']['latest_month']
54
+ except Exception as e:
55
+ today = StatsDateTime.get_today()
56
+ target_month = today.month
57
+ target_year = today.year
52
58
 
53
59
  # Query data
54
60
  fetched_data = self.collect_data(target_year, target_month)
@@ -1,11 +1,13 @@
1
1
  from .base import StatsFetcher, StatsDateTime
2
+ import importlib.resources as pkg_resources
2
3
  import json
4
+ import numpy as np
3
5
  import pandas as pd
4
6
  from ..utils import StatsDateTime, StatsProcessor
5
- import importlib.resources as pkg_resources
6
7
  import yaml
7
8
 
8
9
 
10
+
9
11
  class ProfitLoseFetcher(StatsFetcher):
10
12
  """
11
13
  iFa.ai: 財務分析 -> 損益表
@@ -73,10 +75,15 @@ class ProfitLoseFetcher(StatsFetcher):
73
75
  return list(fetched_data)[-1]
74
76
 
75
77
  def query_data(self):
76
- today = StatsDateTime.get_today()
78
+ try:
79
+ latest_time = StatsDateTime.get_latest_time(
80
+ self.ticker, self.collection)['last_update_time']
81
+ target_season = latest_time['seasonal_data']['latest_season']
82
+ except Exception as e:
83
+ today = StatsDateTime.get_today()
77
84
 
78
- target_season = today.season
79
- target_season = target_season - 1 if target_season > 1 else 4
85
+ target_season = today.season
86
+ target_season = target_season - 1 if target_season > 1 else 4
80
87
 
81
88
  fetched_data = self.collect_data(target_season)
82
89
 
@@ -108,6 +115,12 @@ class ProfitLoseFetcher(StatsFetcher):
108
115
  for index_name, value_dict in profit_lose.items():
109
116
  # (2020Q1, 項目, 金額或%)
110
117
  for item_name, item in value_dict.items():
118
+ if (item_name == 'percentage'):
119
+ if (isinstance(item, (float, int))):
120
+ item = np.round(item, 2)
121
+ if ('YoY' in item_name):
122
+ if (isinstance(item, (float, int))):
123
+ item = np.round(item * 100, 2)
111
124
  try:
112
125
  table_dict[index_name][(time_index, item_name)] = item
113
126
 
@@ -121,6 +134,8 @@ class ProfitLoseFetcher(StatsFetcher):
121
134
  total_table = pd.DataFrame.from_dict(table_dict, orient='index')
122
135
  total_table.columns = pd.MultiIndex.from_tuples(total_table.columns)
123
136
 
137
+ total_table = total_table.replace("N/A", None)
138
+
124
139
  for name, setting in self.table_settings.items():
125
140
  return_dict[name] = StatsProcessor.slice_multi_col_table(
126
141
  total_table=total_table,
@@ -54,11 +54,20 @@ class ValueFetcher(StatsFetcher):
54
54
  return pipeline
55
55
 
56
56
  def query_data(self):
57
- today = StatsDateTime.get_today()
58
-
59
- this_year = today.year - 1911
60
- start_date = (today.date - timedelta(days=31))
61
- end_date = today.date
57
+ try:
58
+ latest_time = StatsDateTime.get_latest_time(
59
+ self.ticker, self.collection)['last_update_time']
60
+ target_year = latest_time['daily_data']['last_update'].year
61
+ start_date = latest_time['daily_data']['last_update'] - timedelta(days=31)
62
+ end_date = latest_time['daily_data']['last_update']
63
+
64
+ except Exception as e:
65
+ today = StatsDateTime.get_today()
66
+ target_year = today.year
67
+ start_date = (today.date - timedelta(days=31))
68
+ end_date = today.date
69
+
70
+ this_year = target_year - 1911
62
71
 
63
72
  fetched_data = self.collect_data(start_date, end_date)
64
73
 
@@ -15,22 +15,22 @@ net_income:
15
15
  field: 本期淨利(淨損)
16
16
  value: value
17
17
 
18
+ tax_fee:
19
+ field: 所得稅費用(利益)合計
20
+ value: value
21
+
18
22
  # TODO: 以下所爬到的資料都是累計的,Ifa有額外計算當季的變化量
19
23
  operating_cash_flow:
20
24
  field: 營業活動之淨現金流入(流出)
21
- value: value
25
+ value: single_season_value
22
26
 
23
27
  invest_cash_flow:
24
28
  field: 投資活動之淨現金流入(流出)
25
- value: value
29
+ value: single_season_value
26
30
 
27
31
  financing_cash_flow:
28
32
  field: 籌資活動之淨現金流入(流出)
29
- value: value
30
-
31
- fcf:
32
- field: 本期現金及約當現金增加(減少)數
33
- value: value
33
+ value: single_season_value
34
34
  # ^^^ 以上皆需要額外在DataBase處理
35
35
 
36
36
  # 每股財務狀況
@@ -84,7 +84,7 @@ net_income_YoY:
84
84
 
85
85
  operating_cash_flow_YoY:
86
86
  field: 營業活動之淨現金流入(流出)
87
- value: YoY_1
87
+ value: single_season_YoY
88
88
 
89
89
  # operating_cash_flow_per_share_YoY:
90
90
  # field: 每股營業現金流年成長率
@@ -123,6 +123,13 @@ total_liabilities:
123
123
  field: 負債總額
124
124
  value: value
125
125
 
126
+ short_term_liabilities:
127
+ field: 短期借款
128
+ value: value
129
+
130
+ long_term_liabilities:
131
+ field: 長期借款
132
+ value: value
126
133
  #
127
134
  cash_and_cash_equivalents:
128
135
  field: 現金及約當現金
@@ -23,6 +23,7 @@
23
23
  "非流動資產合計": "balance_sheet",
24
24
  "資產總額": "balance_sheet",
25
25
  "短期借款": "balance_sheet",
26
+ "長期借款": "balance_sheet",
26
27
  "透過損益按公允價值衡量之金融負債-流動": "balance_sheet",
27
28
  "應付票據": "balance_sheet",
28
29
  "應付帳款": "balance_sheet",
@@ -1,5 +1,6 @@
1
1
  from importlib.resources import files
2
2
  import json
3
+ import numpy as np
3
4
  import pandas as pd
4
5
  import yaml
5
6
 
@@ -117,8 +118,9 @@ class StatsProcessor:
117
118
  sliced_table = sliced_table.pivot(index='level_1',
118
119
  columns='level_0',
119
120
  values=target_index).sort_index(
120
- axis=1, level = 1,ascending = False
121
- )
121
+ axis=1,
122
+ level=1,
123
+ ascending=False)
122
124
 
123
125
  sliced_table.columns = sliced_table.columns.get_level_values(1)
124
126
  sliced_table.columns.name = None
@@ -136,3 +138,27 @@ class StatsProcessor:
136
138
  ]
137
139
  return return_table
138
140
 
141
+ @classmethod
142
+ def cal_percentage(cls, value, postfix="%"):
143
+ if (isinstance(value, (float, int))):
144
+ value = np.round(value * 100 , 2).item()
145
+ value = f"{value:.2f}{postfix}"
146
+
147
+ return value
148
+
149
+ else:
150
+ return value
151
+
152
+ @classmethod
153
+ def cal_non_percentage(cls, value, to_str=False, postfix="元"):
154
+ if (isinstance(value, (float, int))):
155
+ value = np.round(value, 2).item()
156
+ if (to_str):
157
+ value = f"{value:.2f}{postfix}"
158
+ return value
159
+
160
+ else:
161
+ return value
162
+
163
+ else:
164
+ return value
@@ -19,3 +19,11 @@ class StatsDateTime():
19
19
 
20
20
  return StatsDateTime(today, this_year, this_month, this_day,
21
21
  this_season)
22
+
23
+ @classmethod
24
+ def get_latest_time(cls, ticker, collection):
25
+ return collection.find_one(
26
+ { "ticker" : ticker },
27
+ { "_id": 0, "last_update_time": 1 }
28
+ )
29
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: neurostats-API
3
- Version: 0.0.7
3
+ Version: 0.0.9
4
4
  Summary: The service of NeuroStats website
5
5
  Home-page: https://github.com/NeurowattStats/NeuroStats_API.git
6
6
  Author: JasonWang@Neurowatt
@@ -78,7 +78,7 @@ pip install neurostats-API
78
78
  ```Python
79
79
  >>> import neurostats_API
80
80
  >>> print(neurostats_API.__version__)
81
- 0.0.6
81
+ 0.0.9
82
82
  ```
83
83
 
84
84
  ### 得到最新一期的評價資料與歷年評價
@@ -379,11 +379,12 @@ stats_fetcher.query_data()
379
379
 
380
380
  ### 現金流量表
381
381
  ``` Python
382
- from neurostats_API.utils import StatsFetcher, DBClient
382
+ from neurostats_API.fetchers import CashFlowFetcher
383
383
  db_client = DBClient("<連接的DB位置>").get_client()
384
- fetcher = StatsFetcher(db_client)
385
384
  ticker = 2330 # 換成tw50內任意ticker
386
- stats_fetcher.get_cash_flow(ticker)
385
+ fetcher = StatsFetcher(ticker, db_client)
386
+
387
+ stats_fetcher.query()
387
388
  ```
388
389
  #### 回傳
389
390
  ```Python
@@ -0,0 +1,26 @@
1
+ neurostats_API/__init__.py,sha256=9_jSwg7P5SlFv0Ci2ZSYBcAbygp9XV2C8sryRO8tvko,19
2
+ neurostats_API/cli.py,sha256=UJSWLIw03P24p-gkBb6JSEI5dW5U12UvLf1L8HjQD-o,873
3
+ neurostats_API/main.py,sha256=QcsfmWivg2Dnqw3MTJWiI0QvEiRs0VuH-BjwQHFCv00,677
4
+ neurostats_API/fetchers/__init__.py,sha256=U_OMG-mLpsVKYnCBrW2OjFuCzvPeVQ__7A676vGzztY,313
5
+ neurostats_API/fetchers/balance_sheet.py,sha256=VeWhd8Z2XZnL5RzxmenLzAd4eyK2sWTuiRGkqWsEmzk,5219
6
+ neurostats_API/fetchers/base.py,sha256=NW2SFzrimyAIrdJx1LVmTazelyZOAtcj54kJKHc4Vaw,1662
7
+ neurostats_API/fetchers/cash_flow.py,sha256=4G4SIUoBSwT-BePmz-SprQ0IJRL2QNWqWdQtlgaRKd4,7371
8
+ neurostats_API/fetchers/finance_overview.py,sha256=EVP7k0JkQq3ydXy0f3t2kzy12iIQEwDniTLn98qZ460,25637
9
+ neurostats_API/fetchers/month_revenue.py,sha256=QmhMAO8jbkjg2R1LR0TAPE3bmDnyuLNjnD24ZsFkTBU,3501
10
+ neurostats_API/fetchers/profit_lose.py,sha256=C0y42RBA-s20XcG6CJ10Rt6Gm_rB6lcvBmIzbTpn64o,5123
11
+ neurostats_API/fetchers/tech.py,sha256=wH1kkqiETQhF0HAhk-UIiucnZ3EiL85Q-yMWCcVOiFM,11395
12
+ neurostats_API/fetchers/value_invest.py,sha256=O5IKC8Nl7p5-E-1zoyAyWtiDznaxNemeabanmaHDdJs,3327
13
+ neurostats_API/tools/balance_sheet.yaml,sha256=dKTMbsYR9EFp48WAzmm_ISHMiJQLyE0V-XWS_gkxmr0,541
14
+ neurostats_API/tools/cash_flow_percentage.yaml,sha256=fk2Z4eb1JjGFvP134eJatHacB7BgTkBenhDJr83w8RE,1345
15
+ neurostats_API/tools/finance_overview_dict.yaml,sha256=URL1IFqO0j5uOwN3xETHriy_u9lYbLvdwghuznenP2Q,2500
16
+ neurostats_API/tools/profit_lose.yaml,sha256=qHBnqG7fR4Pxc_c3n4raL-3l7o5RnABLz9YGOXoaGiA,2086
17
+ neurostats_API/tools/seasonal_data_field_dict.txt,sha256=Za1fJR1yERbqrX8TgsS2kmMYMbaye43Gu_5ukUNBCNM,7904
18
+ neurostats_API/utils/__init__.py,sha256=FTYKRFzW2XVXdnSHXnS3mQQaHlKF9xGqrMsgZZ2kroc,142
19
+ neurostats_API/utils/data_process.py,sha256=m1B4EhCNSzOMfTBDtYCjkQSjbDTAEFC6TNf3NNxV36k,5657
20
+ neurostats_API/utils/datetime.py,sha256=XJya4G8b_-ZOaBbMXgQjWh2MC4wc-o6goQ7EQJQMWrQ,773
21
+ neurostats_API/utils/db_client.py,sha256=OYe6yazcR4Aa6jYmy47JrryUeh2NnKGqY2K_lSZe6i8,455
22
+ neurostats_API/utils/fetcher.py,sha256=VbrUhjA-GG5AyjPX2SHtFIbZM4dm3jo0RgZzuCbb_Io,40927
23
+ neurostats_API-0.0.9.dist-info/METADATA,sha256=z--BAc0e6HHBuXSQgc5ikwjPFzTfe-2o02gFLmgY_do,18232
24
+ neurostats_API-0.0.9.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
25
+ neurostats_API-0.0.9.dist-info/top_level.txt,sha256=nSlQPMG0VtXivJyedp4Bkf86EOy2TpW10VGxolXrqnU,15
26
+ neurostats_API-0.0.9.dist-info/RECORD,,
@@ -1,26 +0,0 @@
1
- neurostats_API/__init__.py,sha256=3Kn8sHWnxjlagph2LmftcF8JLlcMlmQIbU5t_jzgK3w,19
2
- neurostats_API/cli.py,sha256=UJSWLIw03P24p-gkBb6JSEI5dW5U12UvLf1L8HjQD-o,873
3
- neurostats_API/main.py,sha256=QcsfmWivg2Dnqw3MTJWiI0QvEiRs0VuH-BjwQHFCv00,677
4
- neurostats_API/fetchers/__init__.py,sha256=U_OMG-mLpsVKYnCBrW2OjFuCzvPeVQ__7A676vGzztY,313
5
- neurostats_API/fetchers/balance_sheet.py,sha256=FPsVobaNzFOxpXCo1Ui_rPmlG1crTRj9ukqQ4J8aiJg,4268
6
- neurostats_API/fetchers/base.py,sha256=NW2SFzrimyAIrdJx1LVmTazelyZOAtcj54kJKHc4Vaw,1662
7
- neurostats_API/fetchers/cash_flow.py,sha256=muVnteEEyeFPapGqgBOoHa8PAieEI796rHPNi5otOMY,7009
8
- neurostats_API/fetchers/finance_overview.py,sha256=t5QlTM0bL3fkrqlyMn8-8GB6YgMLsofH9NRI8PfPRxE,18447
9
- neurostats_API/fetchers/month_revenue.py,sha256=RNA7ROl2vm8Xbib3k50p_1shsHDVSKIbHkyNiRa8yMw,3182
10
- neurostats_API/fetchers/profit_lose.py,sha256=ffEVNo7-fvtnAq2_gj-Ga55TGW7pPd6WhruOZH8NGYM,4463
11
- neurostats_API/fetchers/tech.py,sha256=wH1kkqiETQhF0HAhk-UIiucnZ3EiL85Q-yMWCcVOiFM,11395
12
- neurostats_API/fetchers/value_invest.py,sha256=tg8yELbVnTFTEclrwgXnCRW377KkcoLiP-Gk2pyM-9Y,2886
13
- neurostats_API/tools/balance_sheet.yaml,sha256=dKTMbsYR9EFp48WAzmm_ISHMiJQLyE0V-XWS_gkxmr0,541
14
- neurostats_API/tools/cash_flow_percentage.yaml,sha256=fk2Z4eb1JjGFvP134eJatHacB7BgTkBenhDJr83w8RE,1345
15
- neurostats_API/tools/finance_overview_dict.yaml,sha256=Vvf8bv23NwJP8Yyw8DPS8c0_jjT_Wctnnz51SHS4AeI,2335
16
- neurostats_API/tools/profit_lose.yaml,sha256=qHBnqG7fR4Pxc_c3n4raL-3l7o5RnABLz9YGOXoaGiA,2086
17
- neurostats_API/tools/seasonal_data_field_dict.txt,sha256=KlIIdTTdbvUd9TSDE9-gpzk2jt2ck_LdisX8cnrWMD4,7869
18
- neurostats_API/utils/__init__.py,sha256=FTYKRFzW2XVXdnSHXnS3mQQaHlKF9xGqrMsgZZ2kroc,142
19
- neurostats_API/utils/data_process.py,sha256=rRKf2H0X2J-tDXDreErcz3Y3TGb8_0Q6GKe0izRjnmA,4942
20
- neurostats_API/utils/datetime.py,sha256=I9CIgZdE5OMzUciOS5wvapOVEIrXG_0Qb6iDKfIod6c,574
21
- neurostats_API/utils/db_client.py,sha256=OYe6yazcR4Aa6jYmy47JrryUeh2NnKGqY2K_lSZe6i8,455
22
- neurostats_API/utils/fetcher.py,sha256=VbrUhjA-GG5AyjPX2SHtFIbZM4dm3jo0RgZzuCbb_Io,40927
23
- neurostats_API-0.0.7.dist-info/METADATA,sha256=Ajugxp0vnHoxdzriFfmLhTt32ckq2VnIiIO_eRU2QDo,18241
24
- neurostats_API-0.0.7.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
25
- neurostats_API-0.0.7.dist-info/top_level.txt,sha256=nSlQPMG0VtXivJyedp4Bkf86EOy2TpW10VGxolXrqnU,15
26
- neurostats_API-0.0.7.dist-info/RECORD,,