Showing
2 changed files
with
586 additions
and
1 deletions
1 | +from collections import OrderedDict | ||
2 | +from sqlalchemy import Integer, Text | ||
3 | +import numpy | ||
4 | +import pathlib | ||
5 | +import os | ||
6 | +import time | ||
7 | +from PyQt5.QtWidgets import * | ||
8 | +from pandas import DataFrame | ||
9 | + | ||
10 | +from open_api import * | ||
11 | +from daily_buy_list import * | ||
12 | + | ||
13 | +# open_api를 이용하여 데이터베이스에 정보를 저장하는 클래스 | ||
14 | +class collector_api(): | ||
15 | + def __init__(self): | ||
16 | + self.open_api = open_api() | ||
17 | + self.engine_bot = self.open_api.engine_bot | ||
18 | + self.variable_setting() | ||
19 | + | ||
20 | + # 변수설정 | ||
21 | + def variable_setting(self): | ||
22 | + self.open_api.py_gubun = "collector" # 용도를 저장하는 변수. collector : 데이터 저장 / trader : 종목 거래 | ||
23 | + self.dc = daily_crawler(self.open_api.cf.real_db_name, self.open_api.cf.real_daily_craw_db_name, | ||
24 | + self.open_api.cf.real_daily_buy_list_db_name) | ||
25 | + self.dbl = daily_buy_list() | ||
26 | + | ||
27 | + # 콜렉팅을 실행하는 함수 | ||
28 | + def code_update_check(self): | ||
29 | + logger.debug("code_update_check function") | ||
30 | + query = "select jango_data_db_check, possessed_item, today_profit, final_chegyul_check, " \ | ||
31 | + "db_to_buy_list,today_buy_list, daily_crawler , min_crawler, daily_buy_list from setting_data limit 1" | ||
32 | + | ||
33 | + rows = self.engine_bot.execute(query).fetchall() | ||
34 | + | ||
35 | + # 잔고/보유종목 업데이트 확인 | ||
36 | + if rows[0][0] != self.open_api.today or rows[0][1] != self.open_api.today: | ||
37 | + self.py_check_balance() | ||
38 | + self.open_api.set_invest_unit() | ||
39 | + | ||
40 | + # possessed_item(현재 보유종목) 테이블 업데이트 | ||
41 | + if rows[0][1] != self.open_api.today: | ||
42 | + self.open_api.db_to_possesed_item() | ||
43 | + self.open_api.setting_data_possesed_item() | ||
44 | + | ||
45 | + # 당일 종목별 실현 손익 내역 테이블 업데이트 | ||
46 | + if rows[0][2] != self.open_api.today: | ||
47 | + self.db_to_today_profit_list() | ||
48 | + | ||
49 | + # daily_craw 데이터베이스 업데이트 | ||
50 | + if rows[0][6] != self.open_api.today: | ||
51 | + self.daily_crawler_check() | ||
52 | + | ||
53 | + # daily_buy_list 데이터베이스 업데이트 | ||
54 | + if rows[0][8] != self.open_api.today: | ||
55 | + self.daily_buy_list_check() | ||
56 | + | ||
57 | + # 매수/매도 후 daily_buy_list 데이터베이스 업데이트 | ||
58 | + if rows[0][3] != self.open_api.today: | ||
59 | + self.open_api.chegyul_check() # 매수 후 all_stocks에 저장되지 않은 종목 처리 | ||
60 | + self.open_api.final_chegyul_check() # # 매도 후 all_stocks에 sell_date가 업데이트 되지 않은 항목 처리 | ||
61 | + | ||
62 | + # 다음날 매수 종목 테이블(realtime_daily_buy_list) 업데이트 | ||
63 | + if rows[0][5] != self.open_api.today: | ||
64 | + self.realtime_daily_buy_list_check() | ||
65 | + | ||
66 | + # min_craw db (분별 데이터) 업데이트 | ||
67 | + if rows[0][7] != self.open_api.today: | ||
68 | + self.min_crawler_check() | ||
69 | + | ||
70 | + logger.debug("collecting 작업을 모두 정상적으로 마쳤습니다.") | ||
71 | + | ||
72 | + # cmd 콘솔창 종료 | ||
73 | + os.system("@taskkill /f /im cmd.exe") | ||
74 | + | ||
75 | + # 매수 종목 설정 함수 | ||
76 | + def realtime_daily_buy_list_check(self): | ||
77 | + # daily_buy_list 데이터베이스에 오늘 날짜의 테이블이 존재하는 경우, realtime_daily_buy_list 테이블 생성 | ||
78 | + if self.open_api.sf.is_date_exist(self.open_api.today): | ||
79 | + self.open_api.sf.get_date_for_simul() | ||
80 | + self.open_api.sf.db_to_realtime_daily_buy_list(self.open_api.today, self.open_api.today, len(self.open_api.sf.date_rows)) | ||
81 | + | ||
82 | + # all_stocks 테이블을 오늘 일자 데이터로 업데이트 한다. | ||
83 | + self.open_api.sf.update_all_db_by_date(self.open_api.today) | ||
84 | + self.open_api.rate_check() | ||
85 | + # realtime_daily_buy_list(매수 리스트) 테이블 세팅을 완료 후, setting_data의 today_buy_list에 오늘 날짜를 저장 | ||
86 | + query = "UPDATE setting_data SET today_buy_list='%s' limit 1" | ||
87 | + self.engine_bot.execute(query % (self.open_api.today)) | ||
88 | + | ||
89 | + else: | ||
90 | + logger.debug( | ||
91 | + """daily_buy_list DB에 {} 테이블이 없습니다. realtime_daily_buy_list 테이블을 생성 할 수 없습니다. | ||
92 | + 아래 내역을 확인하세요. | ||
93 | + 1. 장이 열리지 않은 날 혹은 15시 30분 ~ 23시 59분 사이에 콜렉터를 돌리지 않은 경우 | ||
94 | + 2. 콜렉터를 오늘 날짜 까지 돌리지 않아 daily_buy_list의 오늘 날짜 테이블이 없는 경우 | ||
95 | + """.format(self.open_api.today)) | ||
96 | + | ||
97 | + # daily_buy_list 데이터베이스에 테이블이 존재하는지 확인하는 함수 | ||
98 | + def is_table_exist_daily_buy_list(self, date): | ||
99 | + query = "select 1 from information_schema.tables where table_schema ='daily_buy_list' and table_name = '%s'" | ||
100 | + rows = self.open_api.engine_daily_buy_list.execute(query % (date)).fetchall() | ||
101 | + | ||
102 | + if len(rows) == 1: | ||
103 | + return True | ||
104 | + elif len(rows) == 0: | ||
105 | + return False | ||
106 | + | ||
107 | + # min_craw 데이터베이스에 테이블이 존재하는지 확인하는 함수 | ||
108 | + def is_table_exist(self, db_name, table_name): | ||
109 | + query = "select 1 from information_schema.tables where table_schema ='{}' and table_name = '{}'" | ||
110 | + rows = self.open_api.engine_craw.execute(query.format(db_name, table_name)).fetchall() | ||
111 | + if len(rows) == 1: | ||
112 | + return True | ||
113 | + elif len(rows) == 0: | ||
114 | + return False | ||
115 | + | ||
116 | + # daily_buy_list 테이블 생성 및 데이터 저장하는 함수 | ||
117 | + def daily_buy_list_check(self): | ||
118 | + self.dbl.daily_buy_list() | ||
119 | + | ||
120 | + query = "UPDATE setting_data SET daily_buy_list='%s' limit 1" | ||
121 | + self.engine_bot.execute(query % (self.open_api.today)) | ||
122 | + | ||
123 | + # min_craw 데이터베이스 생성 함수 | ||
124 | + def db_to_min_craw(self): | ||
125 | + query = "select code,code_name,check_min_crawler from stock_item_all" | ||
126 | + target_code = self.open_api.engine_daily_buy_list.execute(query).fetchall() | ||
127 | + num = len(target_code) | ||
128 | + | ||
129 | + query = "UPDATE stock_item_all SET check_min_crawler='%s' WHERE code='%s'" | ||
130 | + | ||
131 | + for i in range(num): | ||
132 | + # check_item이 0이 아니면 다음 항목 처리 | ||
133 | + if int(target_code[i][2]) != 0: | ||
134 | + continue | ||
135 | + | ||
136 | + code = target_code[i][0] | ||
137 | + code_name = target_code[i][1] | ||
138 | + | ||
139 | + logger.debug("++++++++++++++" + str(code_name) + "++++++++++++++++++++" + str(i + 1) + '/' + str(num)) | ||
140 | + | ||
141 | + check_item_gubun = self.set_min_crawler_table(code, code_name) | ||
142 | + | ||
143 | + self.open_api.engine_daily_buy_list.execute(query % (check_item_gubun, code)) | ||
144 | + | ||
145 | + # 당일 daily_craw 데이터베이스의 업데이트 내역을 확인하고, 업데이트를 실행하는 함수 | ||
146 | + def db_to_daily_craw(self): | ||
147 | + query = "select code,code_name,check_daily_crawler from stock_item_all" | ||
148 | + | ||
149 | + target_code = self.open_api.engine_daily_buy_list.execute(query).fetchall() | ||
150 | + num = len(target_code) | ||
151 | + query = "UPDATE stock_item_all SET check_daily_crawler='%s' WHERE code='%s'" | ||
152 | + | ||
153 | + # check_daily_crawler : daily_craw 데이터베이스를 업데이트 했는지 확인하는 변수 | ||
154 | + # 1: 당일 업데이트 완료 / 3 : 과거에 업데이트 완료 / 0 : 업데이트 전 / 4 : daily_buy_list에 내용 변동을 업데이트 필요 | ||
155 | + # check_daily_crawler이 1,3이 아닌 경우 업데이트 실행 | ||
156 | + for i in range(num): | ||
157 | + if int(target_code[i][2]) in (1, 3): | ||
158 | + continue | ||
159 | + | ||
160 | + code = target_code[i][0] | ||
161 | + code_name = target_code[i][1] | ||
162 | + | ||
163 | + logger.debug("++++++++++++++" + str(code_name) + "++++++++++++++++++++" + str(i + 1) + '/' + str(num)) | ||
164 | + | ||
165 | + check_item_gubun = self.set_daily_crawler_table(code, code_name) | ||
166 | + | ||
167 | + self.open_api.engine_daily_buy_list.execute(query % (check_item_gubun, code)) | ||
168 | + | ||
169 | + # min_crawler 데이터베이스에 콜렉팅을 완료했는지 확인하는 함수 | ||
170 | + def min_crawler_check(self): | ||
171 | + self.db_to_min_craw() | ||
172 | + | ||
173 | + query = "UPDATE setting_data SET min_crawler='%s' limit 1" | ||
174 | + self.engine_bot.execute(query % (self.open_api.today)) | ||
175 | + | ||
176 | + # daily_crawler 데이터베이스에 콜렉팅을 완료했는지 확인하는 함수 | ||
177 | + def daily_crawler_check(self): | ||
178 | + self.db_to_daily_craw() | ||
179 | + logger.debug("daily_crawler success !!!") | ||
180 | + | ||
181 | + sql = "UPDATE setting_data SET daily_crawler='%s' limit 1" | ||
182 | + self.engine_JB.execute(sql % (self.open_api.today)) | ||
183 | + | ||
184 | + # 틱(1분 별) 데이터를 가져오는 함수 | ||
185 | + def set_min_crawler_table(self, code, code_name): | ||
186 | + df = self.open_api.get_total_data_min(code, code_name, self.open_api.today) | ||
187 | + | ||
188 | + df_temp = DataFrame(df, | ||
189 | + columns=['date', 'check_item', 'code', 'code_name', 'd1_diff_rate', | ||
190 | + 'close', 'open', 'high','low','volume', 'sum_volume', | ||
191 | + 'clo5', 'clo10', 'clo20', 'clo60','clo120', | ||
192 | + "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate", "clo60_diff_rate", | ||
193 | + "clo120_diff_rate", | ||
194 | + 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60', 'yes_clo120', | ||
195 | + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120' | ||
196 | + ]) | ||
197 | + | ||
198 | + df_temp = df_temp.sort_values(by=['date'], ascending=True) | ||
199 | + | ||
200 | + df_temp['code'] = code | ||
201 | + df_temp['code_name'] = code_name | ||
202 | + d1_diff_rate = round((df_temp['close'] - df_temp['close'].shift(1)) / df_temp['close'].shift(1) * 100, 2) | ||
203 | + df_temp['d1_diff_rate'] = d1_diff_rate.replace(numpy.inf, numpy.nan) | ||
204 | + | ||
205 | + clo5 = df_temp['close'].rolling(window=5).mean() | ||
206 | + clo10 = df_temp['close'].rolling(window=10).mean() | ||
207 | + clo20 = df_temp['close'].rolling(window=20).mean() | ||
208 | + clo60 = df_temp['close'].rolling(window=60).mean() | ||
209 | + clo120 = df_temp['close'].rolling(window=120).mean() | ||
210 | + df_temp['clo5'] = round(clo5, 2) | ||
211 | + df_temp['clo10'] = round(clo10, 2) | ||
212 | + df_temp['clo20'] = round(clo20, 2) | ||
213 | + df_temp['clo60'] = round(clo60, 2) | ||
214 | + df_temp['clo120'] = round(clo120, 2) | ||
215 | + | ||
216 | + df_temp['clo5_diff_rate'] = round((df_temp['close'] - clo5) / clo5 * 100, 2) | ||
217 | + df_temp['clo10_diff_rate'] = round((df_temp['close'] - clo10) / clo10 * 100, 2) | ||
218 | + df_temp['clo20_diff_rate'] = round((df_temp['close'] - clo20) / clo20 * 100, 2) | ||
219 | + df_temp['clo60_diff_rate'] = round((df_temp['close'] - clo60) / clo60 * 100, 2) | ||
220 | + df_temp['clo120_diff_rate'] = round((df_temp['close'] - clo120) / clo120 * 100, 2) | ||
221 | + | ||
222 | + df_temp['yes_clo5'] = df_temp['clo5'].shift(1) | ||
223 | + df_temp['yes_clo10'] = df_temp['clo10'].shift(1) | ||
224 | + df_temp['yes_clo20'] = df_temp['clo20'].shift(1) | ||
225 | + df_temp['yes_clo60'] = df_temp['clo60'].shift(1) | ||
226 | + df_temp['yes_clo120'] = df_temp['clo120'].shift(1) | ||
227 | + | ||
228 | + df_temp['vol5'] = df_temp['volume'].rolling(window=5).mean() | ||
229 | + df_temp['vol10'] = df_temp['volume'].rolling(window=10).mean() | ||
230 | + df_temp['vol20'] = df_temp['volume'].rolling(window=20).mean() | ||
231 | + df_temp['vol60'] = df_temp['volume'].rolling(window=60).mean() | ||
232 | + df_temp['vol120'] = df_temp['volume'].rolling(window=120).mean() | ||
233 | + | ||
234 | + # 분별 테이블이 존재한다면, 가장 최근의 분 데이터 이후의 값을 저장 | ||
235 | + if self.open_api.craw_table_exist: | ||
236 | + df_temp = df_temp[df_temp.date > self.open_api.craw_db_last_min] | ||
237 | + | ||
238 | + # 추가할 내역이 없다면, check_item_gubun=3 | ||
239 | + if len(df_temp) == 0: | ||
240 | + time.sleep(0.03) | ||
241 | + check_item_gubun = 3 | ||
242 | + return check_item_gubun | ||
243 | + | ||
244 | + df_temp[['close', 'open', 'high', 'low', 'volume', 'sum_volume', 'clo5', 'clo10', 'clo20', 'clo60','clo120', | ||
245 | + 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120', | ||
246 | + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120']] = \ | ||
247 | + df_temp[ | ||
248 | + ['close', 'open', 'high', 'low', 'volume', 'sum_volume', 'clo5', 'clo10', 'clo20', 'clo60', 'clo120', | ||
249 | + 'yes_clo5', 'yes_clo10', 'yes_clo20','yes_clo60', 'yes_clo120', | ||
250 | + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120']].fillna(0).astype(int) | ||
251 | + | ||
252 | + temp_date = self.open_api.craw_db_last_min | ||
253 | + sum_volume = self.open_api.craw_db_last_min_sum_volume | ||
254 | + | ||
255 | + for i in range(len(df_temp),-1,-1): | ||
256 | + try: | ||
257 | + temp_index = i | ||
258 | + | ||
259 | + # 데이터가 하루 이상 차이날 경우, sum_volume 초기화 | ||
260 | + if ((int(df_temp.loc[temp_index, 'date']) - int(temp_date)) > 9000): | ||
261 | + sum_volume = 0 | ||
262 | + | ||
263 | + temp_date = df_temp.loc[temp_index, 'date'] | ||
264 | + # 분별로 sum_volume값 누적 저장 | ||
265 | + sum_volume += df_temp.loc[temp_index, 'volume'] | ||
266 | + df_temp.loc[temp_index, 'sum_volume'] = sum_volume | ||
267 | + | ||
268 | + except Exception as e: | ||
269 | + logger.critical(e) | ||
270 | + | ||
271 | + df_temp.to_sql(name=code_name, con=self.open_api.engine_craw, if_exists='append') | ||
272 | + # 콜렉팅하다가 max_api_call 횟수까지 가게 된 경우 | ||
273 | + # 이후 콜렉팅 하지 못한 정보를 가져오기 위해 check_item_gubun=0 | ||
274 | + if self.open_api.rq_count == cf.max_api_call - 1: | ||
275 | + check_item_gubun = 0 | ||
276 | + # 정상완료한 경우 check_item_gubun=1 | ||
277 | + else: | ||
278 | + check_item_gubun = 1 | ||
279 | + return check_item_gubun | ||
280 | + | ||
281 | + # daily_crawler(종목별 일일 데이터) 테이블 생성 및 내역을 추가하는 함수 | ||
282 | + # daily_crawler 테이블 업데이트 후, daily_buy_list(일별 종목 데이터) 테이블 생성 및 내역 추가 | ||
283 | + def set_daily_crawler_table(self, code, code_name): | ||
284 | + df = self.open_api.get_total_data(code, code_name, self.open_api.today) | ||
285 | + oldest_row = df.iloc[-1] # 가장 최신 데이터 | ||
286 | + check_row = None | ||
287 | + | ||
288 | + check_dc_query = "UPDATE daily_buy_list.stock_item_all SET check_daily_crawler = '4' WHERE code = '{}'" | ||
289 | + | ||
290 | + # 특정 종목명(code_name)의 테이블이 존재하는 경우 | ||
291 | + if self.engine_bot.dialect.has_table(self.open_api.engine_daily_craw, code_name): | ||
292 | + query=f"select * from '{code_name}' where date='{oldest_row['date']}' limit 1" | ||
293 | + check_row = self.open_api.engine_daily_craw.execute(query).fetchall() | ||
294 | + # 종목명 테이블이 존재하지 않는 경우, 종목 리스트(stock_item_all) 테이블에 check_daily_crawler=4 업데이트 | ||
295 | + else: | ||
296 | + self.engine_bot.execute(check_dc_query.format(code)) | ||
297 | + | ||
298 | + # 종목 테이블에 저장된 가장 최신의 데이터가 실제 가장 최신 데이터와 같지 않다면 다시 테이블 삭제 후 다시 생성 | ||
299 | + if check_row and check_row[0]['close'] != oldest_row['close']: | ||
300 | + # 테이블 삭제 | ||
301 | + logger.info('daily_craw와 min_craw 삭제 중..') | ||
302 | + commands = [ | ||
303 | + f"DROP TABLE IF EXISTS daily_craw.'{code_name}'", | ||
304 | + f"DROP TABLE IF EXISTS min_craw.'{code_name}" | ||
305 | + ] | ||
306 | + | ||
307 | + for com in commands: | ||
308 | + self.open_api.engine_daily_buy_list.execute(com) | ||
309 | + logger.info('삭제 완료') | ||
310 | + | ||
311 | + # 테이블 생성 | ||
312 | + df = self.open_api.get_total_data(code, code_name, self.open_api.today) | ||
313 | + self.engine_bot.execute(check_dc_query.format(code)) | ||
314 | + | ||
315 | + query=f"select check_daily_crawler from daily_buy_list.stock_item_all where code='{code}'" | ||
316 | + check_daily_crawler = self.engine_bot.execute(query).fetchall()[0].check_daily_crawler | ||
317 | + | ||
318 | + df_temp = DataFrame(df, | ||
319 | + columns=['date', 'check_item', 'code', 'code_name', 'd1_diff_rate', | ||
320 | + 'close', 'open', 'high','low','volume', | ||
321 | + 'clo5', 'clo10', 'clo20', 'clo60', 'clo120', | ||
322 | + "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate", "clo60_diff_rate", | ||
323 | + "clo120_diff_rate", | ||
324 | + 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60', 'yes_clo120', | ||
325 | + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120', 'vol80' | ||
326 | + ]) | ||
327 | + | ||
328 | + df_temp = df_temp.sort_values(by=['date'], ascending=True) | ||
329 | + | ||
330 | + df_temp['code'] = code | ||
331 | + df_temp['code_name'] = code_name | ||
332 | + df_temp['d1_diff_rate'] = round( | ||
333 | + (df_temp['close'] - df_temp['close'].shift(1)) / df_temp['close'].shift(1) * 100, 2) | ||
334 | + | ||
335 | + clo5 = df_temp['close'].rolling(window=5).mean() | ||
336 | + clo10 = df_temp['close'].rolling(window=10).mean() | ||
337 | + clo20 = df_temp['close'].rolling(window=20).mean() | ||
338 | + clo60 = df_temp['close'].rolling(window=60).mean() | ||
339 | + clo120 = df_temp['close'].rolling(window=120).mean() | ||
340 | + df_temp['clo5'] = clo5 | ||
341 | + df_temp['clo10'] = clo10 | ||
342 | + df_temp['clo20'] = clo20 | ||
343 | + df_temp['clo60'] = clo60 | ||
344 | + df_temp['clo120'] = clo120 | ||
345 | + | ||
346 | + df_temp['clo5_diff_rate'] = round((df_temp['close'] - clo5) / clo5 * 100, 2) | ||
347 | + df_temp['clo10_diff_rate'] = round((df_temp['close'] - clo10) / clo10 * 100, 2) | ||
348 | + df_temp['clo20_diff_rate'] = round((df_temp['close'] - clo20) / clo20 * 100, 2) | ||
349 | + df_temp['clo60_diff_rate'] = round((df_temp['close'] - clo60) / clo60 * 100, 2) | ||
350 | + df_temp['clo120_diff_rate'] = round((df_temp['close'] - clo120) / clo120 * 100, 2) | ||
351 | + | ||
352 | + df_temp['yes_clo5'] = df_temp['clo5'].shift(1) | ||
353 | + df_temp['yes_clo10'] = df_temp['clo10'].shift(1) | ||
354 | + df_temp['yes_clo20'] = df_temp['clo20'].shift(1) | ||
355 | + df_temp['yes_clo60'] = df_temp['clo60'].shift(1) | ||
356 | + df_temp['yes_clo120'] = df_temp['clo120'].shift(1) | ||
357 | + | ||
358 | + df_temp['vol5'] = df_temp['volume'].rolling(window=5).mean() | ||
359 | + df_temp['vol10'] = df_temp['volume'].rolling(window=10).mean() | ||
360 | + df_temp['vol20'] = df_temp['volume'].rolling(window=20).mean() | ||
361 | + df_temp['vol60'] = df_temp['volume'].rolling(window=60).mean() | ||
362 | + df_temp['vol120'] = df_temp['volume'].rolling(window=120).mean() | ||
363 | + | ||
364 | + # daily_craw테이블이 존재할 경우, 저장되어있는 날짜 이후의 값을 저장 | ||
365 | + if self.engine_bot.dialect.has_table(self.open_api.engine_daily_craw, code_name): | ||
366 | + df_temp = df_temp[df_temp.date > self.open_api.get_daily_craw_db_last_date(code_name)] | ||
367 | + | ||
368 | + # 데이터가 없거나 이미 데이터 콜렉팅을 완료한 경우, check_item_gubun=3으로 설정 | ||
369 | + if len(df_temp) == 0 and check_daily_crawler != '4': | ||
370 | + time.sleep(0.03) | ||
371 | + check_item_gubun = 3 | ||
372 | + return check_item_gubun | ||
373 | + | ||
374 | + df_temp[['close', 'open', 'high', 'low', 'volume', 'clo5', 'clo10', 'clo20', 'clo60','clo120', | ||
375 | + 'yes_clo5', 'yes_clo10', 'yes_clo20','yes_clo60', 'yes_clo80','yes_clo120', | ||
376 | + 'vol5', 'vol10', 'vol20', 'vol40', 'vol60', 'vol80', 'vol100', 'vol120']] = \ | ||
377 | + df_temp[ | ||
378 | + ['close', 'open', 'high', 'low', 'volume', 'clo5', 'clo10', 'clo20','clo60','clo120', | ||
379 | + 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120', | ||
380 | + 'vol5', 'vol10', 'vol20', 'vol40', 'vol60', 'vol80', 'vol100', 'vol120']].fillna(0).astype(int) | ||
381 | + | ||
382 | + df_temp.to_sql(name=code_name, con=self.open_api.engine_daily_craw, if_exists='append') | ||
383 | + | ||
384 | + # check_daily_crawler 가 4 인 경우는 액면분할, 증자 등으로 인해 daily_buy_list 업데이트를 해야하는 경우 | ||
385 | + # 업데이트 완료 후 check_item_gubun=1 | ||
386 | + if check_daily_crawler == '4': | ||
387 | + logger.info(f'daily_craw.{code_name} 업데이트 완료 {code}') | ||
388 | + logger.info('daily_buy_list 업데이트 중..') | ||
389 | + | ||
390 | + query="SELECT table_name as tname FROM information_schema.tables " \ | ||
391 | + "WHERE table_schema ='daily_buy_list' AND table_name REGEXP '[0-9]{8}" | ||
392 | + dbl_dates = self.open_api.engine_daily_buy_list.execute(query).fetchall() | ||
393 | + | ||
394 | + for row in dbl_dates: | ||
395 | + logger.info(f'{code} {code_name} - daily_buy_list.`{row.tname}` 업데이트') | ||
396 | + try: | ||
397 | + new_data = df_temp[df_temp['date'] == row.tname] | ||
398 | + except IndexError: | ||
399 | + continue | ||
400 | + query=f"delete from '{row.tname}' where code={code}" | ||
401 | + self.open_api.engine_daily_buy_list.execute(query) | ||
402 | + new_data.to_sql(name=row.tname, con=self.open_api.engine_daily_buy_list, if_exists='append') | ||
403 | + | ||
404 | + logger.info('daily_buy_list 업데이트 완료') | ||
405 | + | ||
406 | + check_item_gubun = 1 | ||
407 | + return check_item_gubun | ||
408 | + | ||
409 | + # today_profit_list 테이블 생성 및 내역 추가 함수 | ||
410 | + def db_to_today_profit_list(self): | ||
411 | + self.open_api.reset_opt10073_output() | ||
412 | + | ||
413 | + self.open_api.set_input_value("계좌번호", self.open_api.account_number) | ||
414 | + self.open_api.set_input_value("시작일자", self.open_api.today) | ||
415 | + self.open_api.set_input_value("종료일자", self.open_api.today) | ||
416 | + | ||
417 | + self.open_api.comm_rq_data("opt10073_req", "opt10073", 0, "0328") | ||
418 | + | ||
419 | + while self.open_api.remained_data: | ||
420 | + self.open_api.set_input_value("계좌번호", self.open_api.account_number) | ||
421 | + self.open_api.comm_rq_data("opt10073_req", "opt10073", 2, "0328") | ||
422 | + | ||
423 | + today_profit_item_temp = {'date': [], 'code': [], 'code_name': [], 'amount': [], 'today_profit': [], | ||
424 | + 'earning_rate': []} | ||
425 | + | ||
426 | + today_profit_item = DataFrame(today_profit_item_temp, | ||
427 | + columns=['date', 'code', 'code_name', 'amount', 'today_profit', | ||
428 | + 'earning_rate']) | ||
429 | + | ||
430 | + item_count = len(self.open_api.opt10073_output['multi']) | ||
431 | + for i in range(item_count): | ||
432 | + row = self.open_api.opt10073_output['multi'][i] | ||
433 | + today_profit_item.loc[i, 'date'] = row[0] # 날짜 | ||
434 | + today_profit_item.loc[i, 'code'] = row[1] # 종목코드 | ||
435 | + today_profit_item.loc[i, 'code_name'] = row[2] # 종목명 | ||
436 | + today_profit_item.loc[i, 'amount'] = int(row[3]) # 보유수량 | ||
437 | + today_profit_item.loc[i, 'today_profit'] = float(row[4]) # 당일실현손익 | ||
438 | + today_profit_item.loc[i, 'earning_rate'] = float(row[5]) # 수익률 | ||
439 | + | ||
440 | + if len(today_profit_item) > 0: | ||
441 | + today_profit_item.to_sql('today_profit_list', self.engine_bot, if_exists='append') | ||
442 | + query = "UPDATE setting_data SET today_profit='%s' limit 1" | ||
443 | + self.engine_bot.execute(query % (self.open_api.today)) | ||
444 | + | ||
445 | + # jango 테이블 생성 및 내역 추가 함수 | ||
446 | + def db_to_jango(self): | ||
447 | + self.total_invest = self.open_api.change_format( | ||
448 | + str(int(self.open_api.d2_deposit_before_format) + int(self.open_api.total_purchase_price))) | ||
449 | + jango_temp = {'id': [], 'date': [], 'total_asset': [], 'today_profit': [], 'total_profit': [], | ||
450 | + 'total_invest': [], 'd2_deposit': [], | ||
451 | + 'today_purchase': [], 'today_evaluation': [], | ||
452 | + 'today_invest': [], 'today_rate': [], | ||
453 | + 'estimate_asset': []} | ||
454 | + | ||
455 | + jango_col_list = ['date', | ||
456 | + 'today_earning_rate','total_evaluation', | ||
457 | + 'total_profit', 'total_invest', | ||
458 | + 'total_valuation','total_purchase','total_rate','today_profit','estimate_asset','d2_deposit', | ||
459 | + 'volume_limit','sell_point','invest_limit_rate', 'invest_unit','limit_money', | ||
460 | + 'total_profitcut','total_losscut','total_profitcut_count', 'total_losscut_count', | ||
461 | + 'today_buy_count','total_sell_count','total_possess_count'] | ||
462 | + | ||
463 | + jango = DataFrame(jango_temp, | ||
464 | + columns=jango_col_list, | ||
465 | + index=jango_temp['id']) | ||
466 | + | ||
467 | + jango.loc[0, 'date'] = self.open_api.today # 날짜 | ||
468 | + jango.loc[0, 'total_evaluation'] = self.open_api.change_total_eval_price # 총평가금액 | ||
469 | + jango.loc[0, 'total_profit'] = self.open_api.total_profit # 실현손익 | ||
470 | + jango.loc[0, 'total_invest'] = self.total_invest # 총투자금액 | ||
471 | + jango.loc[0, 'total_valuation'] = self.open_api.change_total_eval_profit_loss_price # 총평가손익금액 | ||
472 | + jango.loc[0, 'total_purchase'] = self.open_api.change_total_purchase_price # 총매입금액 | ||
473 | + | ||
474 | + jango.loc[0, 'total_rate'] = float(self.open_api.change_total_earning_rate) / self.open_api.mod_gubun # 총수익률 | ||
475 | + jango.loc[0, 'today_profit'] = self.open_api.today_profit # 당일매도손익 | ||
476 | + jango.loc[0, 'estimate_asset'] = self.open_api.change_estimated_deposit # 추정예탁자산 | ||
477 | + jango.loc[0, 'd2_deposit'] = self.open_api.d2_deposit # 예수금 | ||
478 | + jango.loc[0, 'volume_limit'] = self.open_api.sf.volume_limit | ||
479 | + | ||
480 | + jango.loc[0, 'sell_point'] = self.open_api.sf.sell_point # 매도기준수익률 | ||
481 | + jango.loc[0, 'invest_limit_rate'] = self.open_api.sf.invest_limit_rate # 매수기준수익률 | ||
482 | + jango.loc[0, 'invest_unit'] = self.open_api.invest_unit # 투자기준금액 | ||
483 | + jango.loc[0, 'limit_money'] = self.open_api.sf.limit_money # 잔고에 남겨둘 최소금액 | ||
484 | + | ||
485 | + # 당일 익절 금액(today_profitcut), 당일 손절 금액(today_losscut) | ||
486 | + if self.is_table_exist(self.open_api.db_name, "today_profit_list"): | ||
487 | + query = "select sum(today_profit) from today_profit_list where today_profit >='%s' and date = '%s'" | ||
488 | + rows = self.engine_bot.execute(query % (0, self.open_api.today)).fetchall() | ||
489 | + if rows[0][0] is not None: | ||
490 | + jango.loc[0, 'total_profitcut'] = int(rows[0][0]) | ||
491 | + else: | ||
492 | + jango.loc[0,'total_profitcut']=0 | ||
493 | + | ||
494 | + query = "select sum(today_profit) from today_profit_list where today_profit < '%s' and date = '%s'" | ||
495 | + rows = self.engine_bot.execute(query % (0, self.open_api.today)).fetchall() | ||
496 | + if rows[0][0] is not None: | ||
497 | + jango.loc[0, 'total_losscut'] = int(rows[0][0]) | ||
498 | + else: | ||
499 | + jango.loc[0, 'total_losscut'] = 0 | ||
500 | + | ||
501 | + # 총 익절 종목 수(total_profitcut_count) | ||
502 | + query = "select count(*) " \ | ||
503 | + "from (select code from all_stocks where sell_rate >='%s' and sell_date like '%s' group by code)" | ||
504 | + rows = self.engine_bot.execute(query % (0, self.open_api.today + "%%")).fetchall() | ||
505 | + jango.loc[0, 'total_profitcut_count'] = int(rows[0][0]) | ||
506 | + | ||
507 | + # 총 손절 종목 수(total_losscut_count) | ||
508 | + query = "select count(*) " \ | ||
509 | + "from (select code from all_stocks where sell_rate < '%s' and sell_date like '%s' group by code)" | ||
510 | + rows = self.engine_bot.execute(query % (0, self.open_api.today + "%%")).fetchall() | ||
511 | + jango.loc[0, 'total_losscut_count'] = int(rows[0][0]) | ||
512 | + | ||
513 | + # jango_data 테이블 생성 및 데이터 추가 | ||
514 | + jango.to_sql('jango_data', self.engine_bot, if_exists='append') | ||
515 | + | ||
516 | + query = "select date from jango_data" | ||
517 | + rows = self.engine_bot.execute(query).fetchall() | ||
518 | + | ||
519 | + for i in range(len(rows)): | ||
520 | + # 당일 수익률 (today_earning_rate) | ||
521 | + query = "update jango_data set " \ | ||
522 | + "today_earning_rate =round(today_profit / total_invest * '%s',2) WHERE date='%s'" | ||
523 | + self.engine_bot.execute(query % (100, rows[i][0])) | ||
524 | + | ||
525 | + # 당일 구매 종목 수 (today_buy_count) | ||
526 | + query = "UPDATE jango_data SET " \ | ||
527 | + "today_buy_count=" \ | ||
528 | + "(select count(*) from (select code from all_stocks where buy_date like '%s' group by code)) " \ | ||
529 | + "WHERE date='%s'" | ||
530 | + self.engine_bot.execute(query % (rows[i][0] + "%%", rows[i][0])) | ||
531 | + | ||
532 | + # 총 매수 종목 수 (total_sell_count) | ||
533 | + query = "UPDATE jango_data SET " \ | ||
534 | + "total_sell_count=" \ | ||
535 | + "(select count(*) from " \ | ||
536 | + "(select code from all_stocks a where sell_date!='0' group by code) temp)"\ | ||
537 | + "WHERE date='%s'" | ||
538 | + self.engine_bot.execute(query % (rows[i][0])) | ||
539 | + | ||
540 | + # 총 보유 종목 수 (total_possess_count) | ||
541 | + query = "UPDATE jango_data SET " \ | ||
542 | + "today_buy_total_possess_count=" \ | ||
543 | + "(select count(*) from (select code from all_stocks where sell_date = '0' group by code )) " \ | ||
544 | + "WHERE date='%s'" | ||
545 | + self.engine_bot.execute(query % (rows[i][0])) | ||
546 | + | ||
547 | + query = "UPDATE setting_data SET jango_data_db_check='%s' limit 1" | ||
548 | + self.engine_bot.execute(query % (self.open_api.today)) | ||
549 | + | ||
550 | + # 계좌정보 확인 함수 | ||
551 | + def py_check_balance(self): | ||
552 | + logger.debug("py_check_balance!!!") | ||
553 | + | ||
554 | + # 예수금상세현황 | ||
555 | + self.open_api.reset_opw00018_output() | ||
556 | + | ||
557 | + self.open_api.set_input_value("계좌번호", self.open_api.account_number) | ||
558 | + self.open_api.set_input_value("비밀번호입력매체구분", 00) | ||
559 | + self.open_api.set_input_value("조회구분", 1) | ||
560 | + self.open_api.comm_rq_data("opw00001_req", "opw00001", 0, "2000") | ||
561 | + | ||
562 | + # 계좌평가잔고내역 | ||
563 | + self.open_api.set_input_value("계좌번호", self.open_api.account_number) | ||
564 | + self.open_api.comm_rq_data("opw00018_req", "opw00018", 0, "2000") | ||
565 | + | ||
566 | + while self.open_api.remained_data: | ||
567 | + self.open_api.set_input_value("계좌번호", self.open_api.account_number) | ||
568 | + self.open_api.comm_rq_data("opw00018_req", "opw00018", 2, "2000") | ||
569 | + | ||
570 | + # 일자별실현손익 | ||
571 | + self.open_api.set_input_value("계좌번호", self.open_api.account_number) | ||
572 | + self.open_api.set_input_value("시작일자", "20170101") | ||
573 | + self.open_api.set_input_value("종료일자", self.open_api.today) | ||
574 | + | ||
575 | + self.open_api.comm_rq_data("opt10074_req", "opt10074", 0, "0329") | ||
576 | + while self.open_api.remained_data: | ||
577 | + self.open_api.set_input_value("계좌번호", self.open_api.account_number) | ||
578 | + self.open_api.set_input_value("시작일자", "20170101") | ||
579 | + self.open_api.set_input_value("종료일자", "20180930") | ||
580 | + | ||
581 | + # 구분 = 0:전체, 1:입출금, 2:입출고, 3:매매, 4:매수, 5:매도, 6:입금, 7:출금, A:예탁담보대출입금, F:환전 | ||
582 | + self.open_api.set_input_value("구분", "0") | ||
583 | + self.open_api.comm_rq_data("opt10074_req", "opt10074", 2, "0329") | ||
584 | + | ||
585 | + self.db_to_jango() | ... | ... |
... | @@ -41,7 +41,7 @@ def setup_sql_mod(dbapi_connection): | ... | @@ -41,7 +41,7 @@ def setup_sql_mod(dbapi_connection): |
41 | event.listen(Pool,'connect',setup_sql_mod) | 41 | event.listen(Pool,'connect',setup_sql_mod) |
42 | event.listen(Pool,'first_connect',setup_sql_mod) | 42 | event.listen(Pool,'first_connect',setup_sql_mod) |
43 | 43 | ||
44 | -class Open_Api(QAxWidget): | 44 | +class open_api(QAxWidget): |
45 | def __init__(self): | 45 | def __init__(self): |
46 | super().__init__() | 46 | super().__init__() |
47 | 47 | ... | ... |
-
Please register or login to post a comment