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/.DS_Store +0 -0
- analyser_hj3415/analysers/eval.py +289 -0
- analyser_hj3415/{report.py → analysers/report.py} +23 -59
- analyser_hj3415/{score.py → analysers/score.py} +57 -61
- analyser_hj3415/myredis.py +175 -0
- analyser_hj3415/{db/evaltools.py → tools.py} +102 -79
- analyser_hj3415/trash.py +210 -0
- {analyser_hj3415-2.0.2.dist-info → analyser_hj3415-2.2.0.dist-info}/METADATA +5 -9
- analyser_hj3415-2.2.0.dist-info/RECORD +15 -0
- analyser_hj3415/db/.DS_Store +0 -0
- analyser_hj3415/db/chk_db.py +0 -240
- analyser_hj3415/db/mongo.py +0 -934
- analyser_hj3415/eval.py +0 -382
- analyser_hj3415-2.0.2.dist-info/RECORD +0 -16
- /analyser_hj3415/{db/__init__.py → run.py} +0 -0
- {analyser_hj3415-2.0.2.dist-info → analyser_hj3415-2.2.0.dist-info}/LICENSE +0 -0
- {analyser_hj3415-2.0.2.dist-info → analyser_hj3415-2.2.0.dist-info}/WHEEL +0 -0
- {analyser_hj3415-2.0.2.dist-info → analyser_hj3415-2.2.0.dist-info}/entry_points.txt +0 -0
analyser_hj3415/trash.py
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
def _make_df_part(db_addr, codes: list, q):
|
4
|
+
def make_record(my_client, my_code: str) -> dict:
|
5
|
+
# 장고에서 사용할 eval 테이블을 만들기 위해 각각의 레코드를 구성하는 함수
|
6
|
+
c101 = mongo.C101(my_client, my_code).get_recent()
|
7
|
+
|
8
|
+
red_dict = red(my_client, my_code)
|
9
|
+
mil_dict = mil(my_client, my_code)
|
10
|
+
growth_dict = growth(my_client, my_code)
|
11
|
+
|
12
|
+
mil_date = mil_dict['date']
|
13
|
+
red_date = red_dict['date']
|
14
|
+
growth_date = growth_dict['date']
|
15
|
+
|
16
|
+
return {
|
17
|
+
'code': c101['코드'],
|
18
|
+
'종목명': c101['종목명'],
|
19
|
+
'주가': utils.to_int(c101['주가']),
|
20
|
+
'PER': utils.to_float(c101['PER']),
|
21
|
+
'PBR': utils.to_float(c101['PBR']),
|
22
|
+
'시가총액': utils.to_float(c101['시가총액']),
|
23
|
+
'RED': utils.to_int(red_dict['red_price']),
|
24
|
+
'주주수익률': utils.to_float(mil_dict['주주수익률']),
|
25
|
+
'이익지표': utils.to_float(mil_dict['이익지표']),
|
26
|
+
'ROIC': utils.to_float(mil_dict['투자수익률']['ROIC']),
|
27
|
+
'ROE': utils.to_float(mil_dict['투자수익률']['ROE']),
|
28
|
+
'PFCF': utils.to_float(mongo.Corps.latest_value(mil_dict['가치지표']['PFCF'])[1]),
|
29
|
+
'PCR': utils.to_float(mongo.Corps.latest_value(mil_dict['가치지표']['PCR'])[1]),
|
30
|
+
'매출액증가율': utils.to_float(growth_dict['매출액증가율'][0]),
|
31
|
+
'date': list(set(mil_date + red_date + growth_date))
|
32
|
+
}
|
33
|
+
# 각 코어별로 디비 클라이언트를 만들어야만 한다. 안그러면 에러발생
|
34
|
+
client = mongo.connect_mongo(db_addr)
|
35
|
+
t = len(codes)
|
36
|
+
d = []
|
37
|
+
for i, code in enumerate(codes):
|
38
|
+
print(f'{i+1}/{t} {code}')
|
39
|
+
try:
|
40
|
+
d.append(make_record(client, code))
|
41
|
+
except:
|
42
|
+
logger.error(f'error on {code}')
|
43
|
+
continue
|
44
|
+
df = pd.DataFrame(d)
|
45
|
+
logger.info(df)
|
46
|
+
q.put(df)
|
47
|
+
|
48
|
+
|
49
|
+
def make_today_eval_df(client, refresh: bool = False) -> pd.DataFrame:
|
50
|
+
""" 멀티프로세싱을 사용하여 전체 종목의 eval 을 데이터프레임으로 만들어 반환
|
51
|
+
|
52
|
+
기본값으로 refresh 는 False 로 설정되어 당일자의 저장된 데이터프레임이 있으면 새로 생성하지 않고 mongo DB를 이용한다.
|
53
|
+
"""
|
54
|
+
today_str = datetime.datetime.today().strftime('%Y%m%d')
|
55
|
+
df = mongo.EvalByDate(client, today_str).load_df()
|
56
|
+
if refresh or len(df) == 0:
|
57
|
+
codes_in_db = mongo.Corps.get_all_codes(client)
|
58
|
+
|
59
|
+
print('*' * 25, f"Eval all using multiprocess(refresh={refresh})", '*' * 25)
|
60
|
+
print(f'Total {len(codes_in_db)} items..')
|
61
|
+
logger.debug(codes_in_db)
|
62
|
+
n, divided_list = utils.code_divider_by_cpu_core(codes_in_db)
|
63
|
+
|
64
|
+
addr = mongo.extract_addr_from_client(client)
|
65
|
+
|
66
|
+
start_time = time.time()
|
67
|
+
q = Queue()
|
68
|
+
ths = []
|
69
|
+
for i in range(n):
|
70
|
+
ths.append(Process(target=_make_df_part, args=(addr, divided_list[i], q)))
|
71
|
+
for i in range(n):
|
72
|
+
ths[i].start()
|
73
|
+
|
74
|
+
df_list = []
|
75
|
+
for i in range(n):
|
76
|
+
df_list.append(q.get())
|
77
|
+
# 부분데이터프레임들을 하나로 합침
|
78
|
+
final_df = pd.concat(df_list, ignore_index=True)
|
79
|
+
|
80
|
+
for i in range(n):
|
81
|
+
ths[i].join()
|
82
|
+
|
83
|
+
print(f'Total spent time : {round(time.time() - start_time, 2)} sec.')
|
84
|
+
logger.debug(final_df)
|
85
|
+
print(f"Save to mongo db(db: eval col: {today_str})")
|
86
|
+
mongo.EvalByDate(client, today_str).save_df(final_df)
|
87
|
+
else:
|
88
|
+
print(f"Use saved dataframe from mongo db..")
|
89
|
+
final_df = df
|
90
|
+
return final_df
|
91
|
+
|
92
|
+
|
93
|
+
def yield_valid_spac(client) -> tuple:
|
94
|
+
"""
|
95
|
+
전체 스팩주의 현재가를 평가하여 2000원 이하인 경우 yield한다.
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
tuple: (code, name, price)
|
99
|
+
"""
|
100
|
+
codes = mongo.Corps.get_all_codes(client)
|
101
|
+
logger.debug(f'len(codes) : {len(codes)}')
|
102
|
+
print('<<< Finding valuable SPAC >>>')
|
103
|
+
for i, code in enumerate(codes):
|
104
|
+
name = mongo.Corps.get_name(client, code)
|
105
|
+
logger.debug(f'code : {code} name : {name}')
|
106
|
+
if '스팩' in str(name):
|
107
|
+
logger.debug(f'>>> spac - code : {code} name : {name}')
|
108
|
+
price, _, _ = utils.get_price_now(code=code)
|
109
|
+
if price <= 2000:
|
110
|
+
logger.warning(f'현재가:{price}')
|
111
|
+
print(f"code: {code} name: {name}, price: {price}")
|
112
|
+
yield code, name, price
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
class GetDFTest(unittest.TestCase):
|
117
|
+
def test_make_df_part(self):
|
118
|
+
codes = ['025320', '000040', '060280', '003240']
|
119
|
+
from multiprocessing import Queue
|
120
|
+
q = Queue()
|
121
|
+
eval._make_df_part(addr, codes, q)
|
122
|
+
|
123
|
+
def test_get_df(self):
|
124
|
+
print(eval.make_today_eval_df(client, refresh=True))
|
125
|
+
print(eval.make_today_eval_df(client, refresh=False))
|
126
|
+
|
127
|
+
|
128
|
+
class SpacTest(unittest.TestCase):
|
129
|
+
def test_valid_spac(self):
|
130
|
+
for code, name, price in eval.yield_valid_spac(client):
|
131
|
+
print(code, name, price)
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
def mil(code: str) -> Tuple[int, int, int, int]:
|
137
|
+
"""
|
138
|
+
- 재무활동현금흐름이 마이너스라는 것은 배당급 지급했거나, 자사주 매입했거나, 부채를 상환한 상태임.
|
139
|
+
- 반대는 채권자로 자금을 조달했거나 신주를 발행했다는 의미
|
140
|
+
<주주수익률> - 재무활동현금흐름/시가총액 => 5%이상인가?
|
141
|
+
|
142
|
+
투하자본수익률(ROIC)가 30%이상인가
|
143
|
+
ROE(자기자본이익률) 20%이상이면 아주 우수 다른 투자이익률과 비교해볼것 10%미만이면 별로...단, 부채비율을 확인해야함.
|
144
|
+
|
145
|
+
이익지표 ...영업현금흐름이 순이익보다 많은가 - 결과값이 음수인가..
|
146
|
+
|
147
|
+
FCF는 영업현금흐름에서 자본적 지출(유·무형투자 비용)을 차감한 순수한 현금력이라 할 수 있다.
|
148
|
+
말 그대로 자유롭게(Free) 사용할 수 있는 여윳돈을 뜻한다.
|
149
|
+
잉여현금흐름이 플러스라면 미래의 투자나 채무상환에 쓸 재원이 늘어난 것이다.
|
150
|
+
CAPEX(Capital expenditures)는 미래의 이윤을 창출하기 위해 지출된 비용을 말한다.
|
151
|
+
이는 기업이 고정자산을 구매하거나, 유효수명이 당회계년도를 초과하는 기존의 고정자산에 대한 투자에 돈이 사용될 때 발생한다.
|
152
|
+
|
153
|
+
잉여현금흐름이 마이너스일때는 설비투자가 많은 시기라 주가가 약세이며 이후 설비투자 마무리되면서 주가가 상승할수 있다.
|
154
|
+
주가는 잉여현금흐름이 증가할때 상승하는 경향이 있다.
|
155
|
+
fcf = 영업현금흐름 - capex
|
156
|
+
|
157
|
+
가치지표평가
|
158
|
+
price to fcf 계산
|
159
|
+
https://www.investopedia.com/terms/p/pricetofreecashflow.asp
|
160
|
+
pcr보다 정확하게 주식의 가치를 평가할수 있음. 10배이하 추천
|
161
|
+
|
162
|
+
Returns:
|
163
|
+
tuple: 주주수익률, 이익지표, 투자수익률, PFCF포인트
|
164
|
+
"""
|
165
|
+
mil_dict = eval.mil(code)
|
166
|
+
|
167
|
+
print(pprint.pformat(mil_dict, width=200))
|
168
|
+
|
169
|
+
# 주주수익률 평가
|
170
|
+
if math.isnan(mil_dict['주주수익률']):
|
171
|
+
score1 = 0
|
172
|
+
else:
|
173
|
+
주주수익률평가 = math.ceil(mil_dict['주주수익률'] - (eval.EXPECT_EARN * 100))
|
174
|
+
score1 = 0 if 0 > 주주수익률평가 else 주주수익률평가
|
175
|
+
|
176
|
+
# 이익지표 평가
|
177
|
+
score2 = 10 if mil_dict['이익지표'] < 0 else 0
|
178
|
+
|
179
|
+
# 투자수익률 평가
|
180
|
+
MAX3 = 20
|
181
|
+
score3 = 0
|
182
|
+
roic = mil_dict['투자수익률']['ROIC']
|
183
|
+
roe = mil_dict['투자수익률']['ROE']
|
184
|
+
if math.isnan(roic) or roic <= 0:
|
185
|
+
# roic 가 비정상이라 평가할 수 없는 경우
|
186
|
+
if 10 < roe <= 20:
|
187
|
+
score3 += round(MAX3 * 0.333)
|
188
|
+
elif 20 < roe:
|
189
|
+
score3 += round(MAX3 * 0.666)
|
190
|
+
elif 0 < roic:
|
191
|
+
# roic 로 평가할 수 있는 경우
|
192
|
+
if 0 < roic <= 15:
|
193
|
+
score3 += round(MAX3 * 0.333)
|
194
|
+
elif 15 < roic <= 30:
|
195
|
+
score3 += round(MAX3 * 0.666)
|
196
|
+
elif 30 < roic:
|
197
|
+
score3 += MAX3
|
198
|
+
|
199
|
+
# PFCF 평가
|
200
|
+
pfcf_dict = mil_dict['가치지표']['PFCF']
|
201
|
+
_, pfcf = mongo.Corps.latest_value(pfcf_dict)
|
202
|
+
|
203
|
+
logger.debug(f'recent pfcf {_}, {pfcf}')
|
204
|
+
try:
|
205
|
+
p = round(-40 * math.log10(pfcf) + 40)
|
206
|
+
except ValueError:
|
207
|
+
p = 0
|
208
|
+
score4 = 0 if 0 > p else p
|
209
|
+
|
210
|
+
return score1, score2, score3, score4
|
@@ -1,15 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: analyser_hj3415
|
3
|
-
Version: 2.0
|
3
|
+
Version: 2.2.0
|
4
4
|
Summary: Stock analyser and database processing programs
|
5
5
|
Author-email: Hyungjin Kim <hj3415@gmail.com>
|
6
6
|
Description-Content-Type: text/markdown
|
7
7
|
Classifier: License :: OSI Approved :: MIT License
|
8
|
-
Requires-Dist:
|
9
|
-
Requires-Dist:
|
10
|
-
Requires-Dist: sqlalchemy>=2.0.31
|
11
|
-
Requires-Dist: utils-hj3415>=2.0.1
|
12
|
-
Requires-Dist: scraper2-hj3415>=2.0.0
|
8
|
+
Requires-Dist: utils-hj3415>=2.6.0
|
9
|
+
Requires-Dist: db-hj3415>=3.3.2
|
13
10
|
Project-URL: Home, https://www.hyungjin.kr
|
14
11
|
|
15
12
|
### analyser-hj3415
|
@@ -20,12 +17,11 @@ analyser_hj3415 manage the database.
|
|
20
17
|
---
|
21
18
|
#### Requirements
|
22
19
|
|
23
|
-
scrapy>=2.11.2
|
24
20
|
pandas>=2.2.2
|
21
|
+
pymongo>=4.8.0
|
25
22
|
sqlalchemy>=2.0.31
|
26
|
-
selenium>=4.22.0
|
27
23
|
utils-hj3415>=2.0.1
|
28
|
-
|
24
|
+
scraper-hj3415>=2.0.0
|
29
25
|
|
30
26
|
---
|
31
27
|
#### API
|
@@ -0,0 +1,15 @@
|
|
1
|
+
analyser_hj3415/.DS_Store,sha256=OQfTSOHL-zjUtnNyBpNRVUJUstR4j6I7jihKDFQQmME,6148
|
2
|
+
analyser_hj3415/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
analyser_hj3415/cli.py,sha256=qzRnpDRJvQnQevSKHBpKbTsBjmSWllZjzTV4z_alg2A,4891
|
4
|
+
analyser_hj3415/myredis.py,sha256=zgsXO4G2VsXt4LID4VF-Y7AqkPjV8Th66a2czuma_bM,8738
|
5
|
+
analyser_hj3415/run.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
analyser_hj3415/tools.py,sha256=SNsrnL5CKmKAdFkmlwgREMIkWDRi6N9LngCdhhhop3Y,13606
|
7
|
+
analyser_hj3415/trash.py,sha256=vHrv8Q61QOkcwhmWfrj_yVdsdd5MoAxs9gXMOJEjMHM,8360
|
8
|
+
analyser_hj3415/analysers/eval.py,sha256=mlHi6EPc8l8O6vKnWyX4Cz1BaeGhUpWM8gVZRNhm-JU,13299
|
9
|
+
analyser_hj3415/analysers/report.py,sha256=whggmLXl7yF-BjQ6JKgxmhILT2T4uFP-rit_BSes9xM,9189
|
10
|
+
analyser_hj3415/analysers/score.py,sha256=C_Xiqo44o2OAXHaHiHYLa60HwKwpUt_H18uO5Iff1TM,16308
|
11
|
+
analyser_hj3415-2.2.0.dist-info/entry_points.txt,sha256=dHaCM3eOAGONmxTWuRVqo9Zyq2C7J5TZmpH0PD6FW5k,103
|
12
|
+
analyser_hj3415-2.2.0.dist-info/LICENSE,sha256=QVKTp0dTnB5xG8RLgG17LwSWCKNEzYoVVM6KjoCPKc0,1079
|
13
|
+
analyser_hj3415-2.2.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
|
14
|
+
analyser_hj3415-2.2.0.dist-info/METADATA,sha256=OJhj-1acjb5Ht817i0tzqYdLUkA94NpGVZ-dclMstKo,6417
|
15
|
+
analyser_hj3415-2.2.0.dist-info/RECORD,,
|
analyser_hj3415/db/.DS_Store
DELETED
Binary file
|
analyser_hj3415/db/chk_db.py
DELETED
@@ -1,240 +0,0 @@
|
|
1
|
-
import time
|
2
|
-
import sys
|
3
|
-
from _datetime import datetime
|
4
|
-
from typing import Dict, List, Tuple, Callable
|
5
|
-
from multiprocessing import Process, Queue
|
6
|
-
from . import mongo
|
7
|
-
from utils_hj3415 import utils, noti
|
8
|
-
from scraper2_hj3415.krx import krx
|
9
|
-
from scraper2_hj3415.nfscrapy import run as nfsrun
|
10
|
-
from pymongo import MongoClient
|
11
|
-
from selenium.webdriver.chrome.webdriver import WebDriver
|
12
|
-
|
13
|
-
import logging
|
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.INFO)
|
20
|
-
|
21
|
-
|
22
|
-
"""
|
23
|
-
chk_integrity_corps 함수로 종목코드를 데이터베이스명으로 가지는 DB의 유효성을 검사한다.
|
24
|
-
"""
|
25
|
-
|
26
|
-
|
27
|
-
def test_corp_one(client1: MongoClient, code: str, driver: WebDriver = None, waiting_time: int = 10) -> Dict[str, list]:
|
28
|
-
"""
|
29
|
-
종목 하나의 컬렉션의 유효성을 검사하여 부족한 컬렉션을 딕셔너리로 만들어서 반환한다.
|
30
|
-
driver와 waiting_time은 본 함수에서 사용하지는 않으나 다른 함수와 인자를 맞추기위해 인자로 받아준다.
|
31
|
-
리턴값 - {'005930': ['c104','c103'...]}
|
32
|
-
"""
|
33
|
-
|
34
|
-
def is_same_count_of_docs(col_name1: str, col_name2: str) -> bool:
|
35
|
-
logger.debug(f"In is_same_count_of_docs {code}/ {col_name1}, {col_name2}")
|
36
|
-
corp_one.page = col_name1
|
37
|
-
count_doc1 = corp_one.count_docs_in_col()
|
38
|
-
corp_one.page = col_name2
|
39
|
-
count_doc2 = corp_one.count_docs_in_col()
|
40
|
-
if count_doc1 == count_doc2:
|
41
|
-
return True
|
42
|
-
else:
|
43
|
-
return False
|
44
|
-
|
45
|
-
proper_collections = {'c101', 'c104y', 'c104q', 'c106y', 'c106q', 'c103손익계산서q', 'c103재무상태표q',
|
46
|
-
'c103현금흐름표q', 'c103손익계산서y', 'c103재무상태표y', 'c103현금흐름표y'}
|
47
|
-
|
48
|
-
logger.debug('In test_corp_one function...')
|
49
|
-
return_dict = {}
|
50
|
-
|
51
|
-
logger.debug(f'return_dict is ... {return_dict}')
|
52
|
-
# 한 종목의 유효성 검사코드
|
53
|
-
corp_one = mongo.Corps(client1, code, 'c101')
|
54
|
-
|
55
|
-
# 차집합을 사용해서 db내에 없는 컬렉션이 있는지 확인한다.
|
56
|
-
set_deficient_collentions = set.difference(proper_collections, set(corp_one.list_collection_names()))
|
57
|
-
|
58
|
-
logger.debug(f'After take a set of difference : {set_deficient_collentions}')
|
59
|
-
|
60
|
-
return_dict[code] = set()
|
61
|
-
# 컬렉션이 아예 없는 것이 있다면 falied_codes에 추가한다.
|
62
|
-
if set_deficient_collentions != set():
|
63
|
-
for item in set_deficient_collentions:
|
64
|
-
# 컬렉션 이름 중 앞의 네글자만 추려서 추가해준다.(ex - c103손익계산서q -> c103)
|
65
|
-
return_dict[code].add(item[:4])
|
66
|
-
|
67
|
-
# 각 컬렉션의 q와 y의 도큐먼트 갯수를 비교하여 차이가 있는지 확인한다.
|
68
|
-
if not is_same_count_of_docs('c104y', 'c104q'):
|
69
|
-
return_dict[code].add('c104')
|
70
|
-
if not is_same_count_of_docs('c106y', 'c106q'):
|
71
|
-
return_dict[code].add('c106')
|
72
|
-
if not is_same_count_of_docs('c103손익계산서q', 'c103손익계산서y') \
|
73
|
-
or not is_same_count_of_docs('c103재무상태표q', 'c103재무상태표y') \
|
74
|
-
or not is_same_count_of_docs('c103현금흐름표y', 'c103현금흐름표q'):
|
75
|
-
return_dict[code].add('c103')
|
76
|
-
|
77
|
-
# 집합을 리스트로 바꿔서 다시 저장한다.
|
78
|
-
return_dict[code] = list(return_dict[code])
|
79
|
-
logger.debug(f'Going out test_corp_one : {return_dict}')
|
80
|
-
return return_dict
|
81
|
-
|
82
|
-
|
83
|
-
def test_corp_one_is_modified(client: MongoClient, code: str, driver: WebDriver, waiting_time: int) -> Dict[str, bool]:
|
84
|
-
"""
|
85
|
-
웹에서 스크랩한 c103손익계산서y와 데이터베이스에 있는 c103손익계산서y를 비교하여 다른지 확인하여 업데이트 유무를 반환한다.
|
86
|
-
리턴값 - (코드, bool-업데이트가필요한지)
|
87
|
-
"""
|
88
|
-
df_online = nfsrun.scrape_c103_first_page(driver, code, waiting_time=waiting_time)
|
89
|
-
df_mongo = mongo.C103(client, code=code, page='c103손익계산서y').load_df()
|
90
|
-
|
91
|
-
logger.debug(df_online)
|
92
|
-
logger.debug(df_mongo)
|
93
|
-
|
94
|
-
return_dict = {code: not df_online.equals(df_mongo)}
|
95
|
-
return return_dict
|
96
|
-
|
97
|
-
|
98
|
-
def working_with_parts(test_func: Callable[[MongoClient, str, WebDriver, int], dict], db_addr: str, divided_code_list: list, my_q: Queue, waiting_time: int):
|
99
|
-
# 각 코어별로 디비 클라이언트를 만들어야만 한다. 안그러면 에러발생
|
100
|
-
client = mongo.connect_mongo(db_addr)
|
101
|
-
driver = utils.get_driver()
|
102
|
-
t = len(divided_code_list)
|
103
|
-
|
104
|
-
failed_dict_part = {}
|
105
|
-
|
106
|
-
for i, code in enumerate(divided_code_list):
|
107
|
-
try:
|
108
|
-
failed_one_dict = test_func(client, code, driver, waiting_time)
|
109
|
-
except Exception as e:
|
110
|
-
print(f"{code} has a error : {e}", file=sys.stderr)
|
111
|
-
continue
|
112
|
-
print(f'{i + 1}/{t} {failed_one_dict}')
|
113
|
-
if failed_one_dict[code]:
|
114
|
-
# 빈리스트가 아니라면...또는 C103이 변화되었다면.. 큐에 추가한다.
|
115
|
-
failed_dict_part.update(failed_one_dict)
|
116
|
-
else:
|
117
|
-
# 큐에서 put은 함수 리턴처럼 함수에서 한번만 한다.
|
118
|
-
my_q.put(failed_dict_part)
|
119
|
-
driver.close()
|
120
|
-
|
121
|
-
|
122
|
-
# 멀티프로세싱을 사용하기 위해서 독립된 함수로 제작하였음(피클링이 가능해야함)
|
123
|
-
def chk_integrity_corps(client: MongoClient, code: str = 'all') -> Dict[str, list]:
|
124
|
-
"""
|
125
|
-
몽고 디비의 corps들의 integrity 검사후 이상이 있는 코드 리스트 반환
|
126
|
-
이상을 찾는 방법 - 각 컬렉션이 다 있는가. 각 컬렉션에서 연도와 분기의 도큐먼트 갯수가 같은가
|
127
|
-
return - {'코드': ['cxxx',...], '코드': ['cxxx',...]...}
|
128
|
-
"""
|
129
|
-
failed_codes = {}
|
130
|
-
codes_in_db = mongo.Corps.get_all_codes(client)
|
131
|
-
if code == 'all':
|
132
|
-
print('*' * 25, f"Check all Corp db integrity using multiprocess", '*' * 25)
|
133
|
-
print(f'Total {len(codes_in_db)} items..')
|
134
|
-
n, divided_list = utils.code_divider_by_cpu_core(codes_in_db)
|
135
|
-
|
136
|
-
addr = mongo.extract_addr_from_client(client)
|
137
|
-
|
138
|
-
start_time = time.time()
|
139
|
-
q = Queue()
|
140
|
-
ths = []
|
141
|
-
for i in range(n):
|
142
|
-
ths.append(Process(target=working_with_parts, args=(test_corp_one, addr, divided_list[i], q, 0)))
|
143
|
-
for i in range(n):
|
144
|
-
ths[i].start()
|
145
|
-
|
146
|
-
for i in range(n):
|
147
|
-
failed_codes.update(q.get())
|
148
|
-
|
149
|
-
for i in range(n):
|
150
|
-
ths[i].join()
|
151
|
-
|
152
|
-
logger.debug(f"failed_codes : {failed_codes}")
|
153
|
-
print(f'Total spent time : {round(time.time() - start_time, 2)} sec.')
|
154
|
-
else:
|
155
|
-
print('*' * 25, f"Check {code} db integrity", '*' * 25)
|
156
|
-
if code in codes_in_db:
|
157
|
-
result_dict = test_corp_one(client, code)
|
158
|
-
print(f'{code} : {result_dict[code]}')
|
159
|
-
if result_dict[code]: # 빈리스트가 아니라면...
|
160
|
-
failed_codes.update(result_dict)
|
161
|
-
|
162
|
-
else:
|
163
|
-
Exception(f'{code} is not in db..')
|
164
|
-
return failed_codes
|
165
|
-
|
166
|
-
|
167
|
-
def chk_modifying_corps(client, code: str = 'all', waiting_time: int = 60) -> Dict[str, bool]:
|
168
|
-
"""
|
169
|
-
각 종목의 웹과 DB의 C103손익계산서y를 비교하여 변화가 있어 refresh가 필요한지를 반환한다.
|
170
|
-
"""
|
171
|
-
failed_codes = {}
|
172
|
-
codes_in_db = mongo.Corps.get_all_codes(client)
|
173
|
-
if code == 'all':
|
174
|
-
print('*' * 25, f"Check all Corp db need for updating using multiprocess", '*' * 25)
|
175
|
-
print(f'Total {len(codes_in_db)} items..')
|
176
|
-
n, divided_list = utils.code_divider_by_cpu_core(codes_in_db)
|
177
|
-
|
178
|
-
addr = mongo.extract_addr_from_client(client)
|
179
|
-
|
180
|
-
start_time = time.time()
|
181
|
-
q = Queue()
|
182
|
-
ths = []
|
183
|
-
for i in range(n):
|
184
|
-
ths.append(Process(target=working_with_parts, args=(test_corp_one_is_modified, addr, divided_list[i], q, waiting_time)))
|
185
|
-
for i in range(n):
|
186
|
-
ths[i].start()
|
187
|
-
|
188
|
-
for i in range(n):
|
189
|
-
failed_codes.update(q.get())
|
190
|
-
|
191
|
-
for i in range(n):
|
192
|
-
ths[i].join()
|
193
|
-
|
194
|
-
logger.debug(f"failed_codes : {failed_codes}")
|
195
|
-
print(f'Total spent time : {round(time.time() - start_time, 2)} sec.')
|
196
|
-
else:
|
197
|
-
print('*' * 25, f"Check {code} db need for updating ", '*' * 25)
|
198
|
-
driver = utils.get_driver()
|
199
|
-
if code in codes_in_db:
|
200
|
-
result_dict = test_corp_one_is_modified(client, code, driver)
|
201
|
-
print(f'{code} : {result_dict[code]}')
|
202
|
-
if result_dict[code]:
|
203
|
-
failed_codes.update(result_dict)
|
204
|
-
|
205
|
-
else:
|
206
|
-
Exception(f'{code} is not in db..')
|
207
|
-
return failed_codes
|
208
|
-
|
209
|
-
|
210
|
-
def sync_mongo_with_krx(client):
|
211
|
-
print('*' * 20, 'Sync with krx and mongodb', '*' * 20)
|
212
|
-
all_codes_in_db = mongo.Corps.get_all_codes(client)
|
213
|
-
print('*' * 20, 'Refreshing krx.db...', '*' * 20)
|
214
|
-
krx.make_db()
|
215
|
-
print('*' * 80)
|
216
|
-
all_codes_in_krx = krx.get_codes()
|
217
|
-
print('\tThe number of codes in krx: ', len(all_codes_in_krx))
|
218
|
-
logger.debug(all_codes_in_krx)
|
219
|
-
try:
|
220
|
-
print('\tThe number of dbs in mongo: ', len(all_codes_in_db))
|
221
|
-
logger.debug(all_codes_in_db)
|
222
|
-
except TypeError:
|
223
|
-
err_msg = "Error while sync mongo data...it's possible mongo db doesn't set yet.."
|
224
|
-
logger.error(err_msg)
|
225
|
-
noti.telegram_to(botname='manager', text=err_msg)
|
226
|
-
return
|
227
|
-
del_targets = list(set(all_codes_in_db) - set(all_codes_in_krx))
|
228
|
-
add_targets = list(set(all_codes_in_krx) - set(all_codes_in_db))
|
229
|
-
print('\tDelete target: ', del_targets)
|
230
|
-
print('\tAdd target: ', add_targets)
|
231
|
-
|
232
|
-
for target in del_targets:
|
233
|
-
mongo.Corps.del_db(client, target)
|
234
|
-
|
235
|
-
if add_targets:
|
236
|
-
print(f'Starting.. c10346 scraper.. items : {len(add_targets)}')
|
237
|
-
addr = mongo.extract_addr_from_client(client)
|
238
|
-
nfsrun.c103(add_targets, addr)
|
239
|
-
nfsrun.c104(add_targets, addr)
|
240
|
-
nfsrun.c106(add_targets, addr)
|