analyser_hj3415 2.8.3__tar.gz → 2.9.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/PKG-INFO +1 -1
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/cli.py +19 -6
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/eval.py +71 -71
- analyser_hj3415-2.9.1/analyser_hj3415/tsa.py +617 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/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.1}/.DS_Store +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.gitattributes +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.gitignore +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.idea/.gitignore +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.idea/analyser-hj3415.iml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.idea/misc.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.idea/modules.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/.idea/vcs.xml +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/LICENSE +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/README.md +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/.DS_Store +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/__init__.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/workroom/__init__.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/workroom/mysklearn.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/workroom/mysklearn2.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/analyser_hj3415/workroom/score.py +0 -0
- {analyser_hj3415-2.8.3 → analyser_hj3415-2.9.1}/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
|
|