analyser_hj3415 2.6.8__py2.py3-none-any.whl → 2.7.1__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,182 +0,0 @@
1
- """다양한 문자열 출력 형식에 맞춘 함수들
2
- """
3
- from db_hj3415 import myredis
4
- from analyser_hj3415.analysers import eval
5
- from analyser_hj3415.analysers import score
6
- from utils_hj3415 import utils
7
- import textwrap
8
-
9
- import logging
10
- logger = logging.getLogger(__name__)
11
- formatter = logging.Formatter('%(levelname)s: [%(name)s] %(message)s')
12
- ch = logging.StreamHandler()
13
- ch.setFormatter(formatter)
14
- logger.addHandler(ch)
15
- logger.setLevel(logging.WARNING)
16
-
17
-
18
- class Report:
19
- separate_line = '\n' + ('-' * 65) + '\n'
20
-
21
- def __init__(self, client, code: str):
22
- self.client = client
23
- self.code = code
24
- self.name = myredis.Corps.get_name(code)
25
-
26
- def __str__(self):
27
- return (self.c101() + self.separate_line
28
- + self.red() + self.separate_line
29
- + self.mil() + self.separate_line
30
- + self.blue() + self.separate_line
31
- + self.growth())
32
- # + make_str.c108())
33
-
34
- def c101(self, full=True):
35
- c101 = myredis.C101(self.code).get_recent()
36
- logger.info(c101)
37
-
38
- title = '=' * 35 + f"\t{c101['코드']}\t\t{c101['종목명']}\t\t{c101['업종']}\t" + '=' * 35
39
- intro = textwrap.fill(f"{c101['intro']}", width=70)
40
-
41
- if full:
42
- price = (f"{c101['date']}\t\t"
43
- f"주가: {utils.deco_num(c101['주가'])}원\t\t"
44
- f"52주최고: {utils.deco_num(c101['최고52주'])}원\t"
45
- f"52주최저: {utils.deco_num(c101['최저52주'])}원")
46
- info = (f"PER: {c101['PER']}\t\t"
47
- f"PBR: {c101['PBR']}\t\t\t"
48
- f"배당수익률: {c101['배당수익률']}%\t\t"
49
- f"시가총액: {utils.get_kor_amount(utils.to_int(c101['시가총액']), omit='억')}\n"
50
- f"업종PER: {c101['업종PER']}\t"
51
- f"유통비율: {c101['유통비율']}%\t\t"
52
- f"거래대금: {utils.to_억(c101['거래대금'])}원\t\t"
53
- f"발행주식: {utils.to_만(c101['발행주식'])}주")
54
- else:
55
- price = (f"<< {c101['date']} >>\n"
56
- f"주가: {utils.deco_num(c101['주가'])}원")
57
- info = (f"PER: {c101['PER']}\n"
58
- f"업종PER: {c101['업종PER']}\n"
59
- f"PBR: {c101['PBR']}\n"
60
- f"배당수익률: {c101['배당수익률']}%\n"
61
- f"유통비율: {c101['유통비율']}%\n"
62
- f"발행주식: {utils.to_만(c101['발행주식'])}주\n"
63
- f"시가총액: {utils.get_kor_amount(utils.to_int(c101['시가총액']), omit='억')}")
64
-
65
- return title + '\n' + intro + self.separate_line + price + '\n' + info
66
-
67
- def red(self, full=True) -> str:
68
- red_dict = eval.red(self.code)
69
- 괴리율 = score.red(self.code)
70
- logger.info(red_dict)
71
-
72
- title = f"Red\t괴리율({괴리율}%)\t{red_dict['date']}\n"
73
- if full:
74
- contents = (f"사업가치({utils.deco_num(red_dict['사업가치'])}억) "
75
- f"+ 재산가치({utils.deco_num(red_dict['재산가치'])}억) "
76
- f"- 부채({utils.deco_num(red_dict['부채평가'])}억) "
77
- f"/ 발행주식({utils.to_만(red_dict['발행주식수'])}주) "
78
- f"= {utils.deco_num(red_dict['red_price'])}원")
79
- else:
80
- contents = f"{utils.deco_num(red_dict['red_price'])}원"
81
- return title + contents
82
-
83
- def mil(self, full=True) -> str:
84
- mil_dict = eval.mil(self.code)
85
- p1, p2, p3, p4 = score.mil(self.code)
86
- logger.info(mil_dict)
87
-
88
- title = f"Millenial\tPoint({p1+p2+p3+p4})\t{mil_dict['date']}\n"
89
- if full:
90
- contents = (f"1. 주주수익률({p1}): {mil_dict['주주수익률']} %\n"
91
- f"2. 이익지표({p2}): {mil_dict['이익지표']}\n"
92
- f"3. 투자수익률({p3}): ROIC 4분기합: {mil_dict['투자수익률']['ROIC']}%, "
93
- f"최근 ROE: {mil_dict['투자수익률']['ROE']}%\n"
94
- f"4. 가치지표\n"
95
- f"\tFCF: {mil_dict['가치지표']['FCF']}\n"
96
- f"\tPFCF({p4}) : {mil_dict['가치지표']['PFCF']}\n"
97
- f"\tPCR: {mil_dict['가치지표']['PCR']}")
98
- else:
99
- contents = (f"1. 주주수익률({p1}): {mil_dict['주주수익률']} %\n"
100
- f"2. 이익지표({p2}): {mil_dict['이익지표']}\n"
101
- f"3. 투자수익률({p3}): ROIC 4분기합: {mil_dict['투자수익률']['ROIC']}%, "
102
- f"최근 ROE: {mil_dict['투자수익률']['ROE']}%\n"
103
- f"4. 가치지표\tPFCF({p4}) : {mongo.EvalTools.get_recent(mil_dict['가치지표']['PFCF'])}")
104
- return title + contents
105
-
106
- def blue(self, full=True) -> str:
107
- blue_dict = eval.blue(self.code)
108
- p1, p2, p3, p4, p5 = score.blue(self.code)
109
- logger.info(blue_dict)
110
-
111
- title = f"Blue\tPoint({p1+p2+p3+p4+p5})\t{blue_dict['date']}\n"
112
- if full:
113
- contents = (f"1. 유동비율({p1}): {blue_dict['유동비율']}(100이하 위험)\n"
114
- f"2. 이자보상배율({p2}): {blue_dict['이자보상배율']}(1이하 위험 5이상 양호)\n"
115
- f"3. 순부채비율({p3}): {blue_dict['순부채비율']}(30이상 not good)\n"
116
- f"4. 순운전자본회전율({p4}): {blue_dict['순운전자본회전율']}\n"
117
- f"5. 재고자산회전율({p5}): {blue_dict['재고자산회전율']}")
118
-
119
- else:
120
- contents = ''
121
- return title + contents
122
-
123
- def growth(self, full=True) -> str:
124
- growth_dict = eval.growth(self.code)
125
- p1, p2 = score.growth(self.code)
126
- logger.info(growth_dict)
127
-
128
- title = f"Growth\tPoint({p1 + p2})\t{growth_dict['date']}\n"
129
- if full:
130
- contents = (f"1. 매출액증가율({p1}): {growth_dict['매출액증가율']}\n"
131
- f"2. 영업이익률({p2}): {growth_dict['영업이익률']}")
132
- else:
133
- contents = (f"1. 매출액증가율({p1}): {growth_dict['매출액증가율'][0]}\n"
134
- f"2. 영업이익률({p2}): {growth_dict['영업이익률'].get(self.name)}")
135
- return title + contents
136
-
137
- def for_django(self) -> dict:
138
- """
139
- 장고에서 report 페이지에서 사용될 eval & score data 를 반환
140
-
141
- 장고의 view context는 딕셔너리 형식이기 때문에 딕셔너리 모음으로 반환한다.
142
-
143
- 리턴값
144
- {'blue': {'date': ['2022/12'],
145
- '순부채비율': (-29.57, {'2018/12': -34.82,...'2023/12': -27.54}),
146
- '순운전자본회전율': (1.59, {'2018/12': 12.3,...'2023/12': nan}),
147
- '유동비율': 278.86,
148
- '이자보상배율': (15.7, {'2018/12': 87.29,...'2023/12': nan}),
149
- '재고자산회전율': (1.29, {'2018/12': 9.03,...'2023/12': nan})},
150
- 'blue_s': (0, 0, 0, -1, 0),
151
- 'c101': {'BPS': 50817.0, 'EPS': 8057.0, 'PBR': 1.28, 'PER': 8.08, 'date': '2023.04.14', 'intro': '...',
152
- '거래대금': '1062800000000', '거래량': '16176500', '발행주식': '5969782550', '배당수익률': '2.22', '베타52주': '0.95',
153
- '시가총액': '388632800000000', '업종': '반도체와반도체장비', '업종PER': '8.36', '유통비율': '75.82', '종목명': '삼성전자',
154
- '주가': '65100', '최고52주': '68800', '최저52주': '51800', '코드': '005930'},
155
- 'growth': {'date': ['2022/12'],
156
- '매출액증가율': (-8.23, {'2018/12': 1.75,...'2023/12': -10.5}),
157
- '영업이익률': {'LG디스플레이': '3.61', 'LG전자': '42.38', 'SK하이닉스': '15.26', '삼성전자': '14.35', '에스에프에이': '45.89'}},
158
- 'growth_s': (-2, 1),
159
- 'mil': {'date': ['2022/12'],
160
- '가치지표': {'FCF': {'2018/12': 374754.5,...'2023/12': 24605.8},
161
- 'PCR': {'2021/12': 8.17,...'2022/12': 6.04},
162
- 'PFCF': {'2018/12': 10.37,...'2023/12': 157.94}},
163
- '이익지표': -0.01917,
164
- '주주수익률': 4.99,
165
- '투자수익률': {'ROE': 17.07, 'ROIC': 13.41}},
166
- 'mil_s': (1, 10, 7, 0),
167
- 'red': {'date': ['2022/12'], 'red_price': 264881, '발행주식수': 6792669000.0, '부채평가': 1257599.6,
168
- '사업가치': 13682505.0, '재산가치': 5567563.52},
169
- 'red_s': (53, -75.42)}
170
- """
171
- return {
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),
181
- }
182
-
@@ -1,186 +0,0 @@
1
- from analyser_hj3415.analysers import eval, score
2
- from typing import Dict, Tuple
3
- from collections import OrderedDict
4
- from db_hj3415 import myredis as db_myredis
5
-
6
- page = '.analyser'
7
- myredis_base = db_myredis.Base()
8
-
9
- def get_redis_expect_earn(redis_name:str) -> float:
10
- redis_name_e = f'{redis_name}_expect_earn'
11
- byte_expect_earn = db_myredis.Base.redis_client.get(redis_name_e)
12
- if byte_expect_earn is not None:
13
- e = float(byte_expect_earn.decode('utf-8'))
14
- else:
15
- e = float('nan')
16
- return e
17
-
18
- def red_ranking(expect_earn: float, refresh=False) -> Tuple[OrderedDict, str]:
19
- """
20
- redis를 사용하며 red score를 계산해서 0이상의 값을 가지는 종목을 순서대로 저장하여 반환한다.
21
- :param expect_earn: 기대수익률(일반적으로 0.06 - 0.10)
22
- :param refresh: 캐시를 사용하지 않고 강제로 다시 계산
23
- :return: OrderedDict([('023590', 101),
24
- ('010060', 91),...]), 레디스이름
25
- """
26
-
27
- print("**** Start red_ranking... ****")
28
- redis_name = 'red_ranking'
29
- redis_name_e = f'{redis_name}_expect_earn'
30
- if get_redis_expect_earn(redis_name) != expect_earn:
31
- # 레디스 저장값과 기대수익률이 다르다면 무조건 리프레시 한다.
32
- refresh = True
33
- db_myredis.Base.redis_client.setex(redis_name_e, db_myredis.Base.DEFAULT_CACHE_EXPIRATION_SEC, expect_earn)
34
-
35
- def fetch_red_scores(expect_earn_i: float) -> Dict:
36
- data = {}
37
- for i, code in enumerate(db_myredis.Corps.list_all_codes()):
38
- red_score = score.red(code, expect_earn_i)
39
- if red_score > 0:
40
- data[code] = red_score
41
- print(f"{i}: {code} - {red_score}")
42
- return data
43
-
44
- data = myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_red_scores, expect_earn)
45
- return OrderedDict(sorted(data.items(), key=lambda item: item[1], reverse=True)), redis_name
46
-
47
-
48
-
49
- def red_n_score(code: str, expect_earn: float, refresh=False) -> Tuple[dict, str]:
50
- """
51
- red 평가후 스코어 계산후 red 딕셔너리에 첨가후 반환
52
- :param code: 종목코드
53
- :param expect_earn: 기대수익률(일반적으로 0.06 - 0.10)
54
- :param refresh: 캐시를 사용하지 않고 강제로 다시 계산
55
- :return:
56
- """
57
- redis_name = f"{code}_{page}_red_n_score"
58
- redis_name_e = f'{redis_name}_expect_earn'
59
- if get_redis_expect_earn(redis_name) != expect_earn:
60
- # 레디스 저장값과 기대수익률이 다르다면 무조건 리프레시 한다.
61
- refresh = True
62
- # print(get_redis_expect_earn(redis_name))
63
- db_myredis.Base.redis_client.setex(redis_name_e, db_myredis.Base.DEFAULT_CACHE_EXPIRATION_SEC, expect_earn)
64
-
65
- def fetch_red_n_score(code_i: str, expect_earn_i: float) -> dict:
66
- data = eval.red(code_i, expect_earn_i)
67
- data['score'] = score.red(code_i, expect_earn_i)
68
- return data
69
-
70
- return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_red_n_score, code, expect_earn), redis_name
71
-
72
-
73
- def mil_n_score(code: str, expect_earn: float, refresh=False) -> Tuple[dict, str]:
74
- """
75
- redis 사용 - 소멸타이머 사용
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
- redis_name = f"{code}_{page}_mil_n_score"
110
- redis_name_e = f'{redis_name}_expect_earn'
111
- if get_redis_expect_earn(redis_name) != expect_earn:
112
- # 레디스 저장값과 기대수익률이 다르다면 무조건 리프레시 한다.
113
- refresh = True
114
- db_myredis.Base.redis_client.setex(redis_name_e, db_myredis.Base.DEFAULT_CACHE_EXPIRATION_SEC, expect_earn)
115
-
116
- def fetch_mil_n_score(code_i: str) -> dict:
117
- data = eval.mil(code_i)
118
- data['score'] = score.mil(code_i, expect_earn)
119
- return data
120
-
121
- return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_mil_n_score, code), redis_name
122
-
123
-
124
- def blue_n_score(code: str, refresh=False) -> Tuple[dict, str]:
125
- """
126
- redis 사용 - 소멸타이머 사용
127
- 리턴값
128
- {
129
- 'date': [각 유효한 값의 최근분기 값 리스트(ex- 2020/09)],
130
- '순부채비율': (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}),
131
- '순운전자본회전율': (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}),
132
- '유동비율': 64.29,
133
- '이자보상배율': (-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}),
134
- '재고자산회전율': (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})
135
- }
136
-
137
- <유동비율>
138
- 100미만이면 주의하나 현금흐름창출력이 좋으면 괜찮을수 있다.
139
- 만약 100%이하면 유동자산에 추정영업현금흐름을 더해서 다시계산해보아 기회를 준다.
140
- <이자보상배율>
141
- 이자보상배율 영업이익/이자비용으로 1이면 자금사정빡빡 5이상이면 양호
142
- <순운전자금회전율>
143
- 순운전자금 => 기업활동을 하기 위해 필요한 자금 (매출채권 + 재고자산 - 매입채무)
144
- 순운전자본회전율은 매출액/순운전자본으로 일정비율이 유지되는것이 좋으며 너무 작아지면 순운전자본이 많아졌다는 의미로 재고나 외상이 쌓인다는 뜻
145
- <재고자산회전율>
146
- 재고자산회전율은 매출액/재고자산으로 회전율이 낮을수록 재고가 많다는 이야기이므로 불리 전년도등과 비교해서 큰차이 발생하면 알람.
147
- 재고자산회전율이 작아지면 재고가 쌓인다는뜻
148
- <순부채비율>
149
- 부채비율은 업종마다 달라 일괄비교 어려우나 순부채 비율이 20%이하인것이 좋고 꾸준히 늘어나지 않는것이 좋다.
150
- 순부채 비율이 30%이상이면 좋치 않다.
151
- <매출액>
152
- 매출액은 어떤경우에도 성장하는 기업이 좋다.매출이 20%씩 늘어나는 종목은 유망한 종목
153
- <영업이익률>
154
- 영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
155
- """
156
- redis_name = f"{code}_{page}_blue_n_score"
157
-
158
- def fetch_blue_n_score(code_i: str) -> dict:
159
- data = eval.blue(code_i)
160
- data['score'] = score.blue(code_i)
161
- return data
162
-
163
- return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_blue_n_score, code), redis_name
164
-
165
-
166
- def growth_n_score(code: str, refresh=False) -> Tuple[dict, str]:
167
- """
168
- redis 사용 - 소멸타이머 사용
169
- 리턴값
170
- {'date': [각 유효한 값의 최근분기 값 리스트(ex- 2020/09)],
171
- '매출액증가율': (-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}),
172
- '영업이익률': {'뉴프렉스': '17.36', '동일기연': '13.58', '비에이치': '16.23', '에이엔피': '-9.30', '이브이첨단소재': '-4.93'}}
173
-
174
- <매출액>
175
- 매출액은 어떤경우에도 성장하는 기업이 좋다.매출이 20%씩 늘어나는 종목은 유망한 종목
176
- <영업이익률>
177
- 영업이익률은 기업의 경쟁력척도로 경쟁사에 비해 높으면 경제적해자를 갖춘셈
178
- """
179
- redis_name = f"{code}_{page}_growth_n_score"
180
-
181
- def fetch_growth_n_score(code_i: str) -> dict:
182
- data = eval.growth(code_i)
183
- data['score'] = score.growth(code_i)
184
- return data
185
-
186
- return myredis_base.fetch_and_cache_data(redis_name, refresh, fetch_growth_n_score, code), redis_name
analyser_hj3415/tools.py DELETED
@@ -1,247 +0,0 @@
1
- import math
2
- from typing import Tuple
3
- from db_hj3415.myredis import C101, C103, C104
4
-
5
- import logging
6
-
7
- logger = logging.getLogger(__name__)
8
- formatter = logging.Formatter('%(levelname)s: [%(name)s] %(message)s')
9
- ch = logging.StreamHandler()
10
- ch.setFormatter(formatter)
11
- logger.addHandler(ch)
12
- logger.setLevel(logging.WARNING)
13
-
14
-
15
- def set_data(*args) -> list:
16
- """
17
- 비유효한 내용 제거(None,nan)하고 중복된 항목 제거하고 리스트로 반환한다.
18
- 여기서 set의 의미는 집합을 뜻함
19
- :param args:
20
- :return:
21
- """
22
- return [i for i in {*args} if i != "" and i is not math.nan and i is not None]
23
-
24
-
25
- def calc당기순이익(code: str) -> Tuple[str, float]:
26
- """지배지분 당기순이익 계산
27
-
28
- 일반적인 경우로는 직전 지배주주지분 당기순이익을 찾아서 반환한다.\n
29
- 금융기관의 경우는 지배당기순이익이 없기 때문에\n
30
- 계산을 통해서 간접적으로 구한다.\n
31
- """
32
- logger.debug(f'In the calc당기순이익... code:{code}')
33
- c103q = C103(code, 'c103재무상태표q')
34
- try:
35
- # print("*(지배)당기순이익: ", c103q.latest_value_pop2('*(지배)당기순이익'))
36
- return c103q.latest_value_pop2('*(지배)당기순이익')
37
- except:
38
- logger.warning(f"{code} - (지배)당기순이익이 없는 종목. 수동으로 계산합니다(금융관련업종일 가능성있음).")
39
- c103q.page = 'c103손익계산서q'
40
- 최근당기순이익date, 최근당기순이익value = c103q.sum_recent_4q('당기순이익')
41
- c103q.page = 'c103재무상태표q'
42
- 비지배당기순이익date, 비지배당기순이익value = c103q.latest_value_pop2('*(비지배)당기순이익')
43
-
44
- # 가변리스트 언패킹으로 하나의 날짜만 사용하고 나머지는 버린다.
45
- date, *_ = set_data(최근당기순이익date, 비지배당기순이익date)
46
- 계산된지배당기순이익value = 최근당기순이익value - 비지배당기순이익value
47
-
48
- return date, 계산된지배당기순이익value
49
-
50
-
51
- def calc유동자산(code: str) -> Tuple[str, float]:
52
- """유효한 유동자산 계산
53
-
54
- 일반적인 경우로 유동자산을 찾아서 반환한다.\n
55
- 금융기관의 경우는 간접적으로 계산한다.\n
56
- Red와 Blue에서 사용한다.\n
57
- """
58
- logger.debug(f'In the calc유동자산... code:{code}')
59
- c103q = C103(code, 'c103재무상태표q')
60
- try:
61
- return c103q.sum_recent_4q('유동자산')
62
- except:
63
- logger.warning(f"{code} - 유동자산이 없는 종목. 수동으로 계산합니다(금융관련업종일 가능성있음).")
64
- d1, v1 = c103q.latest_value_pop2('현금및예치금')
65
- d2, v2 = c103q.latest_value_pop2('단기매매금융자산')
66
- d3, v3 = c103q.latest_value_pop2('매도가능금융자산')
67
- d4, v4 = c103q.latest_value_pop2('만기보유금융자산')
68
- logger.debug(f'현금및예치금 : {d1}, {v1}')
69
- logger.debug(f'단기매매금융자산 : {d2}, {v2}')
70
- logger.debug(f'매도가능금융자산 : {d3}, {v3}')
71
- logger.debug(f'만기보유금융자산 : {d4}, {v4}')
72
-
73
- date, *_ = set_data(d1, d2, d3, d4)
74
- 계산된유동자산value = v1 + v2 + v3 + v4
75
-
76
- return date, 계산된유동자산value
77
-
78
-
79
- def calc유동부채(code: str) -> Tuple[str, float]:
80
- """유효한 유동부채 계산
81
-
82
- 일반적인 경우로 유동부채를 찾아서 반환한다.\n
83
- 금융기관의 경우는 간접적으로 계산한다.\n
84
- Red와 Blue에서 사용한다.\n
85
- """
86
- logger.debug(f'In the calc유동부채... code:{code}')
87
- c103q = C103(code, 'c103재무상태표q')
88
- try:
89
- return c103q.sum_recent_4q('유동부채')
90
- except:
91
- logger.warning(f"{code} - 유동부채가 없는 종목. 수동으로 계산합니다(금융관련업종일 가능성있음).")
92
- d1, v1 = c103q.latest_value_pop2('당기손익인식(지정)금융부채')
93
- d2, v2 = c103q.latest_value_pop2('당기손익-공정가치측정금융부채')
94
- d3, v3 = c103q.latest_value_pop2('매도파생결합증권')
95
- d4, v4 = c103q.latest_value_pop2('단기매매금융부채')
96
- logger.debug(f'당기손익인식(지정)금융부채 : {d1}, {v1}')
97
- logger.debug(f'당기손익-공정가치측정금융부채 : {d2}, {v2}')
98
- logger.debug(f'매도파생결합증권 : {d3}, {v3}')
99
- logger.debug(f'단기매매금융부채 : {d4}, {v4}')
100
-
101
- date, *_ = set_data(d1, d2, d3, d4)
102
- 계산된유동부채value = v1 + v2 + v3 + v4
103
-
104
- return date, 계산된유동부채value
105
-
106
-
107
- def calc비유동부채(code: str) -> Tuple[str, float]:
108
- """유효한 비유동부채 계산
109
-
110
- 일반적인 경우로 비유동부채를 찾아서 반환한다.\n
111
- 금융기관의 경우는 간접적으로 계산한다.\n
112
- Red와 Blue에서 사용한다.\n
113
- """
114
- logger.debug(f'In the calc비유동부채... code:{code}')
115
- c103q = C103(code, 'c103재무상태표q')
116
- try:
117
- return c103q.sum_recent_4q('비유동부채')
118
- except:
119
- logger.warning(f"{code} - 비유동부채가 없는 종목. 수동으로 계산합니다(금융관련업종일 가능성있음).")
120
- # 보험관련업종은 예수부채가 없는대신 보험계약부채가 있다...
121
- d1, v1 = c103q.latest_value_pop2('예수부채')
122
- d2, v2 = c103q.latest_value_pop2('보험계약부채(책임준비금)')
123
- d3, v3 = c103q.latest_value_pop2('차입부채')
124
- d4, v4 = c103q.latest_value_pop2('기타부채')
125
- logger.debug(f'예수부채 : {d1}, {v1}')
126
- logger.debug(f'보험계약부채(책임준비금) : {d2}, {v2}')
127
- logger.debug(f'차입부채 : {d3}, {v3}')
128
- logger.debug(f'기타부채 : {d4}, {v4}')
129
-
130
- date, *_ = set_data(d1, d2, d3, d4)
131
- 계산된비유동부채value = v1 + v2 + v3 + v4
132
-
133
- return date, 계산된비유동부채value
134
-
135
-
136
- def calc유동비율(code: str, pop_count: int) -> Tuple[str, float]:
137
- """유동비율계산 - Blue에서 사용
138
-
139
- c104q에서 최근유동비율 찾아보고 유효하지 않거나 \n
140
- 100이하인 경우에는수동으로 계산해서 다시 한번 평가해 본다.\n
141
- """
142
- logger.debug(f'In the calc유동비율... code:{code}')
143
- c104q = C104(code, 'c104q')
144
- 유동비율date, 유동비율value = c104q.mymongo_c1034.latest_value('유동비율', pop_count=pop_count)
145
- logger.debug(f'{code} 유동비율 : {유동비율value}({유동비율date})')
146
-
147
- if math.isnan(유동비율value) or 유동비율value < 100:
148
- logger.warning('유동비율 is under 100 or nan..so we will recalculate..')
149
- 유동자산date, 유동자산value = calc유동자산(code)
150
- 유동부채date, 유동부채value = calc유동부채(code)
151
-
152
- c103q = C103(code, 'c103현금흐름표q')
153
- 추정영업현금흐름date, 추정영업현금흐름value = c103q.sum_recent_4q('영업활동으로인한현금흐름')
154
- logger.debug(f'{code} 계산전 유동비율 : {유동비율value}({유동비율date})')
155
-
156
- 계산된유동비율 = 0
157
- try:
158
- 계산된유동비율 = round(((유동자산value + 추정영업현금흐름value) / 유동부채value) * 100, 2)
159
- except ZeroDivisionError:
160
- logger.debug(f'유동자산: {유동자산value} + 추정영업현금흐름: {추정영업현금흐름value} / 유동부채: {유동부채value}')
161
- 계산된유동비율 = float('inf')
162
- finally:
163
- logger.debug(f'{code} 계산된 유동비율 : {계산된유동비율}')
164
- date, *_ = set_data(유동자산date, 유동부채date, 추정영업현금흐름date)
165
- return date, 계산된유동비율
166
- else:
167
- return 유동비율date, 유동비율value
168
-
169
-
170
- def findFCF(code: str) -> dict:
171
- """
172
- FCF 계산
173
- Returns:
174
- dict: 계산된 fcf 딕셔너리 또는 영업현금흐름 없는 경우 - {}
175
-
176
- Note:
177
- CAPEX 가 없는 업종은 영업활동현금흐름을 그대로 사용한다.\n
178
-
179
- """
180
- c103y = C103(code, 'c103현금흐름표y')
181
- _, 영업활동현금흐름_dict = c103y.find_without_yoy('영업활동으로인한현금흐름')
182
- c103y.page = 'c103재무상태표y'
183
- _, capex = c103y.find_without_yoy('*CAPEX')
184
-
185
- logger.debug(f'영업활동현금흐름 {영업활동현금흐름_dict}')
186
- logger.debug(f'CAPEX {capex}')
187
-
188
- if len(영업활동현금흐름_dict) == 0:
189
- return {}
190
-
191
- if len(capex) == 0:
192
- # CAPEX 가 없는 업종은 영업활동현금흐름을 그대로 사용한다.
193
- logger.warning(f"{code} - CAPEX가 없는 업종으로 영업현금흐름을 그대로 사용합니다..")
194
- return 영업활동현금흐름_dict
195
-
196
- # 영업 활동으로 인한 현금 흐름에서 CAPEX 를 각 연도별로 빼주어 fcf 를 구하고 리턴값으로 fcf 딕셔너리를 반환한다.
197
- r_dict = {}
198
- for i in range(len(영업활동현금흐름_dict)):
199
- # 영업활동현금흐름에서 아이템을 하나씩 꺼내서 CAPEX 전체와 비교하여 같으면 차를 구해서 r_dict 에 추가한다.
200
- 영업활동현금흐름date, 영업활동현금흐름value = 영업활동현금흐름_dict.popitem()
201
- # 해당 연도의 capex 가 없는 경우도 있어 일단 capex를 0으로 치고 먼저 추가한다.
202
- r_dict[영업활동현금흐름date] = 영업활동현금흐름value
203
- for CAPEXdate, CAPEXvalue in capex.items():
204
- if 영업활동현금흐름date == CAPEXdate:
205
- r_dict[영업활동현금흐름date] = round(영업활동현금흐름value - CAPEXvalue, 2)
206
- logger.debug(f'r_dict {r_dict}')
207
- # 연도순으로 정렬해서 딕셔너리로 반환한다.
208
- return dict(sorted(r_dict.items(), reverse=False))
209
-
210
-
211
- def findPFCF(code: str) -> dict:
212
- """Price to Free Cash Flow Ratio(주가 대비 자유 현금 흐름 비율)계산
213
-
214
- PFCF = 시가총액 / FCF
215
-
216
- Note:
217
- https://www.investopedia.com/terms/p/pricetofreecashflow.asp
218
- """
219
- # marketcap 계산 (fcf가 억 단위라 시가총액을 억으로 나눠서 단위를 맞춰 준다)
220
- marketcap억 = get_marketcap(code) / 100000000
221
- if math.isnan(marketcap억):
222
- return {}
223
-
224
- # pfcf 계산
225
- fcf_dict = findFCF(code)
226
- logger.debug(f'fcf_dict : {fcf_dict}')
227
- pfcf_dict = {}
228
- for FCFdate, FCFvalue in fcf_dict.items():
229
- if FCFvalue == 0:
230
- pfcf_dict[FCFdate] = math.nan
231
- else:
232
- pfcf_dict[FCFdate] = round(marketcap억 / FCFvalue, 2)
233
- logger.debug(f'pfcf_dict : {pfcf_dict}')
234
- return pfcf_dict
235
-
236
-
237
- def get_marketcap(code: str) -> float:
238
- """
239
- 시가총액(원) 반환
240
- :param code:
241
- :return:
242
- """
243
- c101 = C101(code)
244
- try:
245
- return int(c101.get_recent()['시가총액'])
246
- except KeyError:
247
- return math.nan
@@ -1,14 +0,0 @@
1
- analyser_hj3415/.DS_Store,sha256=qr9-0FPn5CFKe6kEu8_dWCNhzQ0sN7bwQgffKsaJEEo,6148
2
- analyser_hj3415/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- analyser_hj3415/cli.py,sha256=eLo3U2VpBXVFwCCwxvge-nLc6wEeWWCbcORHRFELAFs,7356
4
- analyser_hj3415/myredis.py,sha256=e9WH9Vbyph3jsA1TO9KWjow6-wxct4vLwINjRVHw1IQ,9609
5
- analyser_hj3415/tools.py,sha256=lyfvmze9e4lGqgimuVOXUbgt7YNaJ7h8PpC7dWaaW94,10942
6
- analyser_hj3415/trash.py,sha256=zF-W0piqkGr66UP6-iybo9EXh2gO0RP6R1FnIpsGkl8,12262
7
- analyser_hj3415/analysers/eval.py,sha256=Ihx1UiNbrUUPgaZLNvbWQfO_aAwlB9vxREXJl7HNA_c,12072
8
- analyser_hj3415/analysers/report.py,sha256=yY-AeDHOqDPrm4lpvZv3NPTJK1Z7lKsjoO5ck8AP6u4,9007
9
- analyser_hj3415/analysers/score.py,sha256=8dlnYu-iQiwY-pkKH4N05MVanVGVsOajmryVR9_BYMI,18534
10
- analyser_hj3415-2.6.8.dist-info/entry_points.txt,sha256=ZfjPnJuH8SzvhE9vftIPMBIofsc65IAWYOhqOC_L5ck,65
11
- analyser_hj3415-2.6.8.dist-info/LICENSE,sha256=QVKTp0dTnB5xG8RLgG17LwSWCKNEzYoVVM6KjoCPKc0,1079
12
- analyser_hj3415-2.6.8.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
13
- analyser_hj3415-2.6.8.dist-info/METADATA,sha256=cXfIcA1mrmJ2lLnnEG7xU8kBhS0G2E8H4LfiPy01r-g,6417
14
- analyser_hj3415-2.6.8.dist-info/RECORD,,
File without changes