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/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