analyser_hj3415 2.7.8__py2.py3-none-any.whl → 2.8.0__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,24 +1,36 @@
1
+ """
2
+ Time Series Analysis
3
+ """
1
4
  import yfinance as yf
2
5
  from datetime import datetime, timedelta
3
6
  import pandas as pd
4
7
  from prophet import Prophet
5
8
  from sklearn.preprocessing import StandardScaler
6
- from utils_hj3415 import utils
9
+ from utils_hj3415 import utils, helpers
7
10
  from typing import Optional
8
11
  import plotly.graph_objs as go
9
12
  from plotly.offline import plot
10
13
  import matplotlib.pyplot as plt # Matplotlib 수동 임포트
11
14
  from db_hj3415 import myredis
15
+ from collections import OrderedDict
16
+ from analyser_hj3415 import eval
17
+
18
+ import logging
19
+ analyser_logger = helpers.setup_logger('analyser_logger', logging.WARNING)
20
+
21
+ expire_time = 3600 * 12
12
22
 
13
23
  class MyProphet:
14
24
  def __init__(self, code: str):
15
25
  assert utils.is_6digit(code), f'Invalid value : {code}'
16
- self._code = code
17
- self.name = myredis.Corps(code, 'c101').get_name()
18
- self.raw_data = self.get_raw_data()
19
-
20
26
  self.scaler = StandardScaler()
27
+
21
28
  self.model = Prophet()
29
+ self._code = code
30
+ self.name = myredis.Corps(code, 'c101').get_name()
31
+ self.raw_data = self._get_raw_data()
32
+ self.df_real = self._preprocessing_for_prophet()
33
+ self.df_forecast = self._make_forecast()
22
34
 
23
35
  @property
24
36
  def code(self) -> str:
@@ -27,11 +39,25 @@ class MyProphet:
27
39
  @code.setter
28
40
  def code(self, code: str):
29
41
  assert utils.is_6digit(code), f'Invalid value : {code}'
42
+ analyser_logger.info(f'change code : {self.code} -> {code}')
43
+ self.model = Prophet()
30
44
  self._code = code
31
45
  self.name = myredis.Corps(code, 'c101').get_name()
32
- self.raw_data = self.get_raw_data()
33
-
34
- def get_raw_data(self) -> pd.DataFrame:
46
+ self.raw_data = self._get_raw_data()
47
+ self.df_real = self._preprocessing_for_prophet()
48
+ self.df_forecast = self._make_forecast()
49
+
50
+ @staticmethod
51
+ def is_valid_date(date_string):
52
+ try:
53
+ # %Y-%m-%d 형식으로 문자열을 datetime 객체로 변환 시도
54
+ datetime.strptime(date_string, '%Y-%m-%d')
55
+ return True
56
+ except ValueError:
57
+ # 변환이 실패하면 ValueError가 발생, 형식이 맞지 않음
58
+ return False
59
+
60
+ def _get_raw_data(self) -> pd.DataFrame:
35
61
  """
36
62
  야후에서 해당 종목의 4년간 주가 raw data를 받아온다.
37
63
  :return:
@@ -48,7 +74,7 @@ class MyProphet:
48
74
  end=today.strftime('%Y-%m-%d')
49
75
  )
50
76
 
51
- def preprocessing_for_prophet(self) -> pd.DataFrame:
77
+ def _preprocessing_for_prophet(self) -> pd.DataFrame:
52
78
  """
53
79
  Prophet이 사용할 수 있도록 데이터 준비
54
80
  ds는 날짜, y는 주가
@@ -61,14 +87,11 @@ class MyProphet:
61
87
  df['volume_scaled'] = self.scaler.fit_transform(df[['volume']])
62
88
  return df
63
89
 
64
- def make_forecast(self) -> pd.DataFrame:
65
- # Prophet을 위한 dataframe 만들기
66
- df_for_prophet = self.preprocessing_for_prophet()
67
-
90
+ def _make_forecast(self) -> pd.DataFrame:
68
91
  # 정규화된 'volume_scaled' 변수를 외부 변수로 추가
69
92
  self.model.add_regressor('volume_scaled')
70
93
 
71
- self.model.fit(df_for_prophet)
94
+ self.model.fit(self.df_real)
72
95
 
73
96
  # 향후 180일 동안의 주가 예측
74
97
  future = self.model.make_future_dataframe(periods=180)
@@ -80,30 +103,36 @@ class MyProphet:
80
103
  forecast = self.model.predict(future)
81
104
  return forecast
82
105
 
106
+ def get_yhat(self) -> dict:
107
+ """
108
+ 예측하는 첫째날의 예측 데이터를 반환한다.
109
+ :return: {'ds':..., 'yhat':.., 'yhat_lower':.., 'yhat_upper':..,}
110
+ """
111
+ df = self.df_forecast
112
+ analyser_logger.debug(df)
113
+ yhat_dict = df.iloc[0][['ds', 'yhat_lower', 'yhat_upper', 'yhat']].to_dict()
114
+ analyser_logger.info(yhat_dict)
115
+ return yhat_dict
116
+
83
117
  def export_to(self, to="str") -> Optional[str]:
84
118
  """
85
119
  prophet과 plotly로 그래프를 그려서 html을 문자열로 반환
86
120
  :param to: str, png, htmlfile, show
87
121
  :return:
88
122
  """
89
- # 실제 데이터
90
- df = self.preprocessing_for_prophet()
91
- # 예측 데이터
92
- forecast = self.make_forecast()
93
-
94
123
  # Plotly를 사용한 시각화
95
124
  fig = go.Figure()
96
125
 
97
126
  # 실제 데이터
98
- fig.add_trace(go.Scatter(x=df['ds'], y=df['y'], mode='markers', name='실제주가'))
127
+ fig.add_trace(go.Scatter(x=self.df_real['ds'], y=self.df_real['y'], mode='markers', name='실제주가'))
99
128
  # 예측 데이터
100
- fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat'], mode='lines', name='예측치'))
129
+ fig.add_trace(go.Scatter(x=self.df_forecast['ds'], y=self.df_forecast['yhat'], mode='lines', name='예측치'))
101
130
 
102
131
  # 상한/하한 구간
103
132
  fig.add_trace(
104
- go.Scatter(x=forecast['ds'], y=forecast['yhat_upper'], fill=None, mode='lines', name='상한'))
133
+ go.Scatter(x=self.df_forecast['ds'], y=self.df_forecast['yhat_upper'], fill=None, mode='lines', name='상한'))
105
134
  fig.add_trace(
106
- go.Scatter(x=forecast['ds'], y=forecast['yhat_lower'], fill='tonexty', mode='lines', name='하한'))
135
+ go.Scatter(x=self.df_forecast['ds'], y=self.df_forecast['yhat_lower'], fill='tonexty', mode='lines', name='하한'))
107
136
 
108
137
  fig.update_layout(
109
138
  title=f'{self.code} {self.name} 주가 예측 그래프(prophet)',
@@ -130,15 +159,46 @@ class MyProphet:
130
159
  return None
131
160
  elif to == 'show':
132
161
  # 예측 결과 출력
133
- print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
162
+ print(self.df_forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
134
163
  # 예측 결과 시각화 (Matplotlib 사용)
135
- fig = self.model.plot(forecast)
164
+ fig = self.model.plot(self.df_forecast)
136
165
  # 추세 및 계절성 시각화
137
- fig2 = self.model.plot_components(forecast)
166
+ fig2 = self.model.plot_components(self.df_forecast)
138
167
  plt.show() # 시각화 창 띄우기
139
168
  else:
140
169
  Exception("to 인자가 맞지 않습니다.")
141
170
 
171
+ @classmethod
172
+ def ranking(cls, refresh = False) -> OrderedDict:
173
+ """
174
+ 가장 최근 날짜의 랭킹 분석
175
+ :param refresh:
176
+ :return:
177
+ """
178
+ print("**** Start myprophet_ranking... ****")
179
+ redis_name = 'myprophet_ranking'
180
+
181
+ print(
182
+ f"redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time / 3600}h")
183
+
184
+ def fetch_ranking() -> dict:
185
+ data = {}
186
+ p = MyProphet('005930')
187
+ for i, code in enumerate(myredis.Corps.list_all_codes()):
188
+ p.code = code
189
+ recent_price = p._preprocessing_for_prophet().iloc[-1]['y']
190
+ yhat_dict = p.get_yhat()
191
+ analyser_logger.info(f'recent_price: {recent_price}, yhat_dict: {yhat_dict}')
192
+ yhat_lower = int(yhat_dict['yhat_lower'])
193
+ if recent_price < yhat_lower:
194
+ deviation = int(eval.Tools.cal_deviation(recent_price, yhat_lower))
195
+ data[code] = deviation
196
+ print(f"{i}.{p.code}/{p.name} 최근가격:{recent_price} 기대하한값:{yhat_lower} 편차:{deviation}")
197
+ return data
198
+
199
+ data_dict = myredis.Base.fetch_and_cache_data(redis_name, refresh, fetch_ranking, timer=expire_time)
200
+
201
+ return OrderedDict(sorted(data_dict.items(), key=lambda item: item[1], reverse=True))
142
202
 
143
203
 
144
204
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: analyser_hj3415
3
- Version: 2.7.8
3
+ Version: 2.8.0
4
4
  Summary: Stock analyser and database processing programs
5
5
  Author-email: Hyungjin Kim <hj3415@gmail.com>
6
6
  Description-Content-Type: text/markdown
@@ -2,15 +2,15 @@ analyser_hj3415/.DS_Store,sha256=qr9-0FPn5CFKe6kEu8_dWCNhzQ0sN7bwQgffKsaJEEo,614
2
2
  analyser_hj3415/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  analyser_hj3415/cli.py,sha256=7ys-b9H_tJAbLLi_XpjmEvDiyNHddpg9F1FNAACfWnE,11005
4
4
  analyser_hj3415/eval.py,sha256=4F0GIknCogAhv_iTq8auLrmwW20u8kH0HY0fP4SaVa4,39099
5
- analyser_hj3415/myprophet.py,sha256=N_eUzAmrbEuqJBJ9OqbnMrHC3_kc3JXGq6pND5o4yuE,5096
5
+ analyser_hj3415/tsa.py,sha256=4fg92xzEnp9kChvEzXbnAv6jGLuDK4zMaZjBoobp6I0,7649
6
6
  analyser_hj3415/workroom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  analyser_hj3415/workroom/lstm.py,sha256=gF7i1NqPOhNysvkSQcC_mkOmvLk96jPxoqajZ-FFD8I,4078
8
8
  analyser_hj3415/workroom/mysklearn.py,sha256=wJXKz5MqqTzADdG2mqRMMzc_G9RzwYjj5_j4gyOopxQ,2030
9
9
  analyser_hj3415/workroom/mysklearn2.py,sha256=1lIy6EWEQHkOzDS-av8U0zQH6DuCLKWMI73dnJx5KRs,1495
10
10
  analyser_hj3415/workroom/score.py,sha256=P6nHBJYmyhigGtT4qna4BmNtvt4B93b7SKyzdstJK24,17376
11
11
  analyser_hj3415/workroom/trash.py,sha256=zF-W0piqkGr66UP6-iybo9EXh2gO0RP6R1FnIpsGkl8,12262
12
- analyser_hj3415-2.7.8.dist-info/entry_points.txt,sha256=ZfjPnJuH8SzvhE9vftIPMBIofsc65IAWYOhqOC_L5ck,65
13
- analyser_hj3415-2.7.8.dist-info/LICENSE,sha256=QVKTp0dTnB5xG8RLgG17LwSWCKNEzYoVVM6KjoCPKc0,1079
14
- analyser_hj3415-2.7.8.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
15
- analyser_hj3415-2.7.8.dist-info/METADATA,sha256=Ru0TFe19ItTPkffO_39zz7vuX0b78V7EZoiO4f1wCEM,6607
16
- analyser_hj3415-2.7.8.dist-info/RECORD,,
12
+ analyser_hj3415-2.8.0.dist-info/entry_points.txt,sha256=ZfjPnJuH8SzvhE9vftIPMBIofsc65IAWYOhqOC_L5ck,65
13
+ analyser_hj3415-2.8.0.dist-info/LICENSE,sha256=QVKTp0dTnB5xG8RLgG17LwSWCKNEzYoVVM6KjoCPKc0,1079
14
+ analyser_hj3415-2.8.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
15
+ analyser_hj3415-2.8.0.dist-info/METADATA,sha256=4Zf9g7uum4fIQqqY1IF0_HRzQwT-JAJvAPdfRY0eW9Q,6607
16
+ analyser_hj3415-2.8.0.dist-info/RECORD,,