analyser_hj3415 2.10.1__tar.gz → 2.10.2__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: analyser_hj3415
3
- Version: 2.10.1
3
+ Version: 2.10.2
4
4
  Summary: Stock analyser and database processing programs
5
5
  Requires-Python: >=3.6
6
6
  Description-Content-Type: text/markdown
@@ -114,7 +114,7 @@ def analyser_manager():
114
114
 
115
115
  args = parser.parse_args()
116
116
 
117
- from analyser_hj3415 import eval, tsa
117
+ from . import eval, tsa, score
118
118
 
119
119
  if args.type == 'red':
120
120
  if args.command == 'get':
@@ -206,8 +206,7 @@ def analyser_manager():
206
206
 
207
207
  elif args.type == 'prophet':
208
208
  if args.command == 'ranking':
209
- myprophet = tsa.MyProphet
210
- result = myprophet.ranking(refresh=args.refresh, expire_time_h=48)
209
+ result = score.Score.ranking(refresh=args.refresh, expire_time_h=48)
211
210
  print(result)
212
211
  mymongo.Logs.save('cli','INFO', 'run >> analyser prophet ranking')
213
212
 
@@ -4,7 +4,7 @@ from utils_hj3415 import utils, helpers
4
4
  from typing import Tuple
5
5
  from db_hj3415 import myredis, mymongo
6
6
  import math
7
- from analyser_hj3415.cli import AnalyserSettingsManager
7
+ from .cli import AnalyserSettingsManager
8
8
  from collections import OrderedDict
9
9
  import logging
10
10
 
@@ -0,0 +1,157 @@
1
+ from db_hj3415 import myredis
2
+ from utils_hj3415 import utils, helpers
3
+ import datetime
4
+ from collections import OrderedDict
5
+ from . import eval, tsa
6
+
7
+ import logging
8
+
9
+ score_logger = helpers.setup_logger('score_logger', logging.WARNING)
10
+
11
+
12
+ def is_within_last_three_days(date_to_check: datetime.datetime.date) -> bool:
13
+ today = datetime.datetime.now().date() # 현재 날짜 (시간은 무시)
14
+ # print('today - ', today)
15
+ three_days_ago = today - datetime.timedelta(days=3) # 3일 전 날짜
16
+ return three_days_ago <= date_to_check <= today
17
+
18
+
19
+ class Score:
20
+ def __init__(self, code):
21
+ self._code = code
22
+ self.c101 = myredis.C101(code)
23
+ self.name = self.c101.get_name()
24
+ self.c108 = myredis.C108(code)
25
+ self.dart = myredis.Dart(code)
26
+ self.red = eval.Red(code)
27
+ self.mil = eval.Mil(code)
28
+ self.lstm = tsa.MyLSTM(code)
29
+ self.prophet = tsa.MyProphet(code)
30
+
31
+ @property
32
+ def code(self) -> str:
33
+ return self._code
34
+
35
+ @code.setter
36
+ def code(self, code: str):
37
+ assert utils.is_6digit(code), f'Invalid value : {code}'
38
+ score_logger.info(f'change code : {self.code} -> {code}')
39
+ self._code = code
40
+ self.c101.code = code
41
+ self.name = self.c101.get_name()
42
+ self.c108.code = code
43
+ self.dart.code = code
44
+ self.red.code = code
45
+ self.mil.code = code
46
+ self.lstm.code = code
47
+ self.prophet.code = code
48
+
49
+ def get(self, refresh=False, expire_time_h=24) -> dict:
50
+ """
51
+ 한 종목의 각분야 평가를 모아서 딕셔너리 형태로 반환함.
52
+ redis_name = self.code + '_score'
53
+
54
+ Returns:
55
+ dict: A dictionary containing the following key-value pairs:
56
+
57
+ - 'code': str - 종목코드
58
+ - 'name': str - 종목명
59
+ - '시가총액': str - 시가총액
60
+ - 'is_update_c108': bool - 최근 3일 이내에 c108이 없데이트 되었는가
61
+ - 'is_update_dart': bool - 최근 3일 이내에 Dart가 없데이트 되었는가
62
+ - 'red_score': float - Red score
63
+ - '이익지표': float - Mil의 이익지표
64
+ - '주주수익률': float - Mil의 주주수익률
65
+ - 'is_lstm_up': Union[bool, None] - lstm 예측치가 상승인지 아닌지, returns None - 데이터가 없으면..
66
+ - 'prophet_score': int - prophet score
67
+ """
68
+ print(f"{self.code}/{self.name}의 scoring을 시작합니다.")
69
+ redis_name = self.code + '_score'
70
+ print(
71
+ f"redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time_h}h")
72
+
73
+ def fetch_score() -> dict:
74
+ score_logger.info("시가총액 데이터 추출중..")
75
+ 시가총액 = utils.format_large_number(int(self.c101.get_recent()['시가총액']))
76
+
77
+ score_logger.info("C108 최근 데이터 추출중..")
78
+ # c108이 최근에 업데이트 되었는지...
79
+ c108_recent_date = self.c108.get_recent_date()
80
+ # print('code - ', code, ' | c108 recent date - ', c108_recent_date.date())
81
+ if c108_recent_date is None:
82
+ is_update_c108 = False
83
+ else:
84
+ is_update_c108 = is_within_last_three_days(c108_recent_date.date())
85
+
86
+ score_logger.info("Dart 최근 데이터 추출중..")
87
+ # dart가 최근에 업데이트 되었는지...
88
+ dart_recent_date = self.dart.get_recent_date()
89
+ # print('code - ', code, ' | dart recent date - ', dart_recent_date.date())
90
+ if dart_recent_date is None:
91
+ is_update_dart = False
92
+ else:
93
+ is_update_dart = is_within_last_three_days(dart_recent_date.date())
94
+
95
+ score_logger.info("Red score 계산중..")
96
+ red_score = self.red.get(verbose=False).score
97
+
98
+ score_logger.info("Mil data 계산중..")
99
+ mil_data = self.mil.get(verbose=False)
100
+
101
+ score_logger.info("Lstm 최근 데이터 조회중..")
102
+ if myredis.Base.exists(f'{self.code}_mylstm_predictions'):
103
+ is_lstm_up = self.lstm.is_up()
104
+ else:
105
+ is_lstm_up = None
106
+
107
+ score_logger.info("\tProphet 최근 데이터 조회중..")
108
+ prophet_score = self.prophet.scoring()
109
+
110
+ return {
111
+ 'code': self.code,
112
+ 'name': self.name,
113
+ '시가총액': 시가총액,
114
+ 'is_update_c108': is_update_c108,
115
+ 'is_update_dart': is_update_dart,
116
+ 'red_score': red_score,
117
+ '이익지표': mil_data.이익지표,
118
+ '주주수익률': mil_data.주주수익률,
119
+ 'is_lstm_up': is_lstm_up,
120
+ 'prophet_score': prophet_score,
121
+ }
122
+ data_dict = myredis.Base.fetch_and_cache_data(redis_name, refresh, fetch_score, timer=expire_time_h * 3600)
123
+ return data_dict
124
+
125
+ @classmethod
126
+ def ranking(self, refresh=False, expire_time_h=24, top='all') -> OrderedDict:
127
+ print("**** Start score_ranking... ****")
128
+ redis_name = 'score_ranking'
129
+
130
+ print(
131
+ f"redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time_h}h")
132
+
133
+ def fetch_ranking() -> dict:
134
+ data = {}
135
+ s = Score('005930')
136
+ for code in myredis.Corps.list_all_codes():
137
+ try:
138
+ s.code = code
139
+ except ValueError:
140
+ score_logger.error(f'score ranking error : {code}')
141
+ continue
142
+ score = s.get()
143
+ data[code] = score
144
+ return data
145
+
146
+ data_dict = myredis.Base.fetch_and_cache_data(redis_name, refresh, fetch_ranking, timer=expire_time_h * 3600)
147
+
148
+ # prophet_score를 기준으로 정렬
149
+ ranking = OrderedDict(sorted(data_dict.items(), key=lambda x: x[1]['prophet_score'], reverse=True))
150
+
151
+ if top == 'all':
152
+ return ranking
153
+ else:
154
+ if isinstance(top, int):
155
+ return OrderedDict(list(ranking.items())[:top])
156
+ else:
157
+ raise ValueError("top 인자는 'all' 이나 int형 이어야 합니다.")
@@ -193,6 +193,22 @@ class MyProphet:
193
193
  Exception("to 인자가 맞지 않습니다.")
194
194
 
195
195
  def scoring(self) -> int:
196
+ """
197
+ prophet의 yhat_lower 예측치와 주가를 비교하여 주가가 낮으면 양의 점수를 높으면 음의 점수를 준다.
198
+
199
+ Returns:
200
+ int: The calculated score based on the deviation between the recent price
201
+ and the expected lower limit.
202
+
203
+ Parameters:
204
+ None
205
+
206
+ Raises:
207
+ AttributeError: Raised if the necessary attributes like `df_real` or methods like `get_yhat`
208
+ are not correctly set or implemented.
209
+ KeyError: Raised if the expected keys (`'yhat_lower'` or `'y'`) are not found in the data involved.
210
+ ValueError: Raised if the format of data does not conform to expected structure for calculations.
211
+ """
196
212
  last_real_data = self.df_real.iloc[-1]
197
213
  recent_price = last_real_data['y']
198
214
  recent_date = datetime.strftime(last_real_data['ds'], '%Y-%m-%d')
@@ -204,45 +220,9 @@ class MyProphet:
204
220
  score = -deviation
205
221
  else:
206
222
  score = deviation
207
- print(f"{self.code}/{self.name} date: {recent_date} 가격:{recent_price} 기대하한값:{yhat_lower} 편차:{deviation} score:{score}")
223
+ tsa_logger.info(f"{self.code}/{self.name} date: {recent_date} 가격:{recent_price} 기대하한값:{yhat_lower} 편차:{deviation} score:{score}")
208
224
  return score
209
225
 
210
- @classmethod
211
- def ranking(cls, refresh = False, expire_time_h = 24, top='all') -> OrderedDict:
212
- """
213
- 가장 최근 날짜의 랭킹 분석
214
- :param refresh:
215
- :return:
216
- """
217
- print("**** Start myprophet_ranking... ****")
218
- redis_name = 'myprophet_ranking'
219
-
220
- print(
221
- f"redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time_h}h")
222
-
223
- def fetch_ranking() -> dict:
224
- data = {}
225
- p = MyProphet('005930')
226
- for code in myredis.Corps.list_all_codes():
227
- try:
228
- p.code = code
229
- except ValueError:
230
- tsa_logger.error(f'myprophet ranking error : {code}/{myredis.Corps(code, "c101").get_name()}')
231
- continue
232
- score = p.scoring()
233
- data[code] = score
234
- return data
235
-
236
- data_dict = myredis.Base.fetch_and_cache_data(redis_name, refresh, fetch_ranking, timer=expire_time_h * 3600)
237
-
238
- ranking = OrderedDict(sorted(data_dict.items(), key=lambda item: item[1], reverse=True))
239
- if top == 'all':
240
- return ranking
241
- else:
242
- if isinstance(top, int):
243
- return OrderedDict(list(ranking.items())[:top])
244
- else:
245
- raise ValueError("top 인자는 'all' 이나 int형 이어야 합니다.")
246
226
 
247
227
  @dataclass
248
228
  class LSTMData:
@@ -698,6 +678,12 @@ class MyLSTM:
698
678
  plt.show()"""
699
679
 
700
680
  def is_up(self)-> bool:
681
+ """
682
+ lstm 데이터가 증가하는 추세인지 확인후 참/거짓 반환
683
+
684
+ Returns:
685
+ bool: True if the data is strictly increasing, False otherwise.
686
+ """
701
687
  # 튜플의 [0]은 날짜 [1]은 값 배열
702
688
  data = self.get_final_predictions(refresh=False, expire_time_h=24)[1]
703
689
  # 데이터를 1D 배열로 변환
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
5
5
 
6
6
  [project]
7
7
  name = "analyser_hj3415"
8
- version = "2.10.1"
8
+ version = "2.10.2"
9
9
  description = "Stock analyser and database processing programs"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.6"