analyser_hj3415 2.10.1__tar.gz → 2.10.3__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/PKG-INFO +1 -1
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/cli.py +2 -3
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/eval.py +1 -1
- analyser_hj3415-2.10.3/analyser_hj3415/score.py +159 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/tsa.py +23 -37
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/pyproject.toml +1 -1
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/.gitignore +0 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/README.md +0 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/__init__.py +0 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/workroom/__init__.py +0 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/workroom/mysklearn.py +0 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/workroom/mysklearn2.py +0 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/workroom/score.py +0 -0
- {analyser_hj3415-2.10.1 → analyser_hj3415-2.10.3}/analyser_hj3415/workroom/trash.py +0 -0
@@ -114,7 +114,7 @@ def analyser_manager():
|
|
114
114
|
|
115
115
|
args = parser.parse_args()
|
116
116
|
|
117
|
-
from
|
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
|
-
|
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
|
7
|
+
from .cli import AnalyserSettingsManager
|
8
8
|
from collections import OrderedDict
|
9
9
|
import logging
|
10
10
|
|
@@ -0,0 +1,159 @@
|
|
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("Red score 계산중..")
|
87
|
+
red_score = self.red.get(verbose=False).score
|
88
|
+
|
89
|
+
score_logger.info("Mil data 계산중..")
|
90
|
+
mil_data = self.mil.get(verbose=False)
|
91
|
+
|
92
|
+
score_logger.info("\tProphet 최근 데이터 조회중..")
|
93
|
+
prophet_score = self.prophet.scoring()
|
94
|
+
|
95
|
+
return {
|
96
|
+
'name': self.name,
|
97
|
+
'시가총액': 시가총액,
|
98
|
+
'is_update_c108': is_update_c108,
|
99
|
+
'red_score': red_score,
|
100
|
+
'이익지표': mil_data.이익지표,
|
101
|
+
'주주수익률': mil_data.주주수익률,
|
102
|
+
'prophet_score': prophet_score,
|
103
|
+
}
|
104
|
+
data_dict = myredis.Base.fetch_and_cache_data(redis_name, refresh, fetch_score, timer=expire_time_h * 3600)
|
105
|
+
return data_dict
|
106
|
+
|
107
|
+
@classmethod
|
108
|
+
def ranking(self, refresh=False, expire_time_h=24, top='all') -> OrderedDict:
|
109
|
+
"""
|
110
|
+
prophet score 기준으로 정렬하여 ordered dict로 반환함
|
111
|
+
|
112
|
+
Parameters:
|
113
|
+
refresh (bool): Specifies whether to refresh the ranking data. Defaults
|
114
|
+
to `False`.
|
115
|
+
expire_time_h (int): Time in hours after which the cached data should
|
116
|
+
expire. Defaults to `24` hours.
|
117
|
+
top (Union[str, int]): Determines how many top rankings to return.
|
118
|
+
Defaults to `'all'`. If an integer is provided, it limits the
|
119
|
+
ranking to the specified count.
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
OrderedDict: A dictionary containing the rankings, sorted in
|
123
|
+
descending order by `prophet_score`.
|
124
|
+
|
125
|
+
Raises:
|
126
|
+
ValueError: Raised if the parameter `top` is neither `'all'` nor an
|
127
|
+
integer.
|
128
|
+
"""
|
129
|
+
print("**** Start score_ranking... ****")
|
130
|
+
redis_name = 'score_ranking'
|
131
|
+
|
132
|
+
print(
|
133
|
+
f"redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time_h}h")
|
134
|
+
|
135
|
+
def fetch_ranking() -> dict:
|
136
|
+
data = {}
|
137
|
+
s = Score('005930')
|
138
|
+
for code in myredis.Corps.list_all_codes():
|
139
|
+
try:
|
140
|
+
s.code = code
|
141
|
+
except ValueError:
|
142
|
+
score_logger.error(f'score ranking error : {code}')
|
143
|
+
continue
|
144
|
+
score = s.get()
|
145
|
+
data[code] = score
|
146
|
+
return data
|
147
|
+
|
148
|
+
data_dict = myredis.Base.fetch_and_cache_data(redis_name, refresh, fetch_ranking, timer=expire_time_h * 3600)
|
149
|
+
|
150
|
+
# prophet_score를 기준으로 정렬
|
151
|
+
ranking = OrderedDict(sorted(data_dict.items(), key=lambda x: x[1]['prophet_score'], reverse=True))
|
152
|
+
|
153
|
+
if top == 'all':
|
154
|
+
return ranking
|
155
|
+
else:
|
156
|
+
if isinstance(top, int):
|
157
|
+
return OrderedDict(list(ranking.items())[:top])
|
158
|
+
else:
|
159
|
+
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
|
-
|
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 배열로 변환
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|