neurostats-API 0.0.21b0__py3-none-any.whl → 0.0.23b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. neurostats_API/__init__.py +1 -1
  2. neurostats_API/fetchers/balance_sheet.py +138 -111
  3. neurostats_API/fetchers/base.py +89 -74
  4. neurostats_API/fetchers/cash_flow.py +120 -111
  5. neurostats_API/fetchers/finance_overview.py +2 -2
  6. neurostats_API/fetchers/month_revenue.py +1 -1
  7. neurostats_API/fetchers/profit_lose.py +188 -113
  8. neurostats_API/fetchers/tech.py +175 -42
  9. neurostats_API/fetchers/tej_finance_report.py +230 -335
  10. neurostats_API/tools/company_list/tw.json +2175 -0
  11. neurostats_API/tools/tej_db/tej_db_skip_index.yaml +3 -1
  12. neurostats_API/tools/tej_db/tej_db_thousand_index.yaml +0 -1
  13. neurostats_API/utils/__init__.py +0 -1
  14. neurostats_API/utils/calculate_value.py +99 -1
  15. neurostats_API/utils/data_process.py +43 -15
  16. {neurostats_API-0.0.21b0.dist-info → neurostats_API-0.0.23b0.dist-info}/METADATA +2 -2
  17. neurostats_API-0.0.23b0.dist-info/RECORD +34 -0
  18. neurostats_API/utils/fetcher.py +0 -1056
  19. neurostats_API-0.0.21b0.dist-info/RECORD +0 -34
  20. /neurostats_API/tools/{balance_sheet.yaml → twse/balance_sheet.yaml} +0 -0
  21. /neurostats_API/tools/{cash_flow_percentage.yaml → twse/cash_flow_percentage.yaml} +0 -0
  22. /neurostats_API/tools/{finance_overview_dict.yaml → twse/finance_overview_dict.yaml} +0 -0
  23. /neurostats_API/tools/{profit_lose.yaml → twse/profit_lose.yaml} +0 -0
  24. /neurostats_API/tools/{seasonal_data_field_dict.txt → twse/seasonal_data_field_dict.txt} +0 -0
  25. {neurostats_API-0.0.21b0.dist-info → neurostats_API-0.0.23b0.dist-info}/WHEEL +0 -0
  26. {neurostats_API-0.0.21b0.dist-info → neurostats_API-0.0.23b0.dist-info}/top_level.txt +0 -0
@@ -12,7 +12,10 @@ class TechFetcher(StatsFetcher):
12
12
  """
13
13
 
14
14
  super().__init__(ticker, db_client)
15
- self.collection = self.db["TWN/APIPRCD"]
15
+ if (ticker in self.tw_company_list.keys()):
16
+ self.twse_collection = self.db['twse_stats']
17
+ self.tej_collection = self.db["TWN/APIPRCD"]
18
+
16
19
  self.full_ohlcv = self._get_ohlcv()
17
20
  self.basic_indexes = [
18
21
  'SMA5', 'SMA20', 'SMA60', 'EMA5', 'EMA20', 'EMA40', 'EMA12',
@@ -51,53 +54,47 @@ class TechFetcher(StatsFetcher):
51
54
 
52
55
  required_cols = ['date', 'open', 'high', 'low', 'close', 'volume']
53
56
 
54
- try:
55
- # 先對yf search
56
- if self.ticker in ['GSPC', 'IXIC', 'DJI', 'TWII']:
57
- full_tick = f'^{self.ticker}'
58
- else:
59
- full_tick = f'{self.ticker}.tw'
60
-
57
+ if self.ticker in ['GSPC', 'IXIC', 'DJI', 'TWII']:
58
+ full_tick = f'^{self.ticker}'
61
59
  df = self.conduct_yf_search(full_tick)
62
60
 
63
- if not self.has_required_columns(df, required_cols):
64
-
65
- print(f".tw failed, try .two")
66
-
67
- full_tick = f'{self.ticker}.two'
61
+ return df[required_cols]
68
62
 
69
- df = self.conduct_yf_search(full_tick)
70
-
71
- if (df.empty):
72
- raise ValueError(f"No data found for ticker: {self.ticker}")
73
-
74
- except (KeyError, ValueError, TypeError) as e:
75
- # 再對TEJ search
76
- tej_required_cols = [
77
- "mdate", "open_d", 'high_d', 'low_d', 'close_d', 'vol'
63
+ elif(self.ticker in self.tw_company_list.keys()):
64
+ search_fns = [
65
+ self.conduct_db_search_twse,
66
+ self.conduct_db_search_tej,
67
+ lambda: self.conduct_yf_search(f'{self.ticker}.tw'),
68
+ lambda: self.conduct_yf_search(f'{self.ticker}.two')
78
69
  ]
79
- tej_name_proj = {
80
- tej_name: org_name
81
- for tej_name, org_name in zip(tej_required_cols, required_cols)
82
- }
83
-
84
- query = {'ticker': self.ticker}
85
- ticker_full = self.collection.find_one(query)
86
70
 
87
- if not ticker_full:
88
- raise ValueError("No ticker found in database")
89
-
90
- daily_data = ticker_full.get("data", [])
91
- if not isinstance(daily_data, list):
92
- raise TypeError("Expected 'daily_data' to be a list.")
93
-
94
- df = pd.DataFrame(daily_data)
95
-
96
- if not self.has_required_columns(df, tej_required_cols):
97
- raise KeyError(f"Missing required columns")
98
- df = df.rename(columns=tej_name_proj)
71
+ for search_method in search_fns:
72
+ try:
73
+ df = search_method()
74
+ break
75
+ except (KeyError, ValueError, TypeError):
76
+ continue
77
+ else:
78
+ return pd.DataFrame(columns=required_cols)
79
+
80
+ # break跳出後
81
+ return df[required_cols]
82
+ else: # 美股
83
+ search_fns = [
84
+ self.conduct_db_search_us,
85
+ lambda : self.conduct_yf_search(f"{self.ticker}")
86
+ ]
87
+ for search_method in search_fns:
88
+ try:
89
+ df = search_method()
90
+ break
91
+ except (KeyError, ValueError, TypeError):
92
+ continue
93
+ else:
94
+ df = pd.DataFrame()
99
95
 
100
- return df[required_cols]
96
+ return df
97
+
101
98
 
102
99
  def get_daily(self):
103
100
 
@@ -141,6 +138,142 @@ class TechFetcher(StatsFetcher):
141
138
  )
142
139
 
143
140
  return df
141
+
142
+ def conduct_db_search_tej(self):
143
+ # 再對TEJ search
144
+ tej_required_cols = [
145
+ "mdate", "open_d", 'high_d', 'low_d', 'close_d', 'vol'
146
+ ]
147
+
148
+ required_cols = ['date', 'open', 'high', 'low', 'close', 'volume']
149
+ tej_name_proj = {
150
+ tej_name: org_name
151
+ for tej_name, org_name in zip(tej_required_cols, required_cols)
152
+ }
153
+
154
+ query = {'ticker': self.ticker}
155
+ ticker_full = self.collection.find_one(query)
156
+
157
+ if not ticker_full:
158
+ raise ValueError("No ticker found in database")
159
+
160
+ daily_data = ticker_full.get("data", [])
161
+ if not isinstance(daily_data, list):
162
+ raise TypeError("Expected 'daily_data' to be a list.")
163
+
164
+ df = pd.DataFrame(daily_data)
165
+
166
+ if not self.has_required_columns(df, tej_required_cols):
167
+ raise KeyError(f"Missing required columns")
168
+ df = df.rename(columns=tej_name_proj)
169
+
170
+ return df[required_cols]
171
+
172
+ def conduct_db_search_us(self):
173
+ required_cols = ['date', 'open', 'high', 'low', 'close', 'volume']
174
+
175
+ query = {'ticker': self.ticker}
176
+ filter_query = {"daily_data" : 1, "_id": 0}
177
+ ticker_full = self.collection.find_one(query, filter_query)
178
+
179
+ if not ticker_full:
180
+ raise ValueError("No ticker found in database")
181
+
182
+ daily_data = ticker_full.get("daily_data", [])
183
+ if not isinstance(daily_data, list):
184
+ raise TypeError("Expected 'daily_data' to be a list.")
185
+
186
+ df = pd.DataFrame(daily_data)
187
+
188
+ if not self.has_required_columns(df, required_cols):
189
+ missing_cols = [col for col in required_cols if col not in df.columns]
190
+ missing_cols = ",".join(missing_cols)
191
+ print(Warning(f"{missing_cols} not in columns"))
192
+ for col in missing_cols:
193
+ df[col] = pd.NA
194
+ # raise KeyError(f"Missing required columns")
195
+
196
+ return df[required_cols]
197
+
198
+
199
+ def conduct_db_search_twse(self):
200
+ required_cols = ['date', 'open', 'high', 'low', 'close', 'volume']
201
+ match_query = {"ticker" : self.ticker}
202
+ proj_query = {"_id": 0, "daily_data": 1}
203
+
204
+ full_data = self.twse_collection.find_one(match_query, proj_query)
205
+
206
+ if (not full_data):
207
+ raise ValueError("No ticker found in database twse_stats")
208
+
209
+ daily_data = full_data.get("daily_data", [])
210
+
211
+ if (not isinstance(daily_data, list)):
212
+ raise ValueError("No ticker found in database twse_stats")
213
+
214
+ df = pd.DataFrame(daily_data)
215
+ if not self.has_required_columns(df, required_cols):
216
+ raise KeyError(f"Missing required columns")
217
+
218
+ df = df[required_cols]
219
+ df = df.sort_values(by = 'date').drop_duplicates(subset=['date'])
220
+
221
+ return df
222
+
223
+ def conduct_db_search_tej(self):
224
+ # 再對TEJ search
225
+ tej_required_cols = [
226
+ "mdate", "open_d", 'high_d', 'low_d', 'close_d', 'vol'
227
+ ]
228
+
229
+ required_cols = ['date', 'open', 'high', 'low', 'close', 'volume']
230
+ tej_name_proj = {
231
+ tej_name: org_name
232
+ for tej_name, org_name in zip(tej_required_cols, required_cols)
233
+ }
234
+
235
+ query = {'ticker': self.ticker}
236
+ ticker_full = self.tej_collection.find_one(query)
237
+
238
+ if not ticker_full:
239
+ raise ValueError("No ticker found in database")
240
+
241
+ daily_data = ticker_full.get("data", [])
242
+ if not isinstance(daily_data, list):
243
+ raise TypeError("Expected 'daily_data' to be a list.")
244
+
245
+ df = pd.DataFrame(daily_data)
246
+
247
+ if not self.has_required_columns(df, tej_required_cols):
248
+ raise KeyError(f"Missing required columns")
249
+ df = df.rename(columns=tej_name_proj)
250
+
251
+ return df[required_cols]
252
+
253
+ def conduct_db_search_us(self):
254
+ required_cols = ['date', 'open', 'high', 'low', 'close', 'volume']
255
+
256
+ query = {'ticker': self.ticker}
257
+ filter_query = {"daily_data" : 1, "_id": 0}
258
+ ticker_full = self.collection.find_one(query, filter_query)
259
+
260
+ if not ticker_full:
261
+ raise ValueError("No ticker found in database")
262
+
263
+ daily_data = ticker_full.get("daily_data", [])
264
+ if not isinstance(daily_data, list):
265
+ raise TypeError("Expected 'daily_data' to be a list.")
266
+
267
+ df = pd.DataFrame(daily_data)
268
+
269
+ if not self.has_required_columns(df, required_cols):
270
+ missing_cols = [col for col in required_cols if col not in df.columns]
271
+ missing_cols = ",".join(missing_cols)
272
+ for col in missing_cols:
273
+ df[col] = pd.NA
274
+ # raise KeyError(f"Missing required columns")
275
+
276
+ return df[required_cols]
144
277
 
145
278
 
146
279
  class TechProcessor: