analyser_hj3415 2.0.2__py2.py3-none-any.whl → 2.1.0__py2.py3-none-any.whl

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/.DS_Store CHANGED
Binary file
@@ -0,0 +1,289 @@
1
+ """red, mil, blue 3가지 분야에서 자료를 계산하여 리턴하는 함수 모음
2
+ """
3
+ import math
4
+
5
+ from analyser_hj3415 import tools
6
+ from utils_hj3415 import utils
7
+ from db_hj3415 import myredis
8
+
9
+ import logging
10
+
11
+ logger = logging.getLogger(__name__)
12
+ formatter = logging.Formatter('%(levelname)s: [%(name)s] %(message)s')
13
+ ch = logging.StreamHandler()
14
+ ch.setFormatter(formatter)
15
+ logger.addHandler(ch)
16
+ logger.setLevel(logging.WARNING)
17
+
18
+
19
+ # 주식을 통한 기대수익률 - 금리가 3%일 경우 두배인 6% 정도로 잡는다.
20
+ EXPECT_EARN = 0.06
21
+
22
+
23
+ def red(code: str) -> dict:
24
+ """
25
+ 리턴값
26
+ {
27
+ 'red_price': red_price,
28
+ '사업가치': 사업가치,
29
+ '재산가치': 재산가치,
30
+ '부채평가': 부채평가,
31
+ '발행주식수': 발행주식수,
32
+ 'date': [각 유효한 값의 년월값 리스트(ex- 2020/09)],
33
+ }
34
+ """
35
+ c103q = myredis.C103(code, 'c103재무상태표q')
36
+
37
+ d1, 지배주주당기순이익 = tools.calc당기순이익(code)
38
+ d2, 유동자산 = tools.calc유동자산(code)
39
+ d3, 유동부채 = tools.calc유동부채(code)
40
+ d4, 부채평가 = tools.calc비유동부채(code)
41
+
42
+ c103q.page = 'c103재무상태표q'
43
+ d5, 투자자산 = c103q.latest_value_pop2('투자자산')
44
+ d6, 투자부동산 = c103q.latest_value_pop2('투자부동산')
45
+
46
+ # 사업가치 계산 - 지배주주지분 당기순이익 / 기대수익률
47
+ 사업가치 = round(utils.nan_to_zero(지배주주당기순이익) / EXPECT_EARN, 2)
48
+
49
+ # 재산가치 계산 - 유동자산 - (유동부채*1.2) + 고정자산중 투자자산
50
+ 재산가치 = round(유동자산 - (유동부채 * 1.2) + utils.nan_to_zero(투자자산) + utils.nan_to_zero(투자부동산), 2)
51
+
52
+ _, 발행주식수 = c103q.latest_value_pop2('발행주식수')
53
+ if math.isnan(발행주식수):
54
+ 발행주식수 = utils.to_int(myredis.C101(code).get_recent().get('발행주식'))
55
+ else:
56
+ 발행주식수 = 발행주식수 * 1000
57
+
58
+ try:
59
+ red_price = round(((사업가치 + 재산가치 - 부채평가) * 100000000) / 발행주식수)
60
+ except (ZeroDivisionError, ValueError) as e:
61
+ red_price = math.nan
62
+
63
+ logger.debug(f'Red Price : {red_price}원')
64
+ return {
65
+ 'red_price': red_price,
66
+ '사업가치': 사업가치,
67
+ '재산가치': 재산가치,
68
+ '부채평가': 부채평가,
69
+ '발행주식수': 발행주식수,
70
+ 'date': tools.set_data(d1, d2, d3, d4, d5, d6), # ''값을 제거하고 리스트로 바꾼다.
71
+ }
72
+
73
+
74
+ def mil(code: str) -> dict:
75
+ """
76
+ 리턴값
77
+ {
78
+ '주주수익률': 주주수익률,
79
+ '이익지표': 이익지표,
80
+ '투자수익률': {'ROIC': roic, 'ROE': roe , 'ROE106': {}},
81
+ '가치지표': {'FCF': fcf_dict, 'PFCF': pfcf_dict, 'PCR': pcr_dict},
82
+ 'date': [각 유효한 값의 년월값 리스트(ex- 2020/09)],
83
+ }
84
+
85
+ - 재무활동현금흐름이 마이너스라는 것은 배당급 지급했거나, 자사주 매입했거나, 부채를 상환한 상태임.
86
+ - 반대는 채권자로 자금을 조달했거나 신주를 발행했다는 의미
87
+ <주주수익률> - 재무활동현금흐름/시가총액 => 5%이상인가?
88
+
89
+ 투하자본수익률(ROIC)가 30%이상인가
90
+ ROE(자기자본이익률) 20%이상이면 아주 우수 다른 투자이익률과 비교해볼것 10%미만이면 별로...단, 부채비율을 확인해야함.
91
+
92
+ 이익지표 ...영업현금흐름이 순이익보다 많은가 - 결과값이 음수인가..
93
+
94
+ FCF는 영업현금흐름에서 자본적 지출(유·무형투자 비용)을 차감한 순수한 현금력이라 할 수 있다.
95
+ 말 그대로 자유롭게(Free) 사용할 수 있는 여윳돈을 뜻한다.
96
+ 잉여현금흐름이 플러스라면 미래의 투자나 채무상환에 쓸 재원이 늘어난 것이다.
97
+ CAPEX(Capital expenditures)는 미래의 이윤을 창출하기 위해 지출된 비용을 말한다.
98
+ 이는 기업이 고정자산을 구매하거나, 유효수명이 당회계년도를 초과하는 기존의 고정자산에 대한 투자에 돈이 사용될 때 발생한다.
99
+
100
+ 잉여현금흐름이 마이너스일때는 설비투자가 많은 시기라 주가가 약세이며 이후 설비투자 마무리되면서 주가가 상승할수 있다.
101
+ 주가는 잉여현금흐름이 증가할때 상승하는 경향이 있다.
102
+ fcf = 영업현금흐름 - capex
103
+
104
+ 가치지표평가
105
+ price to fcf 계산
106
+ https://www.investopedia.com/terms/p/pricetofreecashflow.asp
107
+ pcr보다 정확하게 주식의 가치를 평가할수 있음. 10배이하 추천
108
+ """
109
+ c103q = myredis.C103(code, 'c103현금흐름표q')
110
+ c104q = myredis.C104(code, 'c104q')
111
+ c106q = myredis.C106(code, 'c106q')
112
+
113
+ marketcap억 = tools.get_marketcap(code) / 100000000
114
+ logger.debug(f'{code} market cap: {marketcap억}')
115
+ fcf_dict = tools.findFCF(code)
116
+ pfcf_dict = tools.findPFCF(code)
117
+ d1, 지배주주당기순이익 = tools.calc당기순이익(code)
118
+
119
+ d2, 재무활동현금흐름 = c103q.sum_recent_4q('재무활동으로인한현금흐름')
120
+ d3, 영업활동현금흐름 = c103q.sum_recent_4q('영업활동으로인한현금흐름')
121
+
122
+ d4, roic = c104q.sum_recent_4q('ROIC')
123
+ d5, roe = c104q.latest_value_pop2('ROE')
124
+ roe106 = c106q.find('ROE')
125
+
126
+ _, pcr_dict = c104q.find_without_yoy('PCR')
127
+
128
+ try:
129
+ 주주수익률 = round((재무활동현금흐름 / marketcap억 * -100), 2)
130
+ 이익지표 = round((지배주주당기순이익 - 영업활동현금흐름) / marketcap억, 5)
131
+ except ZeroDivisionError:
132
+ 주주수익률 = math.nan
133
+ 이익지표 = math.nan
134
+
135
+ if math.isnan(주주수익률) or math.isnan(이익지표):
136
+ logger.warning(f'주주수익률: {주주수익률} 이익지표: {이익지표}')
137
+ logger.warning(f'재무활동현금흐름: {재무활동현금흐름} / 지배주주당기순이익: {지배주주당기순이익} / 영업활동현금흐름: {영업활동현금흐름}')
138
+
139
+ logger.debug(f'{code} fcf_dict : {fcf_dict}')
140
+ logger.debug(f"{code} market_cap : {marketcap억}")
141
+ logger.debug(f'{code} pfcf_dict : {pfcf_dict}')
142
+ logger.debug(f'{code} pcr_dict : {pcr_dict}')
143
+
144
+ return {
145
+ '주주수익률': 주주수익률,
146
+ '이익지표': 이익지표,
147
+ '투자수익률': {'ROIC': roic, 'ROE': roe, 'ROE106': roe106},
148
+ '가치지표': {'FCF': fcf_dict, 'PFCF': pfcf_dict, 'PCR': pcr_dict},
149
+ 'date': tools.set_data(d1, d2, d3, d4, d5),
150
+ }
151
+
152
+
153
+ def blue(code: str) -> dict:
154
+ """
155
+ 리턴값
156
+ {
157
+ 'date': [각 유효한 값의 최근분기 값 리스트(ex- 2020/09)],
158
+ '순부채비율': (29.99, {'2018/12': 19.45, '2019/12': 19.52, '2020/12': 12.07, '2021/12': 82.2, '2022/12': 29.99, '2023/12': nan}),
159
+ '순운전자본회전율': (1.04, {'2018/12': 21.91, '2019/12': 23.12, '2020/12': 5.88, '2021/12': 5.6, '2022/12': 6.04, '2023/12': nan}),
160
+ '유동비율': 64.29,
161
+ '이자보상배율': (-3.64, {'2018/12': 4.01, '2019/12': 1.3, '2020/12': -5.05, '2021/12': 0.56, '2022/12': -1.28, '2023/12': nan}),
162
+ '재고자산회전율': (1.66, {'2018/12': 12.41, '2019/12': 12.44, '2020/12': 9.18, '2021/12': 9.76, '2022/12': 8.79, '2023/12': nan})
163
+ }
164
+
165
+ <유동비율>
166
+ 100미만이면 주의하나 현금흐름창출력이 좋으면 괜찮을수 있다.
167
+ 만약 100%이하면 유동자산에 추정영업현금흐름을 더해서 다시계산해보아 기회를 준다.
168
+ <이자보상배율>
169
+ 이자보상배율 영업이익/이자비용으로 1이면 자금사정빡빡 5이상이면 양호
170
+ <순운전자금회전율>
171
+ 순운전자금 => 기업활동을 하기 위해 필요한 자금 (매출채권 + 재고자산 - 매입채무)
172
+ 순운전자본회전율은 매출액/순운전자본으로 일정비율이 유지되는것이 좋으며 너무 작아지면 순운전자본이 많아졌다는 의미로 재고나 외상이 쌓인다는 뜻
173
+ <재고자산회전율>
174
+ 재고자산회전율은 매출액/재고자산으로 회전율이 낮을수록 재고가 많다는 이야기이므로 불리 전년도등과 비교해서 큰차이 발생하면 알람.
175
+ 재고자산회전율이 작아지면 재고가 쌓인다는뜻
176
+ <순부채비율>
177
+ 부채비율은 업종마다 달라 일괄비교 어려우나 순부채 비율이 20%이하인것이 좋고 꾸준히 늘어나지 않는것이 좋다.
178
+ 순부채 비율이 30%이상이면 좋치 않다.
179
+ <매출액>
180
+ 매출액은 어떤경우에도 성장하는 기업이 좋다.매출이 20%씩 늘어나는 종목은 유망한 종목
181
+ <영업이익률>
182
+ 영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
183
+ """
184
+
185
+ d1, 유동비율 = tools.calc유동비율(code, pop_count=3)
186
+ logger.debug(f'유동비율 {유동비율} / [{d1}]')
187
+
188
+ c104y = myredis.C104(code, 'c104y')
189
+ _, dict이자보상배율y = c104y.find_with_yoy('이자보상배율')
190
+ _, dict순운전자본회전율y = c104y.find_with_yoy('순운전자본회전율')
191
+ _, dict재고자산회전율y = c104y.find_with_yoy('재고자산회전율')
192
+ _, dict순부채비율y = c104y.find_with_yoy('순부채비율')
193
+
194
+ c104q = myredis.C104(code, 'c104q')
195
+ d6, 이자보상배율q = c104q.latest_value_pop2('이자보상배율')
196
+ d7, 순운전자본회전율q = c104q.latest_value_pop2('순운전자본회전율')
197
+ d8, 재고자산회전율q = c104q.latest_value_pop2('재고자산회전율')
198
+ d9, 순부채비율q = c104q.latest_value_pop2('순부채비율')
199
+
200
+ if len(dict이자보상배율y) == 0:
201
+ logger.warning(f'empty dict - 이자보상배율 : {이자보상배율q} {dict이자보상배율y}')
202
+
203
+ if len(dict순운전자본회전율y) == 0:
204
+ logger.warning(f'empty dict - 순운전자본회전율 : {순운전자본회전율q} {dict순운전자본회전율y}')
205
+
206
+ if len(dict재고자산회전율y) == 0:
207
+ logger.warning(f'empty dict - 재고자산회전율 : {재고자산회전율q} {dict재고자산회전율y}')
208
+
209
+ if len(dict순부채비율y) == 0:
210
+ logger.warning(f'empty dict - 순부채비율 : {순부채비율q} {dict순부채비율y}')
211
+
212
+ ################################################################
213
+
214
+ return {
215
+ '유동비율': 유동비율,
216
+ '이자보상배율': (이자보상배율q, dict이자보상배율y),
217
+ '순운전자본회전율': (순운전자본회전율q, dict순운전자본회전율y),
218
+ '재고자산회전율': (재고자산회전율q, dict재고자산회전율y),
219
+ '순부채비율': (순부채비율q, dict순부채비율y),
220
+ 'date': tools.set_data(d1, d6, d7, d8, d9), # ''값을 제거하고 리스트로 바꾼다.
221
+ }
222
+
223
+
224
+ def growth(code: str) -> dict:
225
+ """
226
+ 리턴값
227
+ {'date': [각 유효한 값의 최근분기 값 리스트(ex- 2020/09)],
228
+ '매출액증가율': (-14.37, {'2018/12': -24.56, '2019/12': -20.19, '2020/12': -12.64, '2021/12': 38.65, '2022/12': -8.56, '2023/12': nan}),
229
+ '영업이익률': {'뉴프렉스': '17.36', '동일기연': '13.58', '비에이치': '16.23', '에이엔피': '-9.30', '이브이첨단소재': '-4.93'}}
230
+
231
+ <매출액>
232
+ 매출액은 어떤경우에도 성장하는 기업이 좋다.매출이 20%씩 늘어나는 종목은 유망한 종목
233
+ <영업이익률>
234
+ 영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
235
+ """
236
+ c104y = myredis.C104(code, 'c104y')
237
+ c106y = myredis.C106(code, 'c106y')
238
+
239
+ _, dict매출액증가율y = c104y.find_with_yoy('매출액증가율')
240
+
241
+ c104q = myredis.C104(code, 'c104q')
242
+ d2, 매출액증가율q = c104q.latest_value_pop2('매출액증가율')
243
+
244
+ logger.debug(f'매출액증가율 : {매출액증가율q} {dict매출액증가율y}')
245
+
246
+ ################################################################
247
+
248
+ # c106 에서 타 기업과 영업이익률 비교
249
+ dict영업이익률 = c106y.find('영업이익률')
250
+
251
+ return {
252
+ '매출액증가율': (매출액증가율q, dict매출액증가율y),
253
+ '영업이익률': dict영업이익률,
254
+ 'date': [d2, ]}
255
+
256
+
257
+ """
258
+ - 각분기의 합이 연이 아닌 타이틀(즉 sum_4q를 사용하면 안됨)
259
+ '*(지배)당기순이익'
260
+ '*(비지배)당기순이익'
261
+ '장기차입금'
262
+ '현금및예치금'
263
+ '매도가능금융자산'
264
+ '매도파생결합증권'
265
+ '만기보유금융자산'
266
+ '당기손익-공정가치측정금융부채'
267
+ '당기손익인식(지정)금융부채'
268
+ '단기매매금융자산'
269
+ '단기매매금융부채'
270
+ '예수부채'
271
+ '차입부채'
272
+ '기타부채'
273
+ '보험계약부채(책임준비금)'
274
+ '*CAPEX'
275
+ 'ROE'
276
+ """
277
+
278
+ """
279
+ - sum_4q를 사용해도 되는 타이틀
280
+ '자산총계'
281
+ '당기순이익'
282
+ '유동자산'
283
+ '유동부채'
284
+ '비유동부채'
285
+
286
+ '영업활동으로인한현금흐름'
287
+ '재무활동으로인한현금흐름'
288
+ 'ROIC'
289
+ """
@@ -1,8 +1,8 @@
1
1
  """다양한 문자열 출력 형식에 맞춘 함수들
2
2
  """
3
- from .db import mongo
4
- from .eval import red as eval_red, mil as eval_mil, blue as eval_blue, growth as eval_growth
5
- from .score import red as score_red, mil as score_mil, blue as score_blue, growth as score_growth
3
+ from db_hj3415 import myredis
4
+ from analyser_hj3415.analysers import eval
5
+ from analyser_hj3415.analysers import score
6
6
  from utils_hj3415 import utils
7
7
  import textwrap
8
8
 
@@ -21,7 +21,7 @@ class Report:
21
21
  def __init__(self, client, code: str):
22
22
  self.client = client
23
23
  self.code = code
24
- self.name = mongo.Corps.get_name(client, code)
24
+ self.name = myredis.Corps.get_name(code)
25
25
 
26
26
  def __str__(self):
27
27
  return (self.c101() + self.separate_line
@@ -32,7 +32,7 @@ class Report:
32
32
  # + make_str.c108())
33
33
 
34
34
  def c101(self, full=True):
35
- c101 = mongo.C101(self.client, self.code).get_recent(merge_intro=True)
35
+ c101 = myredis.C101(self.code).get_recent()
36
36
  logger.info(c101)
37
37
 
38
38
  title = '=' * 35 + f"\t{c101['코드']}\t\t{c101['종목명']}\t\t{c101['업종']}\t" + '=' * 35
@@ -65,11 +65,11 @@ class Report:
65
65
  return title + '\n' + intro + self.separate_line + price + '\n' + info
66
66
 
67
67
  def red(self, full=True) -> str:
68
- red_dict = eval_red(self.client, self.code)
69
- p, 괴리율 = score_red(self.client, self.code)
68
+ red_dict = eval.red(self.code)
69
+ 괴리율 = score.red(self.code)
70
70
  logger.info(red_dict)
71
71
 
72
- title = f"Red\tPoint({p})\t괴리율({괴리율}%)\t{red_dict['date']}\n"
72
+ title = f"Red\t괴리율({괴리율}%)\t{red_dict['date']}\n"
73
73
  if full:
74
74
  contents = (f"사업가치({utils.deco_num(red_dict['사업가치'])}억) "
75
75
  f"+ 재산가치({utils.deco_num(red_dict['재산가치'])}억) "
@@ -81,8 +81,8 @@ class Report:
81
81
  return title + contents
82
82
 
83
83
  def mil(self, full=True) -> str:
84
- mil_dict = eval_mil(self.client, self.code)
85
- p1, p2, p3, p4 = score_mil(self.client, self.code)
84
+ mil_dict = eval.mil(self.code)
85
+ p1, p2, p3, p4 = score.mil(self.code)
86
86
  logger.info(mil_dict)
87
87
 
88
88
  title = f"Millenial\tPoint({p1+p2+p3+p4})\t{mil_dict['date']}\n"
@@ -104,8 +104,8 @@ class Report:
104
104
  return title + contents
105
105
 
106
106
  def blue(self, full=True) -> str:
107
- blue_dict = eval_blue(self.client, self.code)
108
- p1, p2, p3, p4, p5 = score_blue(self.client, self.code)
107
+ blue_dict = eval.blue(self.code)
108
+ p1, p2, p3, p4, p5 = score.blue(self.code)
109
109
  logger.info(blue_dict)
110
110
 
111
111
  title = f"Blue\tPoint({p1+p2+p3+p4+p5})\t{blue_dict['date']}\n"
@@ -121,8 +121,8 @@ class Report:
121
121
  return title + contents
122
122
 
123
123
  def growth(self, full=True) -> str:
124
- growth_dict = eval_growth(self.client, self.code)
125
- p1, p2 = score_growth(self.client, self.code)
124
+ growth_dict = eval.growth(self.code)
125
+ p1, p2 = score.growth(self.code)
126
126
  logger.info(growth_dict)
127
127
 
128
128
  title = f"Growth\tPoint({p1 + p2})\t{growth_dict['date']}\n"
@@ -169,50 +169,14 @@ class Report:
169
169
  'red_s': (53, -75.42)}
170
170
  """
171
171
  return {
172
- 'c101': mongo.C101(self.client, self.code).get_recent(merge_intro=True),
173
- 'red': eval_red(self.client, self.code),
174
- 'mil': eval_mil(self.client, self.code),
175
- 'blue': eval_blue(self.client, self.code),
176
- 'growth': eval_growth(self.client, self.code),
177
- # 'c108': mongo.C108(self.client, self.code).get_recent(),
178
- 'red_s': score_red(self.client, self.code),
179
- 'mil_s': score_mil(self.client, self.code),
180
- 'blue_s': score_blue(self.client, self.code),
181
- 'growth_s': score_growth(self.client, self.code),
172
+ 'c101': myredis.C101(self.code).get_recent(),
173
+ 'red': eval.red(self.code),
174
+ 'mil': eval.mil(self.code),
175
+ 'blue': eval.blue(self.code),
176
+ 'growth': eval.growth(self.code),
177
+ 'red_s': score.red(self.code),
178
+ 'mil_s': score.mil(self.code),
179
+ 'blue_s': score.blue(self.code),
180
+ 'growth_s': score.growth(self.code),
182
181
  }
183
182
 
184
-
185
- """
186
- def c108(self, full=True) -> str:
187
- if full:
188
- c108_list = mongo.C108(self.client, self.code).get_all()
189
- else:
190
- c108_list = mongo.C108(self.client, self.code).get_recent()
191
- s = ''
192
- logger.info(c108_list)
193
- for i, c108_dict in enumerate(c108_list):
194
- logger.info(c108_dict)
195
- if i == 0:
196
- pass
197
- else:
198
- s += '\n'
199
- header = f"{c108_dict['날짜']}\thprice : {c108_dict['목표가']} 원\n"
200
- title = f"<<{c108_dict['제목']}>>\n"
201
- contents = ''
202
- for line in c108_dict['내용'].split('▶'):
203
- contents += line.strip()
204
- s += header + title + textwrap.fill(contents, width=70) + self.separate_line
205
- return s
206
- """
207
-
208
-
209
-
210
- def for_telegram(client, code: str) -> str:
211
- make_str = MakeStr(client, code)
212
-
213
- return (make_str.c101(full=False) + make_str.separate_line
214
- + make_str.red(full=False) + make_str.separate_line
215
- + make_str.mil(full=False) + make_str.separate_line
216
- + make_str.blue(full=False) + make_str.separate_line
217
- + make_str.growth(full=False))
218
- # + make_str.c108(full=False))
@@ -4,8 +4,8 @@ import pprint
4
4
  import copy
5
5
  from typing import Tuple
6
6
 
7
- from .db import mongo
8
- from .eval import EXPECT_EARN, red as eval_red, mil as eval_mil, blue as eval_blue, growth as eval_growth
7
+ from db_hj3415 import myredis, mymongo
8
+ from analyser_hj3415.analysers import eval
9
9
  from utils_hj3415 import utils
10
10
 
11
11
  import logging
@@ -18,50 +18,45 @@ logger.addHandler(ch)
18
18
  logger.setLevel(logging.WARNING)
19
19
 
20
20
 
21
- def red(client, code: str) -> Tuple[int, float]:
22
- """red price와 최근 주가의 괴리율 파악
21
+ def cal_deviation(v1: float, v2: float) -> float:
22
+ """
23
+ 괴리율 구하는 공식
24
+ :param v1:
25
+ :param v2:
26
+ :return:
27
+ """
28
+ try:
29
+ deviation = abs((v1 - v2) / v1) * 100
30
+ except ZeroDivisionError:
31
+ deviation = math.nan
32
+ return deviation
33
+
23
34
 
24
- 양수면 주가가 고평가되어 있는 상태, 음수면 저평가
25
- 음수가 현재 주가가 싸다는 의미
35
+ def red(code: str) -> int:
36
+ """red price와 최근 주가의 괴리율 파악
26
37
 
27
38
  Returns:
28
- tuple : 괴리율을 기반으로한 포인트, 주가와 red price 비교한 괴리율
39
+ int : 주가와 red price 비교한 괴리율
29
40
  """
30
- c101 = mongo.C101(client, code)
31
-
32
- logger.debug(f'c101 {c101.get_recent()}')
33
-
34
41
  try:
35
- recent_price = utils.to_int(c101.get_recent()['주가'])
42
+ recent_price = utils.to_int(myredis.C101(code).get_recent()['주가'])
36
43
  except KeyError:
37
44
  recent_price = float('nan')
38
- red_price = eval_red(client, code)['red_price']
39
-
40
- logger.debug(f"recent_price : {recent_price}\tred_price : {red_price}")
45
+ return 0
41
46
 
42
- try:
43
- # 괴리율 구하는 공식이 두가지임. 어떤걸 사용해도 동일함
44
- f1 = round((recent_price / red_price - 1) * 100, 2)
45
- f2 = round((recent_price - red_price) / red_price * 100, 2)
46
- logger.debug(f'f1 : {f1}, f2 : {f2}')
47
- 괴리율 = round((recent_price / red_price - 1) * 100, 2)
48
- except ZeroDivisionError:
49
- 괴리율 = float('nan')
47
+ red_price = eval.red(code)['red_price']
48
+ deviation = cal_deviation(recent_price, red_price)
49
+ if red_price < 0 or (recent_price >= red_price):
50
+ score = 0
51
+ else:
52
+ score = math.log10(deviation + 1) * 33 # desmos그래프상 33이 제일 적당한듯(최대100점에 가깝게)
50
53
 
51
- logger.debug(f'괴리율 : {괴리율}')
54
+ #print(f"최근주가 : {recent_price}", f"red가격 : {red_price}", f"괴리율 : {utils.to_int(deviation)}", f"score : {utils.to_int(score)}")
52
55
 
53
- if math.isnan(괴리율) or red_price <= 0:
54
- return 0, float('nan')
55
- else:
56
- try:
57
- p = round(100*math.log10(-괴리율+31.622777)-150)
58
- return p if p > 0 else 0, 괴리율
59
- except ValueError:
60
- # 괴리율+31.622777이 0이하인 경우 ValueError 발생함.
61
- return 0, 괴리율
56
+ return utils.to_int(score)
62
57
 
63
58
 
64
- def mil(client, code: str) -> Tuple[int, int, int, int]:
59
+ def mil(code: str) -> Tuple[int, int, int, int]:
65
60
  """
66
61
  - 재무활동현금흐름이 마이너스라는 것은 배당급 지급했거나, 자사주 매입했거나, 부채를 상환한 상태임.
67
62
  - 반대는 채권자로 자금을 조달했거나 신주를 발행했다는 의미
@@ -90,55 +85,55 @@ def mil(client, code: str) -> Tuple[int, int, int, int]:
90
85
  Returns:
91
86
  tuple: 주주수익률, 이익지표, 투자수익률, PFCF포인트
92
87
  """
93
- mil_dict = eval_mil(client, code)
88
+ mil_dict = eval.mil(code)
94
89
 
95
- logger.debug(pprint.pformat(mil_dict, width=200))
90
+ print(pprint.pformat(mil_dict, width=200))
96
91
 
97
92
  # 주주수익률 평가
98
93
  if math.isnan(mil_dict['주주수익률']):
99
- p1 = 0
94
+ score1 = 0
100
95
  else:
101
- 주주수익률평가 = math.ceil(mil_dict['주주수익률'] - (EXPECT_EARN * 100))
102
- p1 = 0 if 0 > 주주수익률평가 else 주주수익률평가
96
+ 주주수익률평가 = math.ceil(mil_dict['주주수익률'] - (eval.EXPECT_EARN * 100))
97
+ score1 = 0 if 0 > 주주수익률평가 else 주주수익률평가
103
98
 
104
99
  # 이익지표 평가
105
- p2 = 10 if mil_dict['이익지표'] < 0 else 0
100
+ score2 = 10 if mil_dict['이익지표'] < 0 else 0
106
101
 
107
102
  # 투자수익률 평가
108
103
  MAX3 = 20
109
- p3 = 0
104
+ score3 = 0
110
105
  roic = mil_dict['투자수익률']['ROIC']
111
106
  roe = mil_dict['투자수익률']['ROE']
112
107
  if math.isnan(roic) or roic <= 0:
113
108
  # roic 가 비정상이라 평가할 수 없는 경우
114
109
  if 10 < roe <= 20:
115
- p3 += round(MAX3 * 0.333)
110
+ score3 += round(MAX3 * 0.333)
116
111
  elif 20 < roe:
117
- p3 += round(MAX3 * 0.666)
112
+ score3 += round(MAX3 * 0.666)
118
113
  elif 0 < roic:
119
114
  # roic 로 평가할 수 있는 경우
120
115
  if 0 < roic <= 15:
121
- p3 += round(MAX3 * 0.333)
116
+ score3 += round(MAX3 * 0.333)
122
117
  elif 15 < roic <= 30:
123
- p3 += round(MAX3 * 0.666)
118
+ score3 += round(MAX3 * 0.666)
124
119
  elif 30 < roic:
125
- p3 += MAX3
120
+ score3 += MAX3
126
121
 
127
122
  # PFCF 평가
128
123
  pfcf_dict = mil_dict['가치지표']['PFCF']
129
- _, pfcf = mongo.Corps.latest_value(pfcf_dict)
124
+ _, pfcf = mymongo.C1034.latest_dict_value(pfcf_dict)
130
125
 
131
126
  logger.debug(f'recent pfcf {_}, {pfcf}')
132
127
  try:
133
128
  p = round(-40 * math.log10(pfcf) + 40)
134
129
  except ValueError:
135
130
  p = 0
136
- p4 = 0 if 0 > p else p
131
+ score4 = 0 if 0 > p else p
137
132
 
138
- return p1, p2, p3, p4
133
+ return score1, score2, score3, score4
139
134
 
140
135
 
141
- def blue(client, code: str) -> Tuple[int, int, int, int, int]:
136
+ def blue(code: str) -> Tuple[int, int, int, int, int]:
142
137
  """회사의 안정성을 보는 지표들
143
138
 
144
139
  0을 기준으로 상태가 좋치 않을 수록 마이너스 값을 가진다.
@@ -181,11 +176,11 @@ def blue(client, code: str) -> Tuple[int, int, int, int, int]:
181
176
 
182
177
  return int(p)
183
178
 
184
- c104y = mongo.C104(client, code, 'c104y')
179
+ c104y = myredis.C104(code, 'c104y')
185
180
 
186
- blue_dict = eval_blue(client, code)
181
+ blue_dict = eval.blue(code)
187
182
 
188
- logger.debug(pprint.pformat(blue_dict, width=200))
183
+ print(pprint.pformat(blue_dict, width=200))
189
184
 
190
185
  def 유동비율평가(유동비율: float) -> int:
191
186
  # 채점은 0을 기준으로 마이너스 해간다. 즉 0이 제일 좋은 상태임.
@@ -210,9 +205,9 @@ def blue(client, code: str) -> Tuple[int, int, int, int, int]:
210
205
  if math.isnan(최근이자보상배율q) or 최근이자보상배율q <= 1:
211
206
  # 최근 분기의 값이 비정상이면 최근 년도를 한번 더 비교해 보지만 좀더 엄격하게 전년대비도 비교한다.
212
207
 
213
- _, 최근이자보상배율y = mongo.Corps.latest_value(dict_y)
208
+ _, 최근이자보상배율y = mymongo.C1034.latest_dict_value(dict_y)
214
209
  c104y.page = 'c104y'
215
- _, 전년대비 = c104y.find_증감율(title='이자보상배율').popitem()
210
+ 전년대비 = c104y.find_yoy(title='이자보상배율')
216
211
 
217
212
  if math.isnan(최근이자보상배율y) or 최근이자보상배율y <= 1 or math.isnan(전년대비) or 전년대비 < 0:
218
213
  p = NEG_MAX
@@ -233,9 +228,9 @@ def blue(client, code: str) -> Tuple[int, int, int, int, int]:
233
228
 
234
229
  if math.isnan(최근순부채비율q) or 최근순부채비율q >= 80:
235
230
  # 최근 분기의 값이 비정상이면 최근 년도를 한번 더 비교해 보지만 좀더 엄격하게 전년대비도 비교한다.
236
- _, 최근순부채비율y = mongo.Corps.latest_value(dict_y)
231
+ _, 최근순부채비율y = mymongo.C1034.latest_dict_value(dict_y)
237
232
  c104y.page = 'c104y'
238
- _, 전년대비 = c104y.find_증감율(title='순부채비율').popitem()
233
+ 전년대비 = c104y.find_yoy(title='순부채비율')
239
234
  if math.isnan(최근순부채비율y) or 최근순부채비율y >= 80 or math.isnan(전년대비) or 전년대비 > 0:
240
235
  p = NEG_MAX
241
236
  else:
@@ -269,7 +264,7 @@ def blue(client, code: str) -> Tuple[int, int, int, int, int]:
269
264
  return p1, p2, p3, p4, p5
270
265
 
271
266
 
272
- def growth(client, code: str) -> Tuple[int, int]:
267
+ def growth(code: str) -> Tuple[int, int]:
273
268
  """회사의 성장성을 보는 지표들
274
269
 
275
270
  <매출액>
@@ -280,7 +275,7 @@ def growth(client, code: str) -> Tuple[int, int]:
280
275
  Returns:
281
276
  tuple : 매출액증가율, 영업이익률 평가 포인트
282
277
  """
283
- growth_dict = eval_growth(client, code)
278
+ growth_dict = eval.growth(code)
284
279
 
285
280
  logger.debug(pprint.pformat(growth_dict, width=200))
286
281
 
@@ -288,7 +283,7 @@ def growth(client, code: str) -> Tuple[int, int]:
288
283
  # 매출액은 어떤경우에도 성장하는 기업이 좋다.매출이 20%씩 늘어나는 종목은 유망한 종목
289
284
  MAX = 20
290
285
  최근매출액증가율q, dict_y = 매출액증가율
291
- _, 최근매출액증가율y = mongo.Corps.latest_value(dict_y)
286
+ _, 최근매출액증가율y = mymongo.C1034.latest_dict_value(dict_y)
292
287
 
293
288
  # 최근 자료가 성장하는 중인지 판단
294
289
  if math.isnan(최근매출액증가율q):
@@ -342,7 +337,7 @@ def growth(client, code: str) -> Tuple[int, int]:
342
337
  def 영업이익률평가(영업이익률: dict) -> int:
343
338
  # 영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
344
339
  영업이익률 = copy.deepcopy(영업이익률)
345
- name = mongo.Corps.get_name(client, code)
340
+ name = myredis.Corps.get_name(code)
346
341
 
347
342
  p = 0
348
343
  try: