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

Sign up to get free protection for your applications and to get access to all the features.
analyser_hj3415/eval.py DELETED
@@ -1,382 +0,0 @@
1
- """red, mil, blue 3가지 분야에서 자료를 계산하여 리턴하는 함수 모음
2
- """
3
- import math
4
- import time
5
- import datetime
6
- import pandas as pd
7
- from multiprocessing import Process, Queue
8
-
9
- from .db import mongo, evaltools
10
- from utils_hj3415 import utils
11
-
12
- import logging
13
-
14
- logger = logging.getLogger(__name__)
15
- formatter = logging.Formatter('%(levelname)s: [%(name)s] %(message)s')
16
- ch = logging.StreamHandler()
17
- ch.setFormatter(formatter)
18
- logger.addHandler(ch)
19
- logger.setLevel(logging.WARNING)
20
-
21
- # 주식을 통한 기대수익률 - 금리가 3%일 경우 두배인 6% 정도로 잡는다.
22
- EXPECT_EARN = 0.04
23
-
24
-
25
- def red(client, code: str) -> dict:
26
- """
27
- 리턴값
28
- {
29
- 'red_price': red_price,
30
- '사업가치': 사업가치,
31
- '재산가치': 재산가치,
32
- '부채평가': 부채평가,
33
- '발행주식수': 발행주식수,
34
- 'date': [각 유효한 값의 년월값 리스트(ex- 2020/09)],
35
- }
36
- """
37
- c101 = mongo.C101(client, code)
38
- c103q = mongo.C103(client, code, 'c103재무상태표q')
39
-
40
- d1, 지배주주당기순이익 = evaltools.calc당기순이익(client, code)
41
- d2, 유동자산 = evaltools.calc유동자산(client, code)
42
- d3, 유동부채 = evaltools.calc유동부채(client, code)
43
- d4, 부채평가 = evaltools.calc비유동부채(client, code)
44
-
45
- c103q.page = 'c103재무상태표q'
46
- d5, 투자자산 = c103q.latest_value('투자자산', nan_to_zero=True, allow_empty=True)
47
- d6, 투자부동산 = c103q.latest_value('투자부동산', nan_to_zero=True, allow_empty=True)
48
-
49
- # 사업가치 계산 - 지배주주지분 당기순이익 / 기대수익률
50
- 사업가치 = round(지배주주당기순이익 / EXPECT_EARN, 2)
51
-
52
- # 재산가치 계산 - 유동자산 - (유동부채*1.2) + 고정자산중 투자자산
53
- 재산가치 = round(유동자산 - (유동부채 * 1.2) + 투자자산 + 투자부동산, 2)
54
- if math.isnan(재산가치):
55
- logger.warning(f'유동자산: {유동자산} - 유동부채: {유동부채} * 1.2 + 투자자산: {투자자산} + 투자부동산: {투자부동산}')
56
-
57
- d, 발행주식수 = c103q.latest_value('발행주식수', allow_empty=True)
58
- if math.isnan(발행주식수):
59
- rc101 = c101.get_recent()
60
- logger.error(rc101)
61
- 발행주식수 = utils.to_int(rc101.get('발행주식'))
62
- else:
63
- 발행주식수 = 발행주식수 * 1000
64
-
65
- try:
66
- red_price = round(((사업가치 + 재산가치 - 부채평가) * 100000000) / 발행주식수)
67
- except (ZeroDivisionError, ValueError) as e:
68
- logger.error(f'In calc red price... {e} : {code}')
69
- red_price = math.nan
70
-
71
- logger.debug(f'Red Price : {red_price}원')
72
- return {
73
- 'red_price': red_price,
74
- '사업가치': 사업가치,
75
- '재산가치': 재산가치,
76
- '부채평가': 부채평가,
77
- '발행주식수': 발행주식수,
78
- 'date': [i for i in {d1, d2, d3, d4, d5, d6} if i != ''], # ''값을 제거하고 리스트로 바꾼다.
79
- }
80
-
81
-
82
- def mil(client, code: str) -> dict:
83
- """
84
- 리턴값
85
- {
86
- '주주수익률': 주주수익률,
87
- '이익지표': 이익지표,
88
- '투자수익률': {'ROIC': roic, 'ROE': roe},
89
- '가치지표': {'FCF': fcf_dict, 'PFCF': pfcf_dict, 'PCR': pcr_dict},
90
- 'date': [각 유효한 값의 년월값 리스트(ex- 2020/09)],
91
- }
92
- """
93
- c103 = mongo.C103(client, code, 'c103현금흐름표q')
94
- c104 = mongo.C104(client, code, 'c104q')
95
-
96
- marketcap억 = evaltools.get_marketcap(client, code, nan_to_zero=False) / 100000000
97
- logger.debug(f'{code} market cap: {marketcap억}')
98
- fcf_dict = evaltools.findFCF(client, code)
99
- pfcf_dict = evaltools.findPFCF(client, code)
100
- d1, 지배주주당기순이익 = evaltools.calc당기순이익(client, code)
101
-
102
- d2, 재무활동현금흐름 = c103.sum_recent_4q(title='재무활동으로인한현금흐름', nan_to_zero=False)
103
- d3, 영업활동현금흐름 = c103.sum_recent_4q(title='영업활동으로인한현금흐름', nan_to_zero=False)
104
-
105
- d4, roic = c104.sum_recent_4q('ROIC', nan_to_zero=False)
106
- d5, roe = c104.latest_value('ROE', nan_to_zero=False, allow_empty=True)
107
- pcr_dict = c104.find('PCR', allow_empty=True)
108
-
109
- try:
110
- 주주수익률 = round((재무활동현금흐름 / marketcap억 * -100), 2)
111
- 이익지표 = round((지배주주당기순이익 - 영업활동현금흐름) / marketcap억, 5)
112
- except ZeroDivisionError:
113
- 주주수익률 = math.nan
114
- 이익지표 = math.nan
115
-
116
- if math.isnan(주주수익률) or math.isnan(이익지표):
117
- logger.warning(f'주주수익률: {주주수익률} 이익지표: {이익지표}')
118
- logger.warning(f'재무활동현금흐름: {재무활동현금흐름}지배주주당기순이익: {지배주주당기순이익}영업활동현금흐름: {영업활동현금흐름}')
119
-
120
- logger.debug(f'{code} fcf_dict : {fcf_dict}')
121
- logger.debug(f"{code} market_cap : {marketcap억}")
122
- logger.debug(f'{code} pfcf_dict : {pfcf_dict}')
123
- logger.debug(f'{code} pcr_dict : {pcr_dict}')
124
-
125
- return {
126
- '주주수익률': 주주수익률,
127
- '이익지표': 이익지표,
128
- '투자수익률': {'ROIC': roic, 'ROE': roe},
129
- '가치지표': {'FCF': fcf_dict, 'PFCF': pfcf_dict, 'PCR': pcr_dict},
130
- 'date': [i for i in {d1, d2, d3, d4, d5} if i != ''], # ''값을 제거하고 리스트로 바꾼다.
131
- }
132
-
133
-
134
- def blue(client, code: str) -> dict:
135
- """
136
- 리턴값
137
- {
138
- 'date': [각 유효한 값의 최근분기 값 리스트(ex- 2020/09)],
139
- '순부채비율': (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}),
140
- '순운전자본회전율': (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}),
141
- '유동비율': 64.29,
142
- '이자보상배율': (-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}),
143
- '재고자산회전율': (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})
144
- }
145
-
146
- <유동비율>
147
- 100미만이면 주의하나 현금흐름창출력이 좋으면 괜찮을수 있다.
148
- 만약 100%이하면 유동자산에 추정영업현금흐름을 더해서 다시계산해보아 기회를 준다.
149
- <이자보상배율>
150
- 이자보상배율 영업이익/이자비용으로 1이면 자금사정빡빡 5이상이면 양호
151
- <순운전자금회전율>
152
- 순운전자금 => 기업활동을 하기 위해 필요한 자금 (매출채권 + 재고자산 - 매입채무)
153
- 순운전자본회전율은 매출액/순운전자본으로 일정비율이 유지되는것이 좋으며 너무 작아지면 순운전자본이 많아졌다는 의미로 재고나 외상이 쌓인다는 뜻
154
- <재고자산회전율>
155
- 재고자산회전율은 매출액/재고자산으로 회전율이 낮을수록 재고가 많다는 이야기이므로 불리 전년도등과 비교해서 큰차이 발생하면 알람.
156
- 재고자산회전율이 작아지면 재고가 쌓인다는뜻
157
- <순부채비율>
158
- 부채비율은 업종마다 달라 일괄비교 어려우나 순부채 비율이 20%이하인것이 좋고 꾸준히 늘어나지 않는것이 좋다.
159
- 순부채 비율이 30%이상이면 좋치 않다.
160
- <매출액>
161
- 매출액은 어떤경우에도 성장하는 기업이 좋다.매출이 20%씩 늘어나는 종목은 유망한 종목
162
- <영업이익률>
163
- 영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
164
- """
165
-
166
- d1, 유동비율 = evaltools.calc유동비율(client, code, pop_count=3)
167
- logger.debug(f'유동비율 {유동비율} / [{d1}]')
168
-
169
- c104y = mongo.C104(client, code, 'c104y')
170
- dict이자보상배율y = c104y.find('이자보상배율', allow_empty=True)
171
- dict순운전자본회전율y = c104y.find('순운전자본회전율', allow_empty=True)
172
- dict재고자산회전율y = c104y.find('재고자산회전율', allow_empty=True)
173
- dict순부채비율y = c104y.find('순부채비율', allow_empty=True)
174
-
175
- c104q = mongo.C104(client, code, 'c104q')
176
- d2, 이자보상배율q = c104q.latest_value('이자보상배율', allow_empty=True)
177
- d3, 순운전자본회전율q = c104q.latest_value('순운전자본회전율', allow_empty=True)
178
- d4, 재고자산회전율q = c104q.latest_value('재고자산회전율', allow_empty=True)
179
- d5, 순부채비율q = c104q.latest_value('순부채비율', allow_empty=True)
180
-
181
- if len(dict이자보상배율y) == 0:
182
- logger.warning(f'empty dict - 이자보상배율 : {이자보상배율q} {dict이자보상배율y}')
183
-
184
- if len(dict순운전자본회전율y) == 0:
185
- logger.warning(f'empty dict - 순운전자본회전율 : {순운전자본회전율q} {dict순운전자본회전율y}')
186
-
187
- if len(dict재고자산회전율y) == 0:
188
- logger.warning(f'empty dict - 재고자산회전율 : {재고자산회전율q} {dict재고자산회전율y}')
189
-
190
- if len(dict순부채비율y) == 0:
191
- logger.warning(f'empty dict - 순부채비율 : {순부채비율q} {dict순부채비율y}')
192
-
193
- ################################################################
194
-
195
- return {
196
- '유동비율': 유동비율,
197
- '이자보상배율': (이자보상배율q, dict이자보상배율y),
198
- '순운전자본회전율': (순운전자본회전율q, dict순운전자본회전율y),
199
- '재고자산회전율': (재고자산회전율q, dict재고자산회전율y),
200
- '순부채비율': (순부채비율q, dict순부채비율y),
201
- 'date': [i for i in {d1, d2, d3, d4, d5} if i != ''], # ''값을 제거하고 리스트로 바꾼다.
202
- }
203
-
204
-
205
- def growth(client, code: str) -> dict:
206
- """
207
- 리턴값
208
- {'date': [각 유효한 값의 최근분기 값 리스트(ex- 2020/09)],
209
- '매출액증가율': (-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}),
210
- '영업이익률': {'뉴프렉스': '17.36', '동일기연': '13.58', '비에이치': '16.23', '에이엔피': '-9.30', '이브이첨단소재': '-4.93'}}
211
-
212
- <매출액>
213
- 매출액은 어떤경우에도 성장하는 기업이 좋다.매출이 20%씩 늘어나는 종목은 유망한 종목
214
- <영업이익률>
215
- 영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
216
- """
217
- c104y = mongo.C104(client, code, 'c104y')
218
- c106y = mongo.C106(client, code, 'c106y')
219
-
220
- dict매출액증가율y = c104y.find('매출액증가율', allow_empty=True)
221
-
222
- c104q = mongo.C104(client, code, 'c104q')
223
- d1, 매출액증가율q = c104q.latest_value('매출액증가율', nan_to_zero=False, allow_empty=True)
224
-
225
- logger.debug(f'매출액증가율 : {매출액증가율q} {dict매출액증가율y}')
226
-
227
- ################################################################
228
-
229
- # c106 에서 타 기업과 영업이익률 비교
230
- dict영업이익률 = c106y.find('영업이익률', allow_empty=True)
231
-
232
- return {
233
- '매출액증가율': (매출액증가율q, dict매출액증가율y),
234
- '영업이익률': dict영업이익률,
235
- 'date': [d1, ]}
236
-
237
-
238
- """
239
- - 각분기의 합이 연이 아닌 타이틀(즉 sum_4q를 사용하면 안됨)
240
- '*(지배)당기순이익'
241
- '*(비지배)당기순이익'
242
- '장기차입금'
243
- '현금및예치금'
244
- '매도가능금융자산'
245
- '매도파생결합증권'
246
- '만기보유금융자산'
247
- '당기손익-공정가치측정금융부채'
248
- '당기손익인식(지정)금융부채'
249
- '단기매매금융자산'
250
- '단기매매금융부채'
251
- '예수부채'
252
- '차입부채'
253
- '기타부채'
254
- '보험계약부채(책임준비금)'
255
- '*CAPEX'
256
- 'ROE'
257
- """
258
-
259
- """
260
- - sum_4q를 사용해도 되는 타이틀
261
- '자산총계'
262
- '당기순이익'
263
- '유동자산'
264
- '유동부채'
265
- '비유동부채'
266
-
267
- '영업활동으로인한현금흐름'
268
- '재무활동으로인한현금흐름'
269
- 'ROIC'
270
- """
271
-
272
-
273
- def _make_df_part(db_addr, codes: list, q):
274
- def make_record(my_client, my_code: str) -> dict:
275
- # 장고에서 사용할 eval 테이블을 만들기 위해 각각의 레코드를 구성하는 함수
276
- c101 = mongo.C101(my_client, my_code).get_recent()
277
-
278
- red_dict = red(my_client, my_code)
279
- mil_dict = mil(my_client, my_code)
280
- growth_dict = growth(my_client, my_code)
281
-
282
- mil_date = mil_dict['date']
283
- red_date = red_dict['date']
284
- growth_date = growth_dict['date']
285
-
286
- return {
287
- 'code': c101['코드'],
288
- '종목명': c101['종목명'],
289
- '주가': utils.to_int(c101['주가']),
290
- 'PER': utils.to_float(c101['PER']),
291
- 'PBR': utils.to_float(c101['PBR']),
292
- '시가총액': utils.to_float(c101['시가총액']),
293
- 'RED': utils.to_int(red_dict['red_price']),
294
- '주주수익률': utils.to_float(mil_dict['주주수익률']),
295
- '이익지표': utils.to_float(mil_dict['이익지표']),
296
- 'ROIC': utils.to_float(mil_dict['투자수익률']['ROIC']),
297
- 'ROE': utils.to_float(mil_dict['투자수익률']['ROE']),
298
- 'PFCF': utils.to_float(mongo.Corps.latest_value(mil_dict['가치지표']['PFCF'])[1]),
299
- 'PCR': utils.to_float(mongo.Corps.latest_value(mil_dict['가치지표']['PCR'])[1]),
300
- '매출액증가율': utils.to_float(growth_dict['매출액증가율'][0]),
301
- 'date': list(set(mil_date + red_date + growth_date))
302
- }
303
- # 각 코어별로 디비 클라이언트를 만들어야만 한다. 안그러면 에러발생
304
- client = mongo.connect_mongo(db_addr)
305
- t = len(codes)
306
- d = []
307
- for i, code in enumerate(codes):
308
- print(f'{i+1}/{t} {code}')
309
- try:
310
- d.append(make_record(client, code))
311
- except:
312
- logger.error(f'error on {code}')
313
- continue
314
- df = pd.DataFrame(d)
315
- logger.info(df)
316
- q.put(df)
317
-
318
-
319
- def make_today_eval_df(client, refresh: bool = False) -> pd.DataFrame:
320
- """ 멀티프로세싱을 사용하여 전체 종목의 eval 을 데이터프레임으로 만들어 반환
321
-
322
- 기본값으로 refresh 는 False 로 설정되어 당일자의 저장된 데이터프레임이 있으면 새로 생성하지 않고 mongo DB를 이용한다.
323
- """
324
- today_str = datetime.datetime.today().strftime('%Y%m%d')
325
- df = mongo.EvalByDate(client, today_str).load_df()
326
- if refresh or len(df) == 0:
327
- codes_in_db = mongo.Corps.get_all_codes(client)
328
-
329
- print('*' * 25, f"Eval all using multiprocess(refresh={refresh})", '*' * 25)
330
- print(f'Total {len(codes_in_db)} items..')
331
- logger.debug(codes_in_db)
332
- n, divided_list = utils.code_divider_by_cpu_core(codes_in_db)
333
-
334
- addr = mongo.extract_addr_from_client(client)
335
-
336
- start_time = time.time()
337
- q = Queue()
338
- ths = []
339
- for i in range(n):
340
- ths.append(Process(target=_make_df_part, args=(addr, divided_list[i], q)))
341
- for i in range(n):
342
- ths[i].start()
343
-
344
- df_list = []
345
- for i in range(n):
346
- df_list.append(q.get())
347
- # 부분데이터프레임들을 하나로 합침
348
- final_df = pd.concat(df_list, ignore_index=True)
349
-
350
- for i in range(n):
351
- ths[i].join()
352
-
353
- print(f'Total spent time : {round(time.time() - start_time, 2)} sec.')
354
- logger.debug(final_df)
355
- print(f"Save to mongo db(db: eval col: {today_str})")
356
- mongo.EvalByDate(client, today_str).save_df(final_df)
357
- else:
358
- print(f"Use saved dataframe from mongo db..")
359
- final_df = df
360
- return final_df
361
-
362
-
363
- def yield_valid_spac(client) -> tuple:
364
- """
365
- 전체 스팩주의 현재가를 평가하여 2000원 이하인 경우 yield한다.
366
-
367
- Returns:
368
- tuple: (code, name, price)
369
- """
370
- codes = mongo.Corps.get_all_codes(client)
371
- logger.debug(f'len(codes) : {len(codes)}')
372
- print('<<< Finding valuable SPAC >>>')
373
- for i, code in enumerate(codes):
374
- name = mongo.Corps.get_name(client, code)
375
- logger.debug(f'code : {code} name : {name}')
376
- if '스팩' in str(name):
377
- logger.debug(f'>>> spac - code : {code} name : {name}')
378
- price, _, _ = utils.get_price_now(code=code)
379
- if price <= 2000:
380
- logger.warning(f'현재가:{price}')
381
- print(f"code: {code} name: {name}, price: {price}")
382
- yield code, name, price
@@ -1,16 +0,0 @@
1
- analyser_hj3415/.DS_Store,sha256=ru32hJTZXnU4wX_07F4wd6nuiLkH9bA3gTALaIXBamM,6148
2
- analyser_hj3415/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- analyser_hj3415/cli.py,sha256=qzRnpDRJvQnQevSKHBpKbTsBjmSWllZjzTV4z_alg2A,4891
4
- analyser_hj3415/eval.py,sha256=v86gNZ722GYHyQKvm1NxHLC8r9mzSx1JgKkznSCyc6Q,16951
5
- analyser_hj3415/report.py,sha256=Sr14o6edWDwFZeR_cjE7zWw3K02Rv1nPKkgCUP-3Ah8,10917
6
- analyser_hj3415/score.py,sha256=hQCV_i_fsXKOYVKDZ4QIpf1SwFh8iHDrQAVFuM9x4os,16693
7
- analyser_hj3415/db/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
8
- analyser_hj3415/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- analyser_hj3415/db/chk_db.py,sha256=NguwgG3TP9Lassh2eJ101AIHGVoWZCxUcESdPt19swE,10115
10
- analyser_hj3415/db/evaltools.py,sha256=aSOnMG2uKp5kTv-UPIgnpfeeePNhScIXZVu50mioAnY,11867
11
- analyser_hj3415/db/mongo.py,sha256=wc8GPwXhsibKWHERflVrOUCSJNmRlKKe0MzWZ6KQsfs,35309
12
- analyser_hj3415-2.0.2.dist-info/entry_points.txt,sha256=dHaCM3eOAGONmxTWuRVqo9Zyq2C7J5TZmpH0PD6FW5k,103
13
- analyser_hj3415-2.0.2.dist-info/LICENSE,sha256=QVKTp0dTnB5xG8RLgG17LwSWCKNEzYoVVM6KjoCPKc0,1079
14
- analyser_hj3415-2.0.2.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
15
- analyser_hj3415-2.0.2.dist-info/METADATA,sha256=HwMmaMdCLkoCMTw53I-AxL555A00z7AMovB8ellrbWw,6534
16
- analyser_hj3415-2.0.2.dist-info/RECORD,,
File without changes