neurostats-API 0.0.21b0__py3-none-any.whl → 0.0.23__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 (31) hide show
  1. neurostats_API/__init__.py +1 -1
  2. neurostats_API/fetchers/balance_sheet.py +152 -102
  3. neurostats_API/fetchers/base.py +93 -74
  4. neurostats_API/fetchers/cash_flow.py +143 -113
  5. neurostats_API/fetchers/finance_overview.py +28 -28
  6. neurostats_API/fetchers/institution.py +211 -97
  7. neurostats_API/fetchers/margin_trading.py +121 -94
  8. neurostats_API/fetchers/month_revenue.py +139 -105
  9. neurostats_API/fetchers/profit_lose.py +203 -108
  10. neurostats_API/fetchers/tech.py +117 -42
  11. neurostats_API/fetchers/tej_finance_report.py +248 -338
  12. neurostats_API/fetchers/value_invest.py +32 -12
  13. neurostats_API/tools/company_list/tw.json +2175 -0
  14. neurostats_API/tools/tej_db/tej_db_percent_index.yaml +0 -3
  15. neurostats_API/tools/tej_db/tej_db_skip_index.yaml +14 -1
  16. neurostats_API/tools/tej_db/tej_db_thousand_index.yaml +0 -5
  17. neurostats_API/utils/__init__.py +0 -1
  18. neurostats_API/utils/calculate_value.py +102 -1
  19. neurostats_API/utils/data_process.py +53 -19
  20. neurostats_API/utils/logger.py +21 -0
  21. {neurostats_API-0.0.21b0.dist-info → neurostats_API-0.0.23.dist-info}/METADATA +2 -2
  22. neurostats_API-0.0.23.dist-info/RECORD +35 -0
  23. neurostats_API/utils/fetcher.py +0 -1056
  24. neurostats_API-0.0.21b0.dist-info/RECORD +0 -34
  25. /neurostats_API/tools/{balance_sheet.yaml → twse/balance_sheet.yaml} +0 -0
  26. /neurostats_API/tools/{cash_flow_percentage.yaml → twse/cash_flow_percentage.yaml} +0 -0
  27. /neurostats_API/tools/{finance_overview_dict.yaml → twse/finance_overview_dict.yaml} +0 -0
  28. /neurostats_API/tools/{profit_lose.yaml → twse/profit_lose.yaml} +0 -0
  29. /neurostats_API/tools/{seasonal_data_field_dict.txt → twse/seasonal_data_field_dict.txt} +0 -0
  30. {neurostats_API-0.0.21b0.dist-info → neurostats_API-0.0.23.dist-info}/WHEEL +0 -0
  31. {neurostats_API-0.0.21b0.dist-info → neurostats_API-0.0.23.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  from .base import BaseTEJFetcher
2
2
  from datetime import datetime
3
3
  from enum import Enum
4
+ import numpy as np
4
5
  import pandas as pd
5
6
  from pymongo import MongoClient
6
7
  from .tech import TechProcessor
@@ -18,34 +19,39 @@ class FinanceReportFetcher(BaseTEJFetcher):
18
19
  QOQ_NOCAL = 4
19
20
 
20
21
  def __init__(
21
- self,
22
- mongo_uri,
23
- db_name="company",
24
- collection_name="TWN/AINVFQ1"
25
- ):
22
+ self, mongo_uri, db_name="company", collection_name="TWN/AINVFQ1"
23
+ ):
26
24
  self.client = MongoClient(mongo_uri)
27
25
  self.db = self.client[db_name]
28
26
  self.collection = self.db[collection_name]
29
27
 
30
- index_dict = StatsProcessor.load_yaml("tej_db/tej_db_index.yaml")
31
- thousand_dict = StatsProcessor.load_yaml("tej_db/tej_db_thousand_index.yaml")
32
- percent_dict = StatsProcessor.load_yaml("tej_db/tej_db_percent_index.yaml")
33
- skip_dict = StatsProcessor.load_yaml("tej_db/tej_db_percent_index.yaml")
34
- self.check_index = set(index_dict[collection_name])
35
- self.skip_index = set(skip_dict[collection_name])
28
+ index_files = [
29
+ "tej_db/tej_db_index.yaml", "tej_db/tej_db_thousand_index.yaml",
30
+ "tej_db/tej_db_percent_index.yaml"
31
+ ]
36
32
 
37
- self.thousand_index_list = list(thousand_dict[collection_name])
38
- self.percent_index_list = list(percent_dict[collection_name])
33
+ self.index_dict, self.thousand_dict, self.percent_dict = [
34
+ StatsProcessor.load_yaml(file) for file in index_files
35
+ ]
39
36
 
37
+ self.check_index = set(self.index_dict.get(collection_name, []))
38
+ self.skip_index = set(self.percent_dict.get(collection_name, []))
39
+ self.thousand_index_list = list(
40
+ self.thousand_dict.get(collection_name, [])
41
+ )
42
+ self.percent_index_list = list(
43
+ self.percent_dict.get(collection_name, [])
44
+ )
40
45
 
41
46
  def get(
42
- self,
43
- ticker,
44
- fetch_mode: FetchMode = FetchMode.QOQ_NOCAL,
45
- start_date: str = None,
46
- end_date: str = None,
47
- report_type: str = "Q",
48
- indexes: list = []):
47
+ self,
48
+ ticker,
49
+ fetch_mode: FetchMode = FetchMode.QOQ_NOCAL,
50
+ start_date: str = None,
51
+ end_date: str = None,
52
+ report_type: str = "Q",
53
+ indexes: list = []
54
+ ):
49
55
  """
50
56
  基礎的query function
51
57
  ticker(str): 股票代碼
@@ -58,351 +64,242 @@ class FinanceReportFetcher(BaseTEJFetcher):
58
64
  indexes(List): 指定的index
59
65
  """
60
66
  # 確認indexes中是否有錯誤的index,有的話回傳warning
61
- if (indexes and self.check_index):
62
- indexes = set(indexes)
63
- difference = indexes - self.check_index
64
- if (difference):
67
+ if indexes and self.check_index:
68
+ invalid_indexes = set(indexes) - self.check_index
69
+ if invalid_indexes:
65
70
  warnings.warn(
66
- f"{list(difference)} 沒有出現在資料表中,請確認column名稱是否正確",
67
- UserWarning)
68
-
69
- if (not start_date):
70
- start_date = datetime.strptime("2005-01-01", "%Y-%m-%d")
71
- else:
72
- start_date = datetime.strptime(start_date, "%Y-%m-%d")
73
-
74
- if (fetch_mode in {self.FetchMode.QOQ, self.FetchMode.QOQ_NOCAL}):
75
-
76
- if (not end_date):
77
- end_date = datetime.today()
78
- else:
79
- end_date = datetime.strptime(end_date, "%Y-%m-%d")
80
-
81
- assert (start_date <= end_date)
82
-
83
- start_year = start_date.year
84
- start_season = (start_date.month - 1) // 4 + 1
85
- end_year = end_date.year
86
- end_season = (end_date.month - 1) // 4 + 1
87
-
88
- if (fetch_mode == self.FetchMode.QOQ):
89
- use_cal = True
90
- else:
91
- use_cal = False
92
-
93
- data_df = self.get_QoQ_data(
71
+ f"{list(invalid_indexes)} 不存在,請確認欄位名稱", UserWarning
72
+ )
73
+
74
+ start_date = datetime.strptime(
75
+ start_date, "%Y-%m-%d"
76
+ ) if start_date else datetime(2005, 1, 1)
77
+
78
+ if fetch_mode in {self.FetchMode.QOQ, self.FetchMode.QOQ_NOCAL}:
79
+ end_date = datetime.strptime(end_date, "%Y-%m-%d"
80
+ ) if end_date else datetime.today()
81
+ assert start_date <= end_date
82
+ start_year, end_year = start_date.year, end_date.year
83
+ return self.get_QoQ_data(
94
84
  ticker=ticker,
95
- start_year=start_year,
96
- start_season=start_season,
97
- end_year=end_year,
98
- end_season=end_season,
85
+ start_date=start_date,
86
+ end_date=end_date,
99
87
  report_type=report_type,
100
88
  indexes=indexes,
101
- use_cal=use_cal)
102
-
103
- return data_df
104
-
105
- elif (fetch_mode in {self.FetchMode.YOY, self.FetchMode.YOY_NOCAL}):
106
- start_year = start_date.year
107
- end_date = self.get_latest_data_time(ticker)
108
- if (not end_date):
109
- end_date = datetime.today()
110
-
111
- end_year = end_date.year
112
- season = (end_date.month - 1) // 4 + 1
113
-
114
- if (fetch_mode == self.FetchMode.YOY):
115
- use_cal = True
116
- else:
117
- use_cal = False
89
+ use_cal=(fetch_mode == self.FetchMode.QOQ)
90
+ )
118
91
 
119
- data_df = self.get_YoY_data(
92
+ elif fetch_mode in {self.FetchMode.YOY, self.FetchMode.YOY_NOCAL}:
93
+ end_date = self.get_latest_data_time(ticker) or datetime.today()
94
+ start_year, end_year = start_date.year, end_date.year
95
+ end_season = (end_date.month - 1) // 4 + 1
96
+ return self.get_YoY_data(
120
97
  ticker=ticker,
121
98
  start_year=start_year,
122
99
  end_year=end_year,
123
- season=season,
100
+ season=end_season,
124
101
  report_type=report_type,
125
102
  indexes=indexes,
126
- use_cal=use_cal)
127
-
128
- return data_df
103
+ use_cal=(fetch_mode == self.FetchMode.YOY)
104
+ )
129
105
 
130
106
  def get_QoQ_data(
131
- self,
132
- ticker,
133
- start_year,
134
- start_season,
135
- end_year,
136
- end_season,
137
- report_type="Q",
138
- indexes=[],
139
- use_cal=False):
107
+ self,
108
+ ticker,
109
+ start_date,
110
+ end_date,
111
+ report_type="Q",
112
+ indexes=[],
113
+ use_cal=False
114
+ ):
140
115
  """
141
116
  取得時間範圍內每季資料
142
117
  """
143
- if (use_cal):
144
- if (start_season == 1):
145
- lower_bound_year = start_year - 1
146
- lower_bound_season = 4
147
-
148
- else:
149
- lower_bound_year = start_year
150
- lower_bound_season = start_season - 1
151
-
152
- else:
153
- lower_bound_year = start_year,
154
- lower_bound_season = start_season
155
-
156
- if (not indexes): # 沒有指定 -> 取全部
157
- pipeline = [
158
- {
159
- "$match": {
160
- "ticker": ticker
161
- }
162
- }, {
163
- "$unwind": "$data"
164
- }, {
165
- "$match": {
166
- "$or": [
167
- {
168
- "data.year": {
169
- "$gt": start_year,
170
- "$lt": end_year
171
- }
172
- }, {
173
- "data.year": start_year,
174
- "data.season": {
175
- "$gte": start_season
176
- }
177
- }, {
178
- "data.year": end_year,
179
- "data.season": {
180
- "$lte": end_season
181
- }
182
- }, {
183
- "data.year": lower_bound_year,
184
- "data.season": lower_bound_season
185
- }
186
- ]
187
- }
188
- }, {
189
- "$project": {
190
- "data.year": 1,
191
- "data.season": 1,
192
- f"data.{report_type}": 1,
193
- "_id": 0
194
- }
195
- }
196
- ]
197
-
198
- else: # 取指定index
199
- project_stage = {"data.year": 1, "data.season": 1}
200
- for index in indexes:
201
- project_stage[f"data.{report_type}.{index}"] = 1
118
+ start_year, start_season = start_date.year, (
119
+ start_date.month - 1
120
+ ) // 4 + 1
121
+ end_year, end_season = end_date.year, (end_date.month - 1) // 4 + 1
122
+ lower_bound_year, lower_bound_season = (
123
+ start_year - 1, 4
124
+ ) if start_season == 1 else (start_year, start_season - 1)
125
+
126
+ pipeline = self.build_pipeline(
127
+ ticker, start_year, start_season, end_year, end_season,
128
+ lower_bound_year, lower_bound_season, report_type, indexes
129
+ )
130
+ fetched_data = self.collection.aggregate(pipeline).to_list()
202
131
 
203
- pipeline = [
204
- {
205
- "$match": {
206
- "ticker": ticker
207
- }
208
- }, {
209
- "$unwind": "$data"
210
- }, {
211
- "$match": {
212
- "$or": [
213
- {
214
- "data.year": {
215
- "$gt": start_year,
216
- "$lt": end_year
217
- }
218
- }, {
219
- "data.year": start_year,
220
- "data.season": {
221
- "$gte": start_season
222
- }
223
- }, {
224
- "data.year": end_year,
225
- "data.season": {
226
- "$lte": end_season
227
- }
228
- }, {
229
- "data.year": lower_bound_year,
230
- "data.season": lower_bound_season
231
- }
232
- ]
233
- }
234
- }, {
235
- "$project": project_stage
236
- }
237
- ]
132
+ data_dict = self.transform_value(
133
+ StatsProcessor.list_of_dict_to_dict(
134
+ data_list=fetched_data,
135
+ keys=["year", "season"],
136
+ delimeter="Q",
137
+ data_key=report_type
138
+ )
139
+ )
238
140
 
239
- fetched_data = self.collection.aggregate(pipeline).to_list()
240
- data_dict = StatsProcessor.list_of_dict_to_dict(
241
- fetched_data,
242
- keys=["year", "season"],
243
- delimeter="Q",
244
- data_key=report_type)
245
-
246
- data_dict = self.transform_value(data_dict)
247
-
248
- if (use_cal):
249
- data_with_QoQ = self.cal_QoQ(data_dict)
250
- data_df = pd.DataFrame.from_dict(data_with_QoQ)
251
- data_df = data_df.iloc[:, 1:]
252
- data_df = data_df.iloc[:, ::-1].T
253
- data_dict = data_df.to_dict()
254
- data_dict = self.get_dict_of_df(data_dict)
255
- return data_dict
256
- else:
257
- data_df = pd.DataFrame.from_dict(data_dict)
258
- data_df = data_df.iloc[:, ::-1]
259
- return data_df
141
+ return self.calculate_and_format(data_dict, use_cal, self.cal_QoQ)
260
142
 
261
143
  def get_YoY_data(
262
- self,
263
- ticker,
264
- start_year,
265
- end_year,
266
- season,
267
- report_type="Q",
268
- indexes=[],
269
- use_cal=False):
144
+ self,
145
+ ticker,
146
+ start_year,
147
+ end_year,
148
+ season,
149
+ report_type="Q",
150
+ indexes=[],
151
+ use_cal=False
152
+ ):
270
153
  """
271
154
  取得某季歷年資料
272
155
  """
273
- if (use_cal):
274
- select_year = set()
275
-
276
- for year in range(start_year, end_year + 1):
277
- year_shifts = {year, year - 1, year - 3, year - 5, year - 10}
278
-
279
- select_year = select_year.union(year_shifts)
280
-
281
- select_year = sorted(list(select_year), reverse=True)
282
- else:
283
- select_year = [year for year in range(start_year, end_year + 1)]
284
-
285
- if (not indexes): # 沒有指定 -> 取全部
286
- pipeline = [
287
- {
288
- "$match": {
289
- "ticker": ticker
290
- }
291
- }, {
292
- "$unwind": "$data"
293
- }, {
294
- "$match": {
295
- "$or": [
296
- {
297
- "$and": [
298
- {
299
- "data.year": {
300
- "$in": select_year
301
- }
302
- }, {
303
- "data.season": {
304
- "$eq": season
305
- }
306
- }
307
- ]
308
- },
309
- ]
310
- }
311
- }, {
312
- "$project": {
313
- "data.year": 1,
314
- "data.season": 1,
315
- f"data.{report_type}": 1,
316
- "_id": 0
317
- }
318
- }
319
- ]
320
-
321
- else: # 取指定index
322
- project_stage = {"data.year": 1, "data.season": 1}
323
- for index in indexes:
324
- project_stage[f"data.{report_type}.{index}"] = 1
325
-
326
- pipeline = [
327
- {
328
- "$match": {
329
- "ticker": ticker
330
- }
331
- }, {
332
- "$unwind": "$data"
333
- }, {
334
- "$match": {
335
- "$and": [
336
- {
337
- "data.year": {
338
- "$in": select_year
339
- }
340
- }, {
341
- "data.season": {
342
- "$eq": season
343
- }
344
- }
345
- ]
346
- }
347
- }, {
348
- "$project": project_stage
349
- }
350
- ]
351
-
156
+ select_year = sorted(
157
+ {year
158
+ for year in range(start_year, end_year + 1)} | {
159
+ y
160
+ for year in range(start_year, end_year + 1)
161
+ for y in {year, year - 1, year - 3, year - 5, year - 10}
162
+ }
163
+ ) if use_cal else list(range(start_year, end_year + 1))
164
+
165
+ pipeline = self.build_pipeline(
166
+ ticker,
167
+ select_year,
168
+ season,
169
+ None,
170
+ None,
171
+ None,
172
+ None,
173
+ report_type,
174
+ indexes,
175
+ year_based=True
176
+ )
352
177
  fetched_data = self.collection.aggregate(pipeline).to_list()
178
+ data_dict = self.transform_value(
179
+ StatsProcessor.list_of_dict_to_dict(
180
+ data_list=fetched_data,
181
+ keys=["year", "season"],
182
+ delimeter="Q",
183
+ data_key=report_type
184
+ )
185
+ )
186
+
187
+ return self.calculate_and_format(
188
+ data_dict, use_cal,
189
+ lambda x: self.cal_YoY(x, start_year, end_year, season)
190
+ )
353
191
 
354
- # 處理計算YoY
355
- data_dict = StatsProcessor.list_of_dict_to_dict(
356
- fetched_data,
357
- keys=['year', 'season'],
358
- data_key=report_type,
359
- delimeter='Q')
360
-
361
- data_dict = self.transform_value(data_dict)
362
-
363
- if (use_cal):
364
- data_with_YoY = self.cal_YoY(
365
- data_dict, start_year, end_year, season)
366
- data_df = pd.DataFrame.from_dict(data_with_YoY)
367
- data_df = data_df.iloc[:, ::-1].T
368
- data_dict = data_df.to_dict()
369
- data_dict = self.get_dict_of_df(data_dict)
370
- return data_dict
371
- else:
372
- data_df = pd.DataFrame.from_dict(data_dict)
373
- data_df = data_df.iloc[:, ::-1]
374
- return data_df
375
-
376
192
  def transform_value(self, data_dict):
377
193
  """
378
194
  處理千元, %等單位
379
195
  """
380
196
 
381
197
  data_df = pd.DataFrame.from_dict(data_dict)
382
-
383
- process_set = set(data_df.index).intersection(set(self.thousand_index_list))
384
- process_list = list(process_set)
385
- data_df.loc[process_list] = data_df.loc[process_list].map(
386
- lambda x : StatsProcessor.cal_non_percentage(x, postfix="千元")
387
- )
198
+ for category, postfix in [(self.thousand_index_list, "千元"),
199
+ (self.percent_index_list, "%")]:
200
+ process_list = list(set(data_df.index) & set(category))
201
+ if postfix == "%":
202
+ data_df = data_df.T
203
+ data_df[process_list] = data_df[process_list].map(lambda x: f"{x}%") # if (not np.isnan(x)) else None)
204
+ data_df = data_df.T
205
+ else:
206
+ data_df.loc[process_list] = data_df.loc[process_list].map(
207
+ lambda x: StatsProcessor.
208
+ cal_non_percentage(x, postfix=postfix)
209
+ )
210
+ return data_df.to_dict()
211
+
212
+ def build_pipeline(
213
+ self,
214
+ ticker,
215
+ start_year,
216
+ start_season,
217
+ end_year,
218
+ end_season,
219
+ lower_bound_year,
220
+ lower_bound_season,
221
+ report_type,
222
+ indexes,
223
+ year_based=False
224
+ ):
225
+ project_stage = {
226
+ "_id": 0,
227
+ "data.year": 1,
228
+ "data.season": 1,
229
+ **{
230
+ f"data.{report_type}.{idx}": 1
231
+ for idx in indexes
232
+ }
233
+ } if indexes else {
234
+ "_id": 0,
235
+ "data.year": 1,
236
+ "data.season": 1,
237
+ f"data.{report_type}": 1
238
+ }
239
+
240
+ if (year_based):
241
+ match_stage = {
242
+ "data.year": {
243
+ "$in": start_year
244
+ } if year_based else {
245
+ "$gt": start_year,
246
+ "$lt": end_year
247
+ },
248
+ "data.season": start_season
249
+ }
250
+ else:
251
+ match_stage = {
252
+ "$or": [
253
+ {
254
+ "data.year": {
255
+ "$gt": start_year,
256
+ "$lt": end_year
257
+ }
258
+ }, {
259
+ "data.year": start_year,
260
+ "data.season": {
261
+ "$gte": start_season
262
+ }
263
+ }, {
264
+ "data.year": end_year,
265
+ "data.season": {
266
+ "$lte": end_season
267
+ }
268
+ }, {
269
+ "data.year": lower_bound_year,
270
+ "data.season": lower_bound_season
271
+ }
272
+ ]
273
+ }
388
274
 
389
- process_set = set(data_df.index).intersection(set(self.percent_index_list))
390
- process_list = list(process_set)
391
- data_df.loc[process_list] = data_df.loc[process_list].map(
392
- lambda x : f"{x}%"
275
+ return [
276
+ {
277
+ "$match": {
278
+ "ticker": ticker
279
+ }
280
+ }, {
281
+ "$unwind": "$data"
282
+ }, {
283
+ "$match": match_stage
284
+ }, {
285
+ "$project": project_stage
286
+ }
287
+ ]
288
+
289
+ def calculate_and_format(self, data_dict, use_cal, calc_function):
290
+ data_df = pd.DataFrame.from_dict(
291
+ calc_function(data_dict) if use_cal else data_dict
292
+ ).iloc[:, ::-1]
293
+ return data_df if not use_cal else self.get_dict_of_df(
294
+ data_df.T.to_dict()
393
295
  )
394
296
 
395
- data_dict = data_df.to_dict()
396
-
397
- return data_dict
398
297
 
399
298
  class TEJStockPriceFetcher(BaseTEJFetcher):
400
299
 
401
300
  def __init__(
402
- self,
403
- mongo_uri,
404
- db_name: str = "company",
405
- collection_name: str = None):
301
+ self, mongo_uri, db_name: str = "company", collection_name: str = None
302
+ ):
406
303
  self.mongo_uri = mongo_uri
407
304
  self.db_name = db_name
408
305
  self.collection_name = collection_name
@@ -411,14 +308,16 @@ class TEJStockPriceFetcher(BaseTEJFetcher):
411
308
  self.db = self.client[self.db_name]
412
309
  self.collection = self.db[self.collection_name]
413
310
 
414
- self.check_period = ['1d', '7d', '1m', '3m', '1y', '3y', '5y', '10y', 'all']
311
+ self.check_period = [
312
+ '1d', '7d', '1m', '3m', '1y', '3y', '5y', '10y', 'all'
313
+ ]
415
314
 
416
315
  def get(
417
- self,
418
- ticker: str = "2330",
419
- start_date: str = "2024-10-01",
420
- period: str = None
421
- ):
316
+ self,
317
+ ticker: str = "2330",
318
+ start_date: str = "2024-10-01",
319
+ period: str = None
320
+ ):
422
321
  """
423
322
  取得開高低收資料
424
323
  start_date: str: 起始的日期
@@ -432,7 +331,10 @@ class TEJStockPriceFetcher(BaseTEJFetcher):
432
331
 
433
332
  if (period is not None):
434
333
  latest_date = self.get_latest_data_time(ticker)
435
- start_date = self.set_time_shift(date=latest_date, period=period)
334
+ if (latest_date):
335
+ start_date = self.set_time_shift(date=latest_date, period=period)
336
+ else:
337
+ start_date = datetime.strptime(start_date, "%Y-%m-%d")
436
338
  else:
437
339
  start_date = datetime.strptime(start_date, "%Y-%m-%d")
438
340
 
@@ -460,7 +362,15 @@ class TEJStockPriceFetcher(BaseTEJFetcher):
460
362
  datas = self.collection.aggregate(pipeline).to_list()
461
363
 
462
364
  elements = [element['data'] for element in datas]
365
+ try:
366
+ data_df = pd.DataFrame(elements).set_index('mdate')
367
+ except:
368
+ column_names = [
369
+ "coid", "mdate", "mkt", "open_d", "high_d", "low_d", "close_d",
370
+ "adjfac", "vol", "amt", "trn", "bid", "offer", "avgprc", "roi",
371
+ "hmlpct", "turnover", "shares", "mktcap", "mktcap_pct",
372
+ "amt_pct", "per", "pbr", "div_yid", "cdiv_yid"
373
+ ]
374
+ data_df = pd.DataFrame(columns = column_names)
463
375
 
464
- data_df = pd.DataFrame(elements).set_index('mdate')
465
-
466
- return data_df
376
+ return data_df