analyser_hj3415 2.8.3__tar.gz → 2.9.0__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/PKG-INFO +1 -1
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/cli.py +19 -6
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/eval.py +71 -71
- analyser_hj3415-2.9.0/analyser_hj3415/tsa.py +615 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/pyproject.toml +1 -1
- analyser_hj3415-2.8.3/analyser_hj3415/tsa.py +0 -207
- analyser_hj3415-2.8.3/analyser_hj3415/workroom/lstm.py +0 -115
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.DS_Store +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.gitattributes +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.gitignore +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.idea/.gitignore +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.idea/analyser-hj3415.iml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.idea/misc.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.idea/modules.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/.idea/vcs.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/LICENSE +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/README.md +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/.DS_Store +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/__init__.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/workroom/__init__.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/workroom/mysklearn.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/workroom/mysklearn2.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/workroom/score.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.0}/analyser_hj3415/workroom/trash.py +0 -0
@@ -41,14 +41,22 @@ def analyser_manager():
|
|
41
41
|
parser = argparse.ArgumentParser(description="Analyser Commands")
|
42
42
|
type_subparsers = parser.add_subparsers(dest='type', help='분석 타입')
|
43
43
|
|
44
|
-
#
|
45
|
-
|
46
|
-
|
44
|
+
# prophet 명령어 서브파서
|
45
|
+
prophet_parser = type_subparsers.add_parser('prophet', help='MyProphet 타입')
|
46
|
+
prophet_subparser = prophet_parser.add_subparsers(dest='command', help='prophet 관련된 명령')
|
47
47
|
# ranking 파서
|
48
|
-
ranking_parser =
|
48
|
+
ranking_parser = prophet_subparser.add_parser('ranking', help='prophet 랭킹 책정 및 레디스 저장')
|
49
49
|
ranking_parser.add_argument('-r', '--refresh', action='store_true', help='래디스 캐시를 사용하지 않고 강제로 재계산 할지')
|
50
50
|
ranking_parser.add_argument('-n', '--noti', action='store_true', help='작업 완료 후 메시지 전송 여부')
|
51
51
|
|
52
|
+
# lstm 명령어 서브파서
|
53
|
+
lstm_parser = type_subparsers.add_parser('lstm', help='MyLSTM 타입')
|
54
|
+
lstm_subparser = lstm_parser.add_subparsers(dest='command', help='lstm 관련된 명령')
|
55
|
+
# caching 파서
|
56
|
+
caching_parser = lstm_subparser.add_parser('caching', help='lstm 랭킹 책정 및 레디스 저장')
|
57
|
+
caching_parser.add_argument('-r', '--refresh', action='store_true', help='래디스 캐시를 사용하지 않고 강제로 재계산 할지')
|
58
|
+
caching_parser.add_argument('-n', '--noti', action='store_true', help='작업 완료 후 메시지 전송 여부')
|
59
|
+
|
52
60
|
# red 명령어 서브파서
|
53
61
|
red_parser = type_subparsers.add_parser('red', help='red 타입')
|
54
62
|
red_subparser = red_parser.add_subparsers(dest='command', help='red 관련된 명령')
|
@@ -203,12 +211,17 @@ def analyser_manager():
|
|
203
211
|
pprint.pprint(growth.get(args.refresh))
|
204
212
|
if args.noti:
|
205
213
|
noti.telegram_to('manager', f"오늘의 Growth({args.code})를 레디스 캐시에 저장했습니다.(유효 12시간)")
|
206
|
-
elif args.type == '
|
214
|
+
elif args.type == 'prophet':
|
207
215
|
if args.command == 'ranking':
|
208
216
|
result = tsa.MyProphet.ranking(refresh=args.refresh)
|
209
217
|
print(result)
|
210
218
|
if args.noti:
|
211
|
-
noti.telegram_to('manager', "오늘의
|
219
|
+
noti.telegram_to('manager', "오늘의 prophet ranking을 레디스캐시에 저장했습니다.(유효 24시간)")
|
220
|
+
elif args.type == 'lstm':
|
221
|
+
if args.command == 'caching':
|
222
|
+
result = tsa.MyLSTM('005930').caching_based_on_prophet_ranking(refresh=args.refresh)
|
223
|
+
if args.noti:
|
224
|
+
noti.telegram_to('manager', "오늘의 lstm caching을 레디스캐시에 저장했습니다.(유효 24시간)")
|
212
225
|
elif args.type == 'setting':
|
213
226
|
if args.command == 'set':
|
214
227
|
settings_manager.set_value(args.title, args.value)
|
@@ -8,7 +8,7 @@ from analyser_hj3415.cli import AnalyserSettingsManager
|
|
8
8
|
from collections import OrderedDict
|
9
9
|
import logging
|
10
10
|
|
11
|
-
|
11
|
+
eval_logger = helpers.setup_logger('eval_logger', logging.WARNING)
|
12
12
|
|
13
13
|
expire_time = 3600 * 12
|
14
14
|
|
@@ -48,30 +48,30 @@ class Tools:
|
|
48
48
|
"""
|
49
49
|
name = myredis.Corps(c103.code, 'c101').get_name(refresh=refresh)
|
50
50
|
|
51
|
-
|
51
|
+
eval_logger.info(f'{c103.code} / {name} Tools : 당기순이익 계산.. refresh : {refresh}')
|
52
52
|
c103.page = 'c103재무상태표q'
|
53
53
|
|
54
54
|
d1, 지배당기순이익 = c103.latest_value_pop2('*(지배)당기순이익', refresh)
|
55
|
-
|
55
|
+
eval_logger.debug(f"*(지배)당기순이익: {지배당기순이익}")
|
56
56
|
|
57
57
|
if math.isnan(지배당기순이익):
|
58
|
-
|
58
|
+
eval_logger.warning(f"{c103.code} / {name} - (지배)당기순이익이 없는 종목. 수동으로 계산합니다.")
|
59
59
|
c103.page = 'c103손익계산서q'
|
60
60
|
d2, 최근4분기당기순이익 = c103.sum_recent_4q('당기순이익', refresh)
|
61
|
-
|
61
|
+
eval_logger.debug(f"{c103.code} / {name} - 최근4분기당기순이익 : {최근4분기당기순이익}")
|
62
62
|
c103.page = 'c103재무상태표y'
|
63
63
|
d3, 비지배당기순이익 = c103.latest_value_pop2('*(비지배)당기순이익', refresh)
|
64
|
-
|
64
|
+
eval_logger.debug(f"{c103.code} / {name} - 비지배당기순이익y : {비지배당기순이익}")
|
65
65
|
# 가변리스트 언패킹으로 하나의 날짜만 사용하고 나머지는 버린다.
|
66
66
|
# 여기서 *_는 “나머지 값을 다 무시하겠다”는 의미
|
67
|
-
|
67
|
+
eval_logger.debug(f"d2:{d2}, d3: {d3}")
|
68
68
|
try:
|
69
69
|
date, *_ = Tools.date_set(d2, d3)
|
70
70
|
except ValueError:
|
71
71
|
# 날짜 데이터가 없는경우
|
72
72
|
date = ''
|
73
73
|
계산된지배당기순이익= round(최근4분기당기순이익 - utils.nan_to_zero(비지배당기순이익), 1)
|
74
|
-
|
74
|
+
eval_logger.debug(f"{c103.code} / {name} - 계산된 지배당기순이익 : {계산된지배당기순이익}")
|
75
75
|
return date, 계산된지배당기순이익
|
76
76
|
else:
|
77
77
|
return d1, 지배당기순이익
|
@@ -85,20 +85,20 @@ class Tools:
|
|
85
85
|
"""
|
86
86
|
name = myredis.Corps(c103.code, 'c101').get_name(refresh=refresh)
|
87
87
|
|
88
|
-
|
88
|
+
eval_logger.info(f'{c103.code} / {name} Tools : 유동자산계산... refresh : {refresh}')
|
89
89
|
c103.page = 'c103재무상태표q'
|
90
90
|
|
91
91
|
d, 유동자산 = c103.sum_recent_4q('유동자산', refresh)
|
92
92
|
if math.isnan(유동자산):
|
93
|
-
|
93
|
+
eval_logger.warning(f"{c103.code} / {name} - 유동자산이 없는 종목. 수동으로 계산합니다(금융관련업종일 가능성있음).")
|
94
94
|
d1, v1 = c103.latest_value_pop2('현금및예치금', refresh)
|
95
95
|
d2, v2 = c103.latest_value_pop2('단기매매금융자산', refresh)
|
96
96
|
d3, v3 = c103.latest_value_pop2('매도가능금융자산', refresh)
|
97
97
|
d4, v4 = c103.latest_value_pop2('만기보유금융자산', refresh)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
eval_logger.debug(f'{c103.code} / {name} 현금및예치금 : {d1}, {v1}')
|
99
|
+
eval_logger.debug(f'{c103.code} / {name} 단기매매금융자산 : {d2}, {v2}')
|
100
|
+
eval_logger.debug(f'{c103.code} / {name} 매도가능금융자산 : {d3}, {v3}')
|
101
|
+
eval_logger.debug(f'{c103.code} / {name} 만기보유금융자산 : {d4}, {v4}')
|
102
102
|
|
103
103
|
try:
|
104
104
|
date, *_ = Tools.date_set(d1, d2, d3, d4)
|
@@ -107,7 +107,7 @@ class Tools:
|
|
107
107
|
date = ''
|
108
108
|
계산된유동자산value = round(utils.nan_to_zero(v1) + utils.nan_to_zero(v2) + utils.nan_to_zero(v3) + utils.nan_to_zero(v4),1)
|
109
109
|
|
110
|
-
|
110
|
+
eval_logger.info(f"{c103.code} / {name} - 계산된 유동자산 : {계산된유동자산value}")
|
111
111
|
return date, 계산된유동자산value
|
112
112
|
else:
|
113
113
|
return d, 유동자산
|
@@ -121,20 +121,20 @@ class Tools:
|
|
121
121
|
"""
|
122
122
|
name = myredis.Corps(c103.code, 'c101').get_name(refresh=refresh)
|
123
123
|
|
124
|
-
|
124
|
+
eval_logger.info(f'{c103.code} / {name} Tools : 유동부채계산... refresh : {refresh}')
|
125
125
|
c103.page = 'c103재무상태표q'
|
126
126
|
|
127
127
|
d, 유동부채 = c103.sum_recent_4q('유동부채', refresh)
|
128
128
|
if math.isnan(유동부채):
|
129
|
-
|
129
|
+
eval_logger.warning(f"{c103.code} / {name} - 유동부채가 없는 종목. 수동으로 계산합니다.")
|
130
130
|
d1, v1 = c103.latest_value_pop2('당기손익인식(지정)금융부채', refresh)
|
131
131
|
d2, v2 = c103.latest_value_pop2('당기손익-공정가치측정금융부채', refresh)
|
132
132
|
d3, v3 = c103.latest_value_pop2('매도파생결합증권', refresh)
|
133
133
|
d4, v4 = c103.latest_value_pop2('단기매매금융부채', refresh)
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
134
|
+
eval_logger.debug(f'{c103.code} / {name} 당기손익인식(지정)금융부채 : {d1}, {v1}')
|
135
|
+
eval_logger.debug(f'{c103.code} / {name} 당기손익-공정가치측정금융부채 : {d2}, {v2}')
|
136
|
+
eval_logger.debug(f'{c103.code} / {name} 매도파생결합증권 : {d3}, {v3}')
|
137
|
+
eval_logger.debug(f'{c103.code} / {name} 단기매매금융부채 : {d4}, {v4}')
|
138
138
|
|
139
139
|
try:
|
140
140
|
date, *_ = Tools.date_set(d1, d2, d3, d4)
|
@@ -143,7 +143,7 @@ class Tools:
|
|
143
143
|
date = ''
|
144
144
|
계산된유동부채value = round(utils.nan_to_zero(v1) + utils.nan_to_zero(v2) + utils.nan_to_zero(v3) + utils.nan_to_zero(v4), 1)
|
145
145
|
|
146
|
-
|
146
|
+
eval_logger.info(f"{c103.code} / {name} - 계산된 유동부채 : {계산된유동부채value}")
|
147
147
|
return date, 계산된유동부채value
|
148
148
|
else:
|
149
149
|
return d, 유동부채
|
@@ -192,7 +192,7 @@ class Red:
|
|
192
192
|
|
193
193
|
def __init__(self, code: str):
|
194
194
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
195
|
-
|
195
|
+
eval_logger.debug(f"Red : 초기화 ({code})")
|
196
196
|
self.c101 = myredis.C101(code)
|
197
197
|
self.c103 = myredis.C103(code, 'c103재무상태표q')
|
198
198
|
|
@@ -209,7 +209,7 @@ class Red:
|
|
209
209
|
@code.setter
|
210
210
|
def code(self, code: str):
|
211
211
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
212
|
-
|
212
|
+
eval_logger.debug(f"Red : 종목코드 변경({self.code} -> {code})")
|
213
213
|
self.c101.code = code
|
214
214
|
self.c103.code = code
|
215
215
|
|
@@ -222,21 +222,21 @@ class Red:
|
|
222
222
|
일반적인 경우로 비유동부채를 찾아서 반환한다.\n
|
223
223
|
금융기관의 경우는 간접적으로 계산한다.\n
|
224
224
|
"""
|
225
|
-
|
225
|
+
eval_logger.info(f'In the calc비유동부채... refresh : {refresh}')
|
226
226
|
self.c103.page = 'c103재무상태표q'
|
227
227
|
|
228
228
|
d, 비유동부채 = self.c103.sum_recent_4q('비유동부채', refresh)
|
229
229
|
if math.isnan(비유동부채):
|
230
|
-
|
230
|
+
eval_logger.warning(f"{self} - 비유동부채가 없는 종목. 수동으로 계산합니다.")
|
231
231
|
# 보험관련업종은 예수부채가 없는대신 보험계약부채가 있다...
|
232
232
|
d1, v1 = self.c103.latest_value_pop2('예수부채', refresh)
|
233
233
|
d2, v2 = self.c103.latest_value_pop2('보험계약부채(책임준비금)', refresh)
|
234
234
|
d3, v3 = self.c103.latest_value_pop2('차입부채', refresh)
|
235
235
|
d4, v4 = self.c103.latest_value_pop2('기타부채', refresh)
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
236
|
+
eval_logger.debug(f'예수부채 : {d1}, {v1}')
|
237
|
+
eval_logger.debug(f'보험계약부채(책임준비금) : {d2}, {v2}')
|
238
|
+
eval_logger.debug(f'차입부채 : {d3}, {v3}')
|
239
|
+
eval_logger.debug(f'기타부채 : {d4}, {v4}')
|
240
240
|
|
241
241
|
try:
|
242
242
|
date, *_ = Tools.date_set(d1, d2, d3, d4)
|
@@ -244,7 +244,7 @@ class Red:
|
|
244
244
|
# 날짜 데이터가 없는경우
|
245
245
|
date = ''
|
246
246
|
계산된비유동부채value = round(utils.nan_to_zero(v1) + utils.nan_to_zero(v2) + utils.nan_to_zero(v3) + utils.nan_to_zero(v4),1)
|
247
|
-
|
247
|
+
eval_logger.info(f"{self} - 계산된 비유동부채 : {계산된비유동부채value}")
|
248
248
|
return date, 계산된비유동부채value
|
249
249
|
else:
|
250
250
|
return d, 비유동부채
|
@@ -266,13 +266,13 @@ class Red:
|
|
266
266
|
else:
|
267
267
|
score = utils.to_int(math.log10(deviation + 1) * 33) # desmos그래프상 33이 제일 적당한듯(최대100점에 가깝게)
|
268
268
|
|
269
|
-
|
269
|
+
eval_logger.debug(f"최근주가 : {recent_price} red가격 : {red_price} 괴리율 : {utils.to_int(deviation)} score : {score}")
|
270
270
|
|
271
271
|
return score
|
272
272
|
|
273
273
|
def _generate_data(self, refresh: bool) -> RedData:
|
274
274
|
d1, 지배주주당기순이익 = Tools.calc당기순이익(self.c103, refresh)
|
275
|
-
|
275
|
+
eval_logger.debug(f"{self} 지배주주당기순이익: {지배주주당기순이익}")
|
276
276
|
d2, 유동자산 = Tools.calc유동자산(self.c103, refresh)
|
277
277
|
d3, 유동부채 = Tools.calc유동부채(self.c103, refresh)
|
278
278
|
d4, 부채평가 = self._calc비유동부채(refresh)
|
@@ -331,7 +331,7 @@ class Red:
|
|
331
331
|
:return:
|
332
332
|
"""
|
333
333
|
redis_name = f"{self.code}_red"
|
334
|
-
|
334
|
+
eval_logger.info(f"{self} RedData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
335
335
|
expire_time = 3600 * 12
|
336
336
|
if verbose:
|
337
337
|
print(f"{self} redisname: '{redis_name}' / expect_earn: {Red.expect_earn} / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
@@ -355,11 +355,11 @@ class Red:
|
|
355
355
|
# expect_earn 및 refresh 설정
|
356
356
|
if expect_earn is None:
|
357
357
|
expect_earn = cls.expect_earn
|
358
|
-
|
358
|
+
eval_logger.info(f"기대수익률을 {expect_earn}으로 설정합니다.")
|
359
359
|
previous_expect_earn = float(AnalyserSettingsManager().get_value('RED_RANKING_EXPECT_EARN'))
|
360
|
-
|
360
|
+
eval_logger.debug(f"previous red ranking expect earn : {previous_expect_earn}")
|
361
361
|
if previous_expect_earn != expect_earn:
|
362
|
-
|
362
|
+
eval_logger.warning(f"expect earn : {expect_earn} / RED_RANKING_EXPECT_EARN : {previous_expect_earn} 두 값이 달라 refresh = True")
|
363
363
|
refresh = True
|
364
364
|
|
365
365
|
redis_name = 'red_ranking'
|
@@ -422,7 +422,7 @@ class MilData:
|
|
422
422
|
class Mil:
|
423
423
|
def __init__(self, code: str):
|
424
424
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
425
|
-
|
425
|
+
eval_logger.debug(f"Mil : 종목코드 ({code})")
|
426
426
|
|
427
427
|
self.c101 = myredis.C101(code)
|
428
428
|
self.c103 = myredis.C103(code, 'c103현금흐름표q')
|
@@ -442,7 +442,7 @@ class Mil:
|
|
442
442
|
@code.setter
|
443
443
|
def code(self, code: str):
|
444
444
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
445
|
-
|
445
|
+
eval_logger.debug(f"Mil : 종목코드 변경({self.code} -> {code})")
|
446
446
|
|
447
447
|
self.c101.code = code
|
448
448
|
self.c103.code = code
|
@@ -459,7 +459,7 @@ class Mil:
|
|
459
459
|
"""
|
460
460
|
c101r = self.c101.get_recent(refresh)
|
461
461
|
시가총액 = int(utils.to_int(c101r.get('시가총액', math.nan)) / 100000000)
|
462
|
-
|
462
|
+
eval_logger.debug(f"시가총액: {시가총액}억원")
|
463
463
|
return 시가총액
|
464
464
|
|
465
465
|
def _calc주주수익률(self, 시가총액_억: float, refresh: bool) -> Tuple[str, float, float]:
|
@@ -469,7 +469,7 @@ class Mil:
|
|
469
469
|
주주수익률 = round((재무활동현금흐름 / 시가총액_억 * -100), 2)
|
470
470
|
except ZeroDivisionError:
|
471
471
|
주주수익률 = math.nan
|
472
|
-
|
472
|
+
eval_logger.warning(f'{self} 주주수익률: {주주수익률} 재무활동현금흐름: {재무활동현금흐름}')
|
473
473
|
return d, 주주수익률, 재무활동현금흐름
|
474
474
|
|
475
475
|
def _calc이익지표(self, 시가총액_억: float, refresh: bool) -> Tuple[str, float, float, float]:
|
@@ -480,7 +480,7 @@ class Mil:
|
|
480
480
|
이익지표 = round(((지배주주당기순이익 - 영업활동현금흐름) / 시가총액_억) * 100, 2)
|
481
481
|
except ZeroDivisionError:
|
482
482
|
이익지표 = math.nan
|
483
|
-
|
483
|
+
eval_logger.warning(f'{self} 이익지표: {이익지표} 영업활동현금흐름: {영업활동현금흐름} 지배주주당기순이익: {지배주주당기순이익}')
|
484
484
|
try:
|
485
485
|
date, *_ = Tools.date_set(d1, d2)
|
486
486
|
except ValueError:
|
@@ -521,15 +521,15 @@ class Mil:
|
|
521
521
|
self.c103.page = 'c103재무상태표y'
|
522
522
|
_, capex = self.c103.find('*CAPEX', remove_yoy=True, del_unnamed_key=True, refresh=refresh)
|
523
523
|
|
524
|
-
|
525
|
-
|
524
|
+
eval_logger.debug(f'영업활동현금흐름 {영업활동현금흐름_dict}')
|
525
|
+
eval_logger.debug(f'CAPEX {capex}')
|
526
526
|
|
527
527
|
if len(영업활동현금흐름_dict) == 0:
|
528
528
|
return {}
|
529
529
|
|
530
530
|
if len(capex) == 0:
|
531
531
|
# CAPEX 가 없는 업종은 영업활동현금흐름을 그대로 사용한다.
|
532
|
-
|
532
|
+
eval_logger.warning(f"{self} - CAPEX가 없는 업종으로 영업현금흐름을 그대로 사용합니다..")
|
533
533
|
return 영업활동현금흐름_dict
|
534
534
|
|
535
535
|
# 영업 활동으로 인한 현금 흐름에서 CAPEX 를 각 연도별로 빼주어 fcf 를 구하고 리턴값으로 fcf 딕셔너리를 반환한다.
|
@@ -543,7 +543,7 @@ class Mil:
|
|
543
543
|
if 영업활동현금흐름date == CAPEXdate:
|
544
544
|
fcf_dict[영업활동현금흐름date] = round(영업활동현금흐름value - CAPEXvalue, 2)
|
545
545
|
|
546
|
-
|
546
|
+
eval_logger.debug(f'fcf_dict {fcf_dict}')
|
547
547
|
# 연도순으로 정렬해서 딕셔너리로 반환한다.
|
548
548
|
return dict(sorted(fcf_dict.items(), reverse=False))
|
549
549
|
|
@@ -556,7 +556,7 @@ class Mil:
|
|
556
556
|
https://www.investopedia.com/terms/p/pricetofreecashflow.asp
|
557
557
|
"""
|
558
558
|
if math.isnan(시가총액_억):
|
559
|
-
|
559
|
+
eval_logger.warning(f"{self} - 시가총액이 nan으로 pFCF를 계산할수 없습니다.")
|
560
560
|
return {}
|
561
561
|
|
562
562
|
# pfcf 계산
|
@@ -569,7 +569,7 @@ class Mil:
|
|
569
569
|
|
570
570
|
pfcf_dict = mymongo.C1034.del_unnamed_key(pfcf_dict)
|
571
571
|
|
572
|
-
|
572
|
+
eval_logger.debug(f'pfcf_dict : {pfcf_dict}')
|
573
573
|
return pfcf_dict
|
574
574
|
|
575
575
|
def _calc가치지표(self, 시가총액_억: float, refresh: bool) -> tuple:
|
@@ -585,15 +585,15 @@ class Mil:
|
|
585
585
|
return [0,]
|
586
586
|
|
587
587
|
def _generate_data(self, refresh: bool) -> MilData:
|
588
|
-
|
588
|
+
eval_logger.info(f"In generate_data..refresh : {refresh}")
|
589
589
|
시가총액_억 = self.get_marketcap억(refresh)
|
590
|
-
|
590
|
+
eval_logger.info(f"{self} 시가총액(억) : {시가총액_억}")
|
591
591
|
|
592
592
|
d1, 주주수익률, 재무활동현금흐름 = self._calc주주수익률(시가총액_억, refresh)
|
593
|
-
|
593
|
+
eval_logger.info(f"{self} 주주수익률 : {주주수익률}, {d1}")
|
594
594
|
|
595
595
|
d2, 이익지표, 영업활동현금흐름, 지배주주당기순이익 = self._calc이익지표(시가총액_억, refresh)
|
596
|
-
|
596
|
+
eval_logger.info(f"{self} 이익지표 : {이익지표}, {d2}")
|
597
597
|
|
598
598
|
d3, roic_r, roic_dict, roe_r, roe106, roa_r = self._calc투자수익률(refresh)
|
599
599
|
d4, fcf_dict, pfcf_dict, pcr_dict = self._calc가치지표(시가총액_억, refresh)
|
@@ -640,7 +640,7 @@ class Mil:
|
|
640
640
|
:return:
|
641
641
|
"""
|
642
642
|
redis_name = f"{self.code}_mil"
|
643
|
-
|
643
|
+
eval_logger.info(f"{self} MilData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
644
644
|
if verbose:
|
645
645
|
print(f"{self} redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
646
646
|
|
@@ -677,7 +677,7 @@ class BlueData:
|
|
677
677
|
class Blue:
|
678
678
|
def __init__(self, code: str):
|
679
679
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
680
|
-
|
680
|
+
eval_logger.debug(f"Blue : 종목코드 ({code})")
|
681
681
|
|
682
682
|
self.c101 = myredis.C101(code)
|
683
683
|
self.c103 = myredis.C103(code, 'c103재무상태표q')
|
@@ -696,7 +696,7 @@ class Blue:
|
|
696
696
|
@code.setter
|
697
697
|
def code(self, code: str):
|
698
698
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
699
|
-
|
699
|
+
eval_logger.debug(f"Blue : 종목코드 변경({self.code} -> {code})")
|
700
700
|
|
701
701
|
self.c101.code = code
|
702
702
|
self.c103.code = code
|
@@ -711,11 +711,11 @@ class Blue:
|
|
711
711
|
c104q에서 최근유동비율 찾아보고 유효하지 않거나 \n
|
712
712
|
100이하인 경우에는수동으로 계산해서 다시 한번 평가해 본다.\n
|
713
713
|
"""
|
714
|
-
|
714
|
+
eval_logger.info(f'In the calc유동비율... refresh : {refresh}')
|
715
715
|
self.c104.page = 'c104q'
|
716
716
|
|
717
717
|
유동비율date, 유동비율value = self.c104.latest_value('유동비율', pop_count=pop_count)
|
718
|
-
|
718
|
+
eval_logger.info(f'{self} 유동비율 : {유동비율value}/({유동비율date})')
|
719
719
|
|
720
720
|
if math.isnan(유동비율value) or 유동비율value < 100:
|
721
721
|
유동자산date, 유동자산value = Tools.calc유동자산(self.c103, refresh)
|
@@ -723,23 +723,23 @@ class Blue:
|
|
723
723
|
|
724
724
|
self.c103.page = 'c103현금흐름표q'
|
725
725
|
추정영업현금흐름date, 추정영업현금흐름value = self.c103.sum_recent_4q('영업활동으로인한현금흐름', refresh)
|
726
|
-
|
726
|
+
eval_logger.debug(f'{self} 계산전 유동비율 : {유동비율value} / ({유동비율date})')
|
727
727
|
|
728
728
|
계산된유동비율 = 0
|
729
729
|
try:
|
730
730
|
계산된유동비율 = round(((유동자산value + 추정영업현금흐름value) / 유동부채value) * 100, 2)
|
731
731
|
except ZeroDivisionError:
|
732
|
-
|
732
|
+
eval_logger.info(f'유동자산: {유동자산value} + 추정영업현금흐름: {추정영업현금흐름value} / 유동부채: {유동부채value}')
|
733
733
|
계산된유동비율 = float('inf')
|
734
734
|
finally:
|
735
|
-
|
735
|
+
eval_logger.debug(f'{self} 계산된 유동비율 : {계산된유동비율}')
|
736
736
|
|
737
737
|
try:
|
738
738
|
date, *_ = Tools.date_set(유동자산date, 유동부채date, 추정영업현금흐름date)
|
739
739
|
except ValueError:
|
740
740
|
# 날짜 데이터가 없는경우
|
741
741
|
date = ''
|
742
|
-
|
742
|
+
eval_logger.warning(f'{self} 유동비율 이상(100 이하 또는 nan) : {유동비율value} -> 재계산 : {계산된유동비율}')
|
743
743
|
return date, 계산된유동비율
|
744
744
|
else:
|
745
745
|
return 유동비율date, 유동비율value
|
@@ -749,7 +749,7 @@ class Blue:
|
|
749
749
|
|
750
750
|
def _generate_data(self, refresh: bool) -> BlueData:
|
751
751
|
d1, 유동비율 = self._calc유동비율(pop_count=3, refresh=refresh)
|
752
|
-
|
752
|
+
eval_logger.info(f'유동비율 {유동비율} / [{d1}]')
|
753
753
|
|
754
754
|
재고자산회전율_c106 = myredis.C106.make_like_c106(self.code, 'c104q', '재고자산회전율', refresh)
|
755
755
|
|
@@ -766,16 +766,16 @@ class Blue:
|
|
766
766
|
d9, 순부채비율_r = self.c104.latest_value_pop2('순부채비율', refresh)
|
767
767
|
|
768
768
|
if len(이자보상배율_dict) == 0:
|
769
|
-
|
769
|
+
eval_logger.warning(f'empty dict - 이자보상배율 : {이자보상배율_r} / {이자보상배율_dict}')
|
770
770
|
|
771
771
|
if len(순운전자본회전율_dict) == 0:
|
772
|
-
|
772
|
+
eval_logger.warning(f'empty dict - 순운전자본회전율 : {순운전자본회전율_r} / {순운전자본회전율_dict}')
|
773
773
|
|
774
774
|
if len(재고자산회전율_dict) == 0:
|
775
|
-
|
775
|
+
eval_logger.warning(f'empty dict - 재고자산회전율 : {재고자산회전율_r} / {재고자산회전율_dict}')
|
776
776
|
|
777
777
|
if len(순부채비율_dict) == 0:
|
778
|
-
|
778
|
+
eval_logger.warning(f'empty dict - 순부채비율 : {순부채비율_r} / {순부채비율_dict}')
|
779
779
|
|
780
780
|
score = self._score()
|
781
781
|
|
@@ -813,7 +813,7 @@ class Blue:
|
|
813
813
|
:return:
|
814
814
|
"""
|
815
815
|
redis_name = f"{self.code}_blue"
|
816
|
-
|
816
|
+
eval_logger.info(f"{self} BlueData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
817
817
|
if verbose:
|
818
818
|
print(f"{self} redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
819
819
|
|
@@ -841,7 +841,7 @@ class GrowthData:
|
|
841
841
|
class Growth:
|
842
842
|
def __init__(self, code: str):
|
843
843
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
844
|
-
|
844
|
+
eval_logger.debug(f"Growth : 종목코드 ({code})")
|
845
845
|
|
846
846
|
self.c101 = myredis.C101(code)
|
847
847
|
self.c104 = myredis.C104(code, 'c104q')
|
@@ -860,7 +860,7 @@ class Growth:
|
|
860
860
|
@code.setter
|
861
861
|
def code(self, code: str):
|
862
862
|
assert utils.is_6digit(code), f'Invalid value : {code}'
|
863
|
-
|
863
|
+
eval_logger.debug(f"Growth : 종목코드 변경({self.code} -> {code})")
|
864
864
|
|
865
865
|
self.c101.code = code
|
866
866
|
self.c104.code = code
|
@@ -879,7 +879,7 @@ class Growth:
|
|
879
879
|
self.c104.page = 'c104q'
|
880
880
|
d2, 매출액증가율_r = self.c104.latest_value_pop2('매출액증가율')
|
881
881
|
|
882
|
-
|
882
|
+
eval_logger.info(f'매출액증가율 : {매출액증가율_r} {매출액증가율_dict}')
|
883
883
|
|
884
884
|
# c106 에서 타 기업과 영업이익률 비교
|
885
885
|
self.c106.page = 'c106y'
|
@@ -913,7 +913,7 @@ class Growth:
|
|
913
913
|
:return:
|
914
914
|
"""
|
915
915
|
redis_name = f"{self.code}_growth"
|
916
|
-
|
916
|
+
eval_logger.info(f"{self} GrowthData를 레디스캐시에서 가져오거나 새로 생성합니다.. refresh : {refresh}")
|
917
917
|
if verbose:
|
918
918
|
print(f"{self} redisname: '{redis_name}' / refresh : {refresh} / expire_time : {expire_time/3600}h")
|
919
919
|
|