neurostats-API 0.0.10__py3-none-any.whl → 0.0.11__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.10'
1
+ __version__='0.0.11'
@@ -2,6 +2,7 @@ from .base import StatsDateTime, StatsFetcher
2
2
  from .balance_sheet import BalanceSheetFetcher
3
3
  from .cash_flow import CashFlowFetcher
4
4
  from .finance_overview import FinanceOverviewFetcher
5
+ from .institution import InstitutionFetcher
5
6
  from .month_revenue import MonthRevenueFetcher
6
7
  from .profit_lose import ProfitLoseFetcher
7
8
  from .value_invest import ValueFetcher
@@ -116,10 +116,13 @@ class BalanceSheetFetcher(StatsFetcher):
116
116
  try: # table_dict[項目][(2020Q1, '%')]
117
117
  if (item_name == 'percentage'):
118
118
  if (isinstance(item, (float, int))):
119
- item = np.round(item, 2)
120
- if ("YoY" in item_name):
119
+ item = StatsProcessor.cal_non_percentage(item, to_str=True, postfix="%")
120
+ elif ("YoY" in item_name):
121
121
  if (isinstance(item, (float, int))):
122
- item = np.round(item * 100, 2)
122
+ item = StatsProcessor.cal_percentage(item)
123
+ else:
124
+ if (isinstance(item, (float, int))):
125
+ item = StatsProcessor.cal_non_percentage(item, postfix="千元")
123
126
  table_dict[index_name][(time_index, item_name)] = item
124
127
 
125
128
  except KeyError:
@@ -132,14 +132,15 @@ class CashFlowFetcher(StatsFetcher):
132
132
  table_dict[time_index][index_name]['value'] = value[
133
133
  'value']
134
134
  if (value['value']):
135
- table_dict[time_index][index_name][
136
- 'percentage'] = np.round(
135
+ ratio = np.round(
137
136
  (value['value'] / cash_flow[
138
137
  main_cash_flow_name]['value']) * 100, 2)
138
+ table_dict[time_index][index_name][
139
+ 'percentage'] = f"{ratio}%"
139
140
  else:
140
141
  table_dict[time_index][index_name][
141
142
  'percentage'] = None
142
- except:
143
+ except: # 新增index再做一次
143
144
  if (time_index not in table_dict.keys()):
144
145
  table_dict[time_index] = dict()
145
146
  table_dict[time_index][index_name] = dict()
@@ -147,14 +148,15 @@ class CashFlowFetcher(StatsFetcher):
147
148
  table_dict[time_index][index_name]['value'] = value[
148
149
  'value']
149
150
  if (value['value']):
150
- table_dict[time_index][index_name][
151
- 'percentage'] = np.round(
151
+ ratio = np.round(
152
152
  (value['value'] / cash_flow[
153
153
  main_cash_flow_name]['value']) * 100, 2)
154
+ table_dict[time_index][index_name][
155
+ 'percentage'] = f"{ratio}%"
154
156
  else:
155
157
  table_dict[time_index][index_name][
156
158
  'percentage'] = None
157
-
159
+ table_dict[time_index][index_name]['value'] = StatsProcessor.cal_non_percentage(value['value'], postfix="千元")
158
160
  try:
159
161
  partial_cash_flow[time_index][index_name] = table_dict[
160
162
  time_index][index_name]
@@ -156,6 +156,7 @@ class FinanceOverviewProcessor(StatsProcessor):
156
156
  finance_dict[index] = StatsProcessor.cal_non_percentage(finance_dict[index], postfix="千元")
157
157
  except Exception as e:
158
158
  finance_dict[index] = None
159
+
159
160
 
160
161
  @classmethod
161
162
  def process_all(cls, finance_dict):
@@ -176,9 +177,6 @@ class FinanceOverviewProcessor(StatsProcessor):
176
177
  cls.cal_net_debt_to_equity_ratio, cls.cal_interest_coverage_ratio,
177
178
  cls.cal_debt_to_operating_cash_flow,
178
179
  cls.cal_debt_to_free_cash_flow, cls.cal_cash_flow_ratio,
179
-
180
- # process to 千元
181
- cls.process_thousand_dollar
182
180
  ]
183
181
 
184
182
  for method in methods:
@@ -18,34 +18,33 @@ class InstitutionFetcher(StatsFetcher):
18
18
  """
19
19
 
20
20
  def __init__(self, ticker, db_client):
21
- raise(NotImplementedError("InstitutionFetcher : Not done yet"))
22
21
  super().__init__(ticker, db_client)
23
22
 
24
23
  def prepare_query(self, start_date, end_date):
25
24
  pipeline = super().prepare_query()
26
25
 
27
- target_query = {
28
- "date": date,
29
- "institution_trading": "$$target_season_data.institution_trading"
30
- }
31
-
26
+ # target_query = {
27
+ # "date": date,
28
+ # "institution_trading": "$$target_season_data.institution_trading"
29
+ # }
32
30
 
33
31
  pipeline.append({
34
32
  "$project": {
35
33
  "_id": 0,
36
34
  "ticker": 1,
37
35
  "company_name": 1,
38
- "profit_loses": {
36
+ "daily_data": {
39
37
  "$map": {
40
38
  "input": {
41
39
  "$filter": {
42
40
  "input": "$daily_data",
43
41
  "as": "daily",
44
42
  "cond": {
45
- "$and": [
46
- {"$gte": ["$$daily.date", start_date]},
47
- {"$lte": ["$$daily.date", end_date]}
48
- ]
43
+ "$and": [{
44
+ "$gte": ["$$daily.date", start_date]
45
+ }, {
46
+ "$lte": ["$$daily.date", end_date]
47
+ }]
49
48
  }
50
49
  }
51
50
  },
@@ -58,57 +57,158 @@ class InstitutionFetcher(StatsFetcher):
58
57
 
59
58
  return pipeline
60
59
 
61
- def collect_data(self, date):
62
- pipeline = self.prepare_query(date)
60
+ def collect_data(self, start_date, end_date):
61
+ pipeline = self.prepare_query(start_date, end_date)
63
62
 
64
63
  fetched_data = self.collection.aggregate(pipeline).to_list()
65
64
 
66
- return fetch_data[-1]
67
-
65
+ return fetched_data[-1]
66
+
68
67
  def query_data(self):
69
68
  try:
70
69
  latest_time = StatsDateTime.get_latest_time(
71
70
  self.ticker, self.collection)['last_update_time']
72
- latest_date = latest_time['daily_data']['institution_trading']['last_update']
73
- date = latest_date.replace(hour=0, minute=0, second=0, microsecond=0)
71
+ latest_date = latest_time['institution_trading'][
72
+ 'latest_date']
73
+ date = latest_date.replace(hour=0,
74
+ minute=0,
75
+ second=0,
76
+ microsecond=0)
74
77
  except Exception as e:
75
- print(f"No updated time for institution_trading in {self.ticker}, use current time instead")
78
+ print(
79
+ f"No updated time for institution_trading in {self.ticker}, use current time instead"
80
+ )
76
81
  date = datetime.now(self.timezone)
77
- date = date.replace(hour=0, minute=0, second=0, microsecond=0)
82
+ date = date.replace(hour=0, minute=0, second=0, microsecond=0)
78
83
 
79
84
  if (date.hour < 17): # 拿不到今天的資料
80
85
  date = date - timedelta(days=1)
81
-
82
- start_date = start_date - timedelta(days=365)
83
86
 
84
- daily_data = self.collect_data(date)
87
+ start_date = date - timedelta(days=365)
85
88
 
86
- daily_data = sorted(daily_data['daily_data'], key = lambda x : x['date'], reverse = True)
89
+ daily_data = self.collect_data(start_date, end_date=date)
90
+
91
+ daily_data = sorted(daily_data['daily_data'],
92
+ key=lambda x: x['date'],
93
+ reverse=True)
94
+
95
+ table_dict = self.process_data(daily_data)
96
+
97
+ return table_dict
87
98
 
88
- self.process_data(self.ticker, daily_data)
89
-
90
99
  def process_data(self, daily_data):
91
100
  table_dict = dict()
92
101
 
93
- latest_data = daily_data[0]
102
+ latest_data = daily_data[0]
94
103
  yesterday_data = daily_data[1]
95
104
 
96
105
  # 交易價格與昨天交易
97
- table_dict = {
106
+ price_dict = {
98
107
  "open": latest_data['open'],
99
108
  'close': latest_data['close'],
100
- 'range': f"{latest_data['high']}-{latest_data['low']}",
101
- 'volumn': latest_data['volumn'] / 1000
102
-
109
+ 'range': f"{latest_data['low']}-{latest_data['high']}",
110
+ 'volumn': latest_data['volume'] / 1000,
111
+ 'last_open': yesterday_data['open'],
112
+ 'last_close': yesterday_data['close'],
113
+ 'last_range': f"{yesterday_data['low']}-{yesterday_data['high']}",
114
+ 'last_volumn': yesterday_data['volume'] / 1000
103
115
  }
116
+ # 一年範圍
117
+ annual_lows = [data['low'] for data in daily_data]
118
+ annual_highs = [data['high'] for data in daily_data]
119
+ lowest = np.min(annual_lows).item()
120
+ highest = np.max(annual_highs).item()
104
121
 
105
- # 今日法人買賣
106
-
107
- # 一年內法人
108
-
109
-
110
-
122
+ price_dict['52weeks_range'] = f"{lowest}-{highest}"
123
+ table_dict['price'] = price_dict
111
124
 
125
+ # 發行股數 & 市值
112
126
 
127
+ # 今日法人買賣
128
+ table_dict['latest_trading'] = {
129
+ "date":
130
+ daily_data[0]['date'],
131
+ "table":
132
+ self.process_latest_trading(daily_data[0]['institution_trading'], daily_data[0]['volume'])
133
+ }
134
+ # 一年內法人
135
+ annual_trading = [
136
+ {
137
+ **data['institution_trading'],
138
+ "收盤價": int(data['close'])
139
+ }
140
+ for data in daily_data
141
+ ] # 將close也併入這個表格
142
+ annual_dates = [data['date'] for data in daily_data]
143
+ table_dict['annual_trading'] = self.process_annual_trading(
144
+ annual_dates, annual_trading)
145
+
146
+ return table_dict
147
+
148
+ def process_latest_trading(self, latest_trading, volume):
149
+ latest_table = {
150
+ "foreign": self.default_institution_chart(),
151
+ "mutual": self.default_institution_chart(),
152
+ "prop": self.default_institution_chart(),
153
+ "institutional_investor":self.default_institution_chart(),
154
+ }
113
155
 
156
+ for key in latest_trading.keys():
157
+ if (key.find("外陸資") >= 0 or key.find("外資") >= 0):
158
+ self.target_institution(latest_trading, latest_table['foreign'], key, volume)
159
+ elif (key.find("自營商") >= 0):
160
+ self.target_institution(latest_trading,latest_table['prop'], key, volume)
161
+ elif (key.find("投信") >= 0):
162
+ self.target_institution(latest_trading,latest_table['mutual'], key, volume)
163
+ elif (key.find("三大法人") >= 0):
164
+ self.target_institution(latest_trading,latest_table['institutional_investor'], key, volume)
165
+
166
+ frames = []
167
+ for category, trades in latest_table.items():
168
+ temp_df = pd.DataFrame(trades).T
169
+ temp_df['category'] = category
170
+ frames.append(temp_df)
171
+
172
+ latest_df = pd.concat(frames)
173
+ latest_df = latest_df.reset_index().rename(columns={'index': 'type'})
174
+ latest_df = latest_df[['type', 'category', 'stock', 'price', 'average_price', 'percentage']]
175
+
176
+ return latest_df
177
+
178
+ def process_annual_trading(self, dates, annual_tradings):
179
+ dates = [date.strftime("%m/%d") for date in dates]
180
+ return pd.DataFrame(annual_tradings, index=dates)
181
+
182
+ def target_institution(self, old_table, new_table, key, volume):
183
+ if (key.find("買進") >= 0):
184
+ self.cal_institution(old_table, new_table['buy'], key, volume)
185
+ elif (key.find("賣出") >= 0):
186
+ self.cal_institution(old_table, new_table['sell'], key, volume)
187
+ elif (key.find("買賣超") >= 0):
188
+ self.cal_institution(old_table, new_table['over_buy_sell'], key, volume)
114
189
 
190
+ def cal_institution(self, old_table, new_table, key, volume):
191
+ new_table['stock'] = np.round(old_table[key] / 1000, 2).item()
192
+ new_table['percentage'] = np.round((old_table[key] / volume) * 100, 2).item()
193
+
194
+ def default_institution_chart(self):
195
+ return {
196
+ "buy": {
197
+ "stock": 0,
198
+ "price": 0,
199
+ "average_price": 0,
200
+ "percentage": 0
201
+ },
202
+ "sell": {
203
+ "stock": 0,
204
+ "price": 0,
205
+ "average_price": 0,
206
+ "percentage": 0
207
+ },
208
+ "over_buy_sell": {
209
+ "stock": 0,
210
+ "price": 0,
211
+ "average_price": 0,
212
+ "percentage": 0
213
+ },
214
+ }
@@ -64,6 +64,17 @@ class MonthRevenueFetcher(StatsFetcher):
64
64
  def process_data(self, fetched_data):
65
65
 
66
66
  monthly_data = fetched_data['monthly_data']
67
+ for data in monthly_data:
68
+ for key, value in data.items():
69
+ if ("YoY" in key):
70
+ data[key] = StatsProcessor.cal_percentage(value)
71
+ elif ("ratio" in key or 'percentage' in key):
72
+ data[key] = StatsProcessor.cal_non_percentage(value,
73
+ to_str=True,
74
+ postfix="%")
75
+ elif (key not in ('year', 'month')):
76
+ data[key] = StatsProcessor.cal_non_percentage(value,
77
+ postfix="千元")
67
78
  target_month = monthly_data[0]['month']
68
79
  monthly_df = pd.DataFrame(monthly_data)
69
80
  target_month_df = monthly_df[monthly_df['month'] == target_month]
@@ -77,21 +88,26 @@ class MonthRevenueFetcher(StatsFetcher):
77
88
 
78
89
  grand_total_df.rename(index={target_month: f"grand_total"},
79
90
  inplace=True)
80
- month_revenue_df = month_revenue_df.sort_index(ascending = False)
91
+ month_revenue_df = month_revenue_df.sort_index(ascending=False)
81
92
  month_revenue_df = pd.concat([grand_total_df, month_revenue_df],
82
93
  axis=0)
83
94
 
84
- fetched_data['month_revenue'] = month_revenue_df[sorted(month_revenue_df.columns, reverse = True)]
95
+ fetched_data['month_revenue'] = month_revenue_df[sorted(
96
+ month_revenue_df.columns, reverse=True)]
85
97
  # 歷年月營收
86
98
  fetched_data[
87
99
  'this_month_revenue_over_years'] = target_month_df.set_index(
88
- "year")[["revenue", "revenue_increment_ratio", "YoY_1",
89
- "YoY_3", "YoY_5", "YoY_10"]].T
100
+ "year")[[
101
+ "revenue", "revenue_increment_ratio", "YoY_1", "YoY_3",
102
+ "YoY_5", "YoY_10"
103
+ ]].T
90
104
  # 歷年營收成長量
91
105
  fetched_data['grand_total_over_years'] = target_month_df.set_index(
92
- "year")[["grand_total", "grand_total_increment_ratio",
93
- "grand_total_YoY_1", "grand_total_YoY_3",
94
- "grand_total_YoY_5", "grand_total_YoY_10"]].T
106
+ "year")[[
107
+ "grand_total", "grand_total_increment_ratio",
108
+ "grand_total_YoY_1", "grand_total_YoY_3", "grand_total_YoY_5",
109
+ "grand_total_YoY_10"
110
+ ]].T
95
111
 
96
112
  fetched_data.pop("monthly_data")
97
113
 
@@ -115,12 +115,15 @@ class ProfitLoseFetcher(StatsFetcher):
115
115
  for index_name, value_dict in profit_lose.items():
116
116
  # (2020Q1, 項目, 金額或%)
117
117
  for item_name, item in value_dict.items():
118
- if (item_name == 'percentage'):
118
+ if ('percentage' in item_name):
119
119
  if (isinstance(item, (float, int))):
120
- item = np.round(item, 2)
121
- if ('YoY' in item_name):
120
+ item = StatsProcessor.cal_non_percentage(item, to_str=True, postfix="%")
121
+ elif ('YoY' in item_name):
122
122
  if (isinstance(item, (float, int))):
123
- item = np.round(item * 100, 2)
123
+ item = StatsProcessor.cal_percentage(item)
124
+ else:
125
+ if (isinstance(item, (float, int))):
126
+ item = StatsProcessor.cal_non_percentage(item, postfix="千元")
124
127
  try:
125
128
  table_dict[index_name][(time_index, item_name)] = item
126
129
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: neurostats-API
3
- Version: 0.0.10
3
+ Version: 0.0.11
4
4
  Summary: The service of NeuroStats website
5
5
  Home-page: https://github.com/NeurowattStats/NeuroStats_API.git
6
6
  Author: JasonWang@Neurowatt
@@ -1,14 +1,14 @@
1
- neurostats_API/__init__.py,sha256=WzeHQJ3r8kPKWXSBuphad80I6bJ-GJORgQF6wSrYmhI,20
1
+ neurostats_API/__init__.py,sha256=oR5iCRZvbIRoODxS1VocreTo19N5L8Omvx_AgflzOO0,20
2
2
  neurostats_API/cli.py,sha256=UJSWLIw03P24p-gkBb6JSEI5dW5U12UvLf1L8HjQD-o,873
3
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=3FzVuDPm88tgljvu5gIxVXcZYQWebMrGnM5_ch9Vdgw,5549
4
+ neurostats_API/fetchers/__init__.py,sha256=27kdeBuM7dNBRcIyQ1u863CYw0P_DQz-I1G6iSFDq-c,357
5
+ neurostats_API/fetchers/balance_sheet.py,sha256=sQv4Gk5uoKURLEdh57YknOQWiyVwaXJ2Mw75jxNqUS0,5804
6
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=hmMurCSCEjYBQ6gRmVgoX6T57g8MjsdWec6LdVztVoE,27813
9
- neurostats_API/fetchers/institution.py,sha256=EYxPebJrcCMm7fW2nBlu4bVsksMMxgcQh16jJ1NxP6I,3384
10
- neurostats_API/fetchers/month_revenue.py,sha256=QmhMAO8jbkjg2R1LR0TAPE3bmDnyuLNjnD24ZsFkTBU,3501
11
- neurostats_API/fetchers/profit_lose.py,sha256=nc9YVi5kv3_loF8m82h3Fxpms7573_rPP9OM36bCK3A,5455
7
+ neurostats_API/fetchers/cash_flow.py,sha256=TY7VAWVXkj5-mzH5Iu0sIE-oV8MvGmmDy0URNotNV1E,7614
8
+ neurostats_API/fetchers/finance_overview.py,sha256=PxUdWY0x030olYMLcCHDBn068JLmCE2RTOce1dxs5vM,27753
9
+ neurostats_API/fetchers/institution.py,sha256=aODtsFyQcnD9PnMeaehMAN9wZdZ2a0EqSSZO57dY9RE,7691
10
+ neurostats_API/fetchers/month_revenue.py,sha256=nixX2llzjCFr2m2YVjxrSfkBusnZPrPb2dRDq1XLGhw,4251
11
+ neurostats_API/fetchers/profit_lose.py,sha256=xlLNsGSy4Azf4HyZyYaX3dFad-ACO-vuQToBooZi1_w,5698
12
12
  neurostats_API/fetchers/tech.py,sha256=wH1kkqiETQhF0HAhk-UIiucnZ3EiL85Q-yMWCcVOiFM,11395
13
13
  neurostats_API/fetchers/value_invest.py,sha256=O5IKC8Nl7p5-E-1zoyAyWtiDznaxNemeabanmaHDdJs,3327
14
14
  neurostats_API/tools/balance_sheet.yaml,sha256=yTxrWh7m4K3LnaNunETidfNzl6S4Bf58VIg9U38XShQ,648
@@ -21,7 +21,7 @@ neurostats_API/utils/data_process.py,sha256=mDznLqAAZ7gFX3LlJkJvtrMPt38Lh5-NONqg
21
21
  neurostats_API/utils/datetime.py,sha256=XJya4G8b_-ZOaBbMXgQjWh2MC4wc-o6goQ7EQJQMWrQ,773
22
22
  neurostats_API/utils/db_client.py,sha256=OYe6yazcR4Aa6jYmy47JrryUeh2NnKGqY2K_lSZe6i8,455
23
23
  neurostats_API/utils/fetcher.py,sha256=VbrUhjA-GG5AyjPX2SHtFIbZM4dm3jo0RgZzuCbb_Io,40927
24
- neurostats_API-0.0.10.dist-info/METADATA,sha256=2zDomUXohUsLpnl4MeD6anZimrhnWvd8n0Rv8d4qkUk,18529
25
- neurostats_API-0.0.10.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
26
- neurostats_API-0.0.10.dist-info/top_level.txt,sha256=nSlQPMG0VtXivJyedp4Bkf86EOy2TpW10VGxolXrqnU,15
27
- neurostats_API-0.0.10.dist-info/RECORD,,
24
+ neurostats_API-0.0.11.dist-info/METADATA,sha256=Tddw5SxRekTkTtemDXgYPoiJf9sxICyRkdlFAbvniSM,18529
25
+ neurostats_API-0.0.11.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
26
+ neurostats_API-0.0.11.dist-info/top_level.txt,sha256=nSlQPMG0VtXivJyedp4Bkf86EOy2TpW10VGxolXrqnU,15
27
+ neurostats_API-0.0.11.dist-info/RECORD,,