이하영

딥러닝 알고리즘

...@@ -15,6 +15,7 @@ from library.open_api import setup_sql_mod ...@@ -15,6 +15,7 @@ from library.open_api import setup_sql_mod
15 listen(Pool,'connect',setup_sql_mod) 15 listen(Pool,'connect',setup_sql_mod)
16 listen(Pool,'first_connect',setup_sql_mod) 16 listen(Pool,'first_connect',setup_sql_mod)
17 17
18 +
18 def filter_by_ai(db_name,simul_num): 19 def filter_by_ai(db_name,simul_num):
19 from library.simulator_api import simulator_api 20 from library.simulator_api import simulator_api
20 sf=simulator_api(simul_num,'real',db_name) 21 sf=simulator_api(simul_num,'real',db_name)
...@@ -22,3 +23,119 @@ def filter_by_ai(db_name,simul_num): ...@@ -22,3 +23,119 @@ def filter_by_ai(db_name,simul_num):
22 ai_filter(sf.ai_num,sf.engine_simul) 23 ai_filter(sf.ai_num,sf.engine_simul)
23 except AttributeError: 24 except AttributeError:
24 sys.exit(1) 25 sys.exit(1)
26 +
27 +
28 +def lstm_algorithm(dataset,ai_setting):
29 + shuffled_data=load_data(df=dataset.copy(),n_steps=ai_setting['n_steps'],test_size=ai_setting['test_size'])
30 + model=create_model(n_steps=ai_setting['n_steps'],loss=ai_setting['loss'],units=ai_setting['units'],
31 + n_layers=ai_setting['n_layers'],dropout=ai_setting['dropout'])
32 + early_stopping=EarlyStopping(monitor='val_loss',patience=50)
33 + model.fit(shuffled_data["X_train"],shuffled_data['y_train'],
34 + batch_size=ai_setting['batch_size'],
35 + epochs=ai_setting['epochs'],
36 + validation_data=(shuffled_data['X_test'],shuffled_data['y_test']),
37 + callbacks=[early_stopping],
38 + verbose=1)
39 + scaled_data=load_data(df=dataset.copy(),n_steps=ai_setting['n_steps'],test_size=ai_setting['test_size'],
40 + shuffle=False)
41 + mse=evaluate(scaled_data,model)
42 +
43 + future_price=predict(scaled_data,model,n_steps=ai_setting['n_steps'])
44 + predicted_y=model.predict(scaled_data['X_test'])
45 + real_y=np.squeeze(scaled_data['column_scaler']['close'].inverse_transform(predicted_y))
46 +
47 + if ai_setting['is_used_predicted_close']:
48 + close=real_y[-1]
49 + else:
50 + close=dataset.iloc[-1]['close']
51 +
52 + ratio=(future_price-close)/close*100
53 +
54 + msg = f"After {ai_setting['lookup_step']}: {int(close)} -> {int(future_price)}"
55 +
56 + if ratio > 0: # lookup_step(분, 일) 후 상승 예상일 경우 출력 메시지
57 + msg += f' {ratio:.2f}% ⯅ '
58 + elif ratio < 0: # lookup_step(분, 일) 후 하락 예상일 경우 출력 메시지
59 + msg += f' {ratio:.2f}% ⯆ '
60 + print(msg, end=' ')
61 +
62 + return ai_setting['ratio_cut']
63 +
64 +
65 +def create_training_engine(db_name):
66 + return pymysql.connect(
67 + host=cf.db_ip,
68 + port=int(cf.db_port),
69 + user=cf.db_id,
70 + password=cf.db_pw,
71 + db=db_name,
72 + charset='utf8mb4',
73 + cursorclass=pymysql.cursors.DictCursor
74 + )
75 +
76 +
77 +def ai_filter(ai_filter_num,engine,until=datetime.datetime.today()):
78 + if ai_filter_num == 1:
79 + ai_setting = {
80 + "n_steps": 100, # 시퀀스 데이터를 몇개씩 담을지 설정
81 + "lookup_step": 30, # 단위 : 몇 일(분) 뒤의 종가를 예측 할 것 인지
82 + "test_size": 0.2, # train 범위
83 + "n_layers": 4, # LSTM layer 개수
84 + "units": 50, # LSTM neurons 개수
85 + "dropout": 0.2, # overfitting 방지를 위한 dropout
86 + "loss": "mse", # loss : 최적화 과정에서 최소화될 손실 함수
87 + "optimizer": "adam", # optimizer : 최적화 알고리즘 선택
88 + "batch_size": 64, # 각 학습 반복에 사용할 데이터 샘플 수
89 + "epochs": 400, # 몇 번 테스트 할지
90 + "ratio_cut": 3, # 단위:(%) lookup_step 기간 뒤 ratio_cut(%) 만큼 증가 할 것이 예측 된다면 매수
91 + "table": "daily_craw", # 분석 시 daily_craw(일별데이터)를 이용 할지 min_craw(분별데이터)를 이용 할지
92 + "is_used_predicted_close" : True # ratio(예상 상승률) 계산 시 예측 그래프의 close 값을 이용 할 경우 True,
93 + # 실제 close 값을 이용할 시 False
94 + }
95 + tr_engine = create_training_engine(ai_setting['table'])
96 +
97 + buy_list=None
98 +
99 + try:
100 + query="SELECT DISTINCT code_name FROM realtime_daily_buy_list"
101 + buy_list=engine.execute(query).fetchall()
102 + except (InternalError,ProgrammingError) as err:
103 + if 'Table' in str(err):
104 + print("realtime_daily_buy_list 테이블이 존재하지 않습니다.")
105 + else:
106 + print("autobot 데이터베이스가 존재하지 않습니다.")
107 + exit(1)
108 +
109 + feature_columns = ["close", "volume", "open", "high", "low"]
110 + filtered_list = []
111 + for code_name in buy_list:
112 + sql = """
113 + SELECT {} FROM `{}`
114 + WHERE STR_TO_DATE(date, '%Y%m%d%H%i') <= '{}'
115 + """.format(','.join(feature_columns), code_name, until)
116 + df = pd.read_sql(sql, tr_engine)
117 +
118 + # 데이터가 1000개(1000일 or 1000분)가 넘지 않으면 예측도가 떨어지기 때문에 필터링
119 + if len(df) < 1000:
120 + filtered_list.append(code_name)
121 + print(f"테스트 데이터가 적어서 realtime_daily_buy_list 에서 제외")
122 + continue
123 + try:
124 + filtered = lstm_algorithm(df, ai_setting)
125 + except ValueError:
126 + print(f"테스트 데이터가 적어서 realtime_daily_buy_list 에서 제외")
127 + filtered_list.append(code_name)
128 + continue
129 +
130 + print(code_name)
131 +
132 + # filtered가 True 이면 filtered_list(필터링 종목)에 해당 종목을 append
133 + if filtered:
134 + print(f"기준에 부합하지 않으므로 realtime_daily_buy_list 에서 제외")
135 + filtered_list.append(code_name)
136 +
137 + # filtered_list에 있는 종목들을 realtime_daily_buy_list(매수리스트)에서 제거
138 + if len(filtered_list) > 0:
139 + engine.execute(f"""
140 + DELETE FROM realtime_daily_buy_list WHERE code_name in ({','.join(map('"{}"'.format, filtered_list))})
141 + """)
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -8,6 +8,7 @@ from library.Logger import * ...@@ -8,6 +8,7 @@ from library.Logger import *
8 import library.cf 8 import library.cf
9 from library.open_api import * 9 from library.open_api import *
10 10
11 +
11 class simulator_api: 12 class simulator_api:
12 def __init__(self,simul_num,op,db_name): 13 def __init__(self,simul_num,op,db_name):
13 self.cf=library.cf 14 self.cf=library.cf
...@@ -54,13 +55,16 @@ class simulator_api: ...@@ -54,13 +55,16 @@ class simulator_api:
54 self.buy_stop=False # 거래를 중지하는 변수 55 self.buy_stop=False # 거래를 중지하는 변수
55 self.trade_check_num=False # 실시간 조건 매수 옵션. 분별 시뮬레이팅의 경우 True, 일별 시뮬레이팅의 경우 False 56 self.trade_check_num=False # 실시간 조건 매수 옵션. 분별 시뮬레이팅의 경우 True, 일별 시뮬레이팅의 경우 False
56 57
57 - self.use_ai=False # ai(deep learning) 알고리즘 사용 여부
58 - self.ai_num=1 # ai 알고리즘 번호
59 -
60 print("simul_num : ",self.simul_num) 58 print("simul_num : ",self.simul_num)
61 59
62 self.volume_limit=1000 60 self.volume_limit=1000
63 61
62 + # not using Deep Learning Algorithm
63 + if self.simul_num in (1,2,3,4):
64 + self.use_ai=False # ai(deep learning) 알고리즘 사용 여부
65 + self.ai_num=1 # ai 알고리즘 번호
66 +
67 + # Golden/Dead Cross(5,20) Algorithm
64 if self.simul_num==1: 68 if self.simul_num==1:
65 self.simul_start_date="20190101" 69 self.simul_start_date="20190101"
66 70
...@@ -77,12 +81,14 @@ class simulator_api: ...@@ -77,12 +81,14 @@ class simulator_api:
77 self.invest_limit_rate=1.01 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 상승했을 때는 매수하지 않음 81 self.invest_limit_rate=1.01 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 상승했을 때는 매수하지 않음
78 self.invest_min_limit_rate=0.98 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 하락했을 경우 매수하지 않음 82 self.invest_min_limit_rate=0.98 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 하락했을 경우 매수하지 않음
79 83
84 + # Golden/Dead Cross(20,60) Algorithm
80 elif self.simul_num==2: 85 elif self.simul_num==2:
81 self.simul_start_date="20190101" 86 self.simul_start_date="20190101"
82 87
83 self.db_to_realtime_daily_buy_list_num=2 88 self.db_to_realtime_daily_buy_list_num=2
84 self.sell_list_num=2 89 self.sell_list_num=2
85 90
91 + # 시뮬레이션 변수 설정
86 self.start_invest_price=1000000 92 self.start_invest_price=1000000
87 self.invest_unit=100000 93 self.invest_unit=100000
88 self.limit_money=300000 94 self.limit_money=300000
...@@ -92,7 +98,79 @@ class simulator_api: ...@@ -92,7 +98,79 @@ class simulator_api:
92 self.invest_limit_rate=1.01 98 self.invest_limit_rate=1.01
93 self.invest_min_limit_rate=0.98 99 self.invest_min_limit_rate=0.98
94 100
101 + # RSI Algorithm
95 elif self.simul_num==3: 102 elif self.simul_num==3:
103 + self.simul_start_date="20190101"
104 +
105 + self.db_to_realtime_daily_buy_list_num=3
106 + self.sell_list_num=3
107 +
108 + self.start_invest_price=1000000
109 + self.invest_unit=100000
110 + self.limit_money=300000
111 + self.sell_point=10
112 + self.losscut_point=-2
113 +
114 + self.invest_limit_rate=1.01
115 + self.invest_min_limit_rate=0.98
116 +
117 + # RMI Algorithm
118 + elif self.simul_num==4:
119 + self.simul_start_date = "20190101"
120 +
121 + self.db_to_realtime_daily_buy_list_num = 4
122 + self.sell_list_num = 4
123 +
124 + self.start_invest_price = 1000000
125 + self.invest_unit = 100000
126 + self.limit_money = 300000
127 + self.sell_point = 10
128 + self.losscut_point = -2
129 +
130 + self.invest_limit_rate = 1.01
131 + self.invest_min_limit_rate = 0.98
132 +
133 + # using Deep Learning Algorithm
134 + elif self.simul_num in (5,6,7,8):
135 + self.use_ai=True
136 + self.ai_num=1
137 +
138 + # Golden/Dead Cross Algorithm
139 + if self.simul_num == 5:
140 + self.simul_start_date = "20190101"
141 +
142 + self.db_to_realtime_daily_buy_list_num = 1
143 + self.sell_list_num = 1
144 +
145 + # 시뮬레이션 변수 설정
146 + self.start_invest_price = 1000000
147 + self.invest_unit = 100000
148 + self.limit_money = 300000
149 + self.sell_point = 10
150 + self.losscut_point = -2
151 +
152 + self.invest_limit_rate = 1.01
153 + self.invest_min_limit_rate = 0.98
154 +
155 + # Golden/Dead Cross Algorithm
156 + if self.simul_num == 6:
157 + self.simul_start_date = "20190101"
158 +
159 + self.db_to_realtime_daily_buy_list_num = 2
160 + self.sell_list_num = 2
161 +
162 + # 시뮬레이션 변수 설정
163 + self.start_invest_price = 1000000
164 + self.invest_unit = 100000
165 + self.limit_money = 300000
166 + self.sell_point = 10
167 + self.losscut_point = -2
168 +
169 + self.invest_limit_rate = 1.01
170 + self.invest_min_limit_rate = 0.98
171 +
172 + # RSI Algorithm
173 + elif self.simul_num == 7:
96 self.simul_start_date = "20190101" 174 self.simul_start_date = "20190101"
97 175
98 self.db_to_realtime_daily_buy_list_num = 3 176 self.db_to_realtime_daily_buy_list_num = 3
...@@ -107,6 +185,22 @@ class simulator_api: ...@@ -107,6 +185,22 @@ class simulator_api:
107 self.invest_limit_rate = 1.01 185 self.invest_limit_rate = 1.01
108 self.invest_min_limit_rate = 0.98 186 self.invest_min_limit_rate = 0.98
109 187
188 + # RMI Algorithm
189 + elif self.simul_num == 8:
190 + self.simul_start_date = "20190101"
191 +
192 + self.db_to_realtime_daily_buy_list_num = 4
193 + self.sell_list_num = 4
194 +
195 + self.start_invest_price = 1000000
196 + self.invest_unit = 100000
197 + self.limit_money = 300000
198 + self.sell_point = 10
199 + self.losscut_point = -2
200 +
201 + self.invest_limit_rate = 1.01
202 + self.invest_min_limit_rate = 0.98
203 +
110 else: 204 else:
111 logger.error("Invalid simul_num") 205 logger.error("Invalid simul_num")
112 206
...@@ -260,10 +354,10 @@ class simulator_api: ...@@ -260,10 +354,10 @@ class simulator_api:
260 "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate", 354 "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate",
261 "clo60_diff_rate", "clo120_diff_rate"]) 355 "clo60_diff_rate", "clo120_diff_rate"])
262 356
263 - #jango(잔고 테이블)에 저장된 가장 최근의 날짜를 가져오는 함수 357 + # jango(잔고 테이블)에 저장된 가장 최근의 날짜를 가져오는 함수
264 def get_jango_data_last_date(self): 358 def get_jango_data_last_date(self):
265 query = "SELECT date from jango_data order by date desc limit 1" 359 query = "SELECT date from jango_data order by date desc limit 1"
266 - result=self.engine_simul.execute(query).fechall() 360 + result=self.engine_simul.execute(query).fetchall()
267 return result[0][0] 361 return result[0][0]
268 362
269 # 시뮬레이팅 할 날짜 리스트를 가져오는 함수 363 # 시뮬레이팅 할 날짜 리스트를 가져오는 함수
...@@ -331,7 +425,7 @@ class simulator_api: ...@@ -331,7 +425,7 @@ class simulator_api:
331 # today_buy_count : 오늘 매수한 종목의 수 425 # today_buy_count : 오늘 매수한 종목의 수
332 query="update jango_data " \ 426 query="update jango_data " \
333 "set " \ 427 "set " \
334 - "today_buy_count=(select count(*) from (select code from all_stocks where buy_date like '%s')) "\ 428 + "today_buy_count=(select count(*) from (select code from all_stocks where buy_date like '%s') b) "\
335 "where date='%s'" 429 "where date='%s'"
336 self.engine_simul.execute(query%("%%"+str(rows[i][0])+"%%",rows[i][0])) 430 self.engine_simul.execute(query%("%%"+str(rows[i][0])+"%%",rows[i][0]))
337 431
...@@ -340,16 +434,16 @@ class simulator_api: ...@@ -340,16 +434,16 @@ class simulator_api:
340 "set " \ 434 "set " \
341 "today_buy_today_sell_count=" \ 435 "today_buy_today_sell_count=" \
342 "(select count(*) from " \ 436 "(select count(*) from " \
343 - "(select code from all_stocks where buy_date like '%s' and sell_date!=0 group by code)) " \ 437 + "(select code from all_stocks where buy_date like '%s' and sell_date!=0 group by code) b) " \
344 "where date='%s'" 438 "where date='%s'"
345 self.engine_simul.execute(query%("%%"+str(rows[i][0])+"%%",rows[i][0])) 439 self.engine_simul.execute(query%("%%"+str(rows[i][0])+"%%",rows[i][0]))
346 440
347 # today_buy_today_possess_count : 오늘 매수하였으나 매도하지 않은 종목의 수 441 # today_buy_today_possess_count : 오늘 매수하였으나 매도하지 않은 종목의 수
348 query="update jango_data " \ 442 query="update jango_data " \
349 - "set" \ 443 + "set " \
350 "today_buy_today_possess_count=" \ 444 "today_buy_today_possess_count=" \
351 "(select count(*) from " \ 445 "(select count(*) from " \
352 - "(select code from all_stocks where buy_date like '%s' and sell_date='%s' group by code)) " \ 446 + "(select code from all_stocks where buy_date like '%s' and sell_date='%s' group by code) b) " \
353 "where date='%s'" 447 "where date='%s'"
354 self.engine_simul.execute(query%("%%"+rows[i][0]+"%%",0,rows[i][0])) 448 self.engine_simul.execute(query%("%%"+rows[i][0]+"%%",0,rows[i][0]))
355 449
...@@ -359,7 +453,7 @@ class simulator_api: ...@@ -359,7 +453,7 @@ class simulator_api:
359 "today_buy_today_profitcut_count=" \ 453 "today_buy_today_profitcut_count=" \
360 "(select count(*) from " \ 454 "(select count(*) from " \
361 "(select code from all_stocks " \ 455 "(select code from all_stocks " \
362 - "where buy_date like '%s' and sell_date like '%s' and sell_rate>'%s' group by code)) " \ 456 + "where buy_date like '%s' and sell_date like '%s' and sell_rate>'%s' group by code) b) " \
363 "where date='%s'" 457 "where date='%s'"
364 self.engine_simul.execute(query%("%%" + rows[i][0] + "%%", "%%" + rows[i][0] + "%%", 0, rows[i][0])) 458 self.engine_simul.execute(query%("%%" + rows[i][0] + "%%", "%%" + rows[i][0] + "%%", 0, rows[i][0]))
365 459
...@@ -376,7 +470,7 @@ class simulator_api: ...@@ -376,7 +470,7 @@ class simulator_api:
376 "today_buy_today_losscut_count=" \ 470 "today_buy_today_losscut_count=" \
377 "(select count(*) from " \ 471 "(select count(*) from " \
378 "(select code from all_stocks " \ 472 "(select code from all_stocks " \
379 - "where buy_date like '%s' and sell_date like '%s' and sell_rate < '%s' group by code)) " \ 473 + "where buy_date like '%s' and sell_date like '%s' and sell_rate < '%s' group by code) b) " \
380 "WHERE date='%s'" 474 "WHERE date='%s'"
381 self.engine_simul.execute(query%("%%" + rows[i][0] + "%%", "%%" + rows[i][0] + "%%", 0, rows[i][0])) 475 self.engine_simul.execute(query%("%%" + rows[i][0] + "%%", "%%" + rows[i][0] + "%%", 0, rows[i][0]))
382 476
...@@ -392,36 +486,42 @@ class simulator_api: ...@@ -392,36 +486,42 @@ class simulator_api:
392 "set " \ 486 "set " \
393 "total_profitcut_count=" \ 487 "total_profitcut_count=" \
394 "(select count(*) from " \ 488 "(select count(*) from " \
395 - "(select code from all_stocks where sell_rate >= '%s' group by code)) "\ 489 + "(select code from all_stocks where sell_rate >= '%s' group by code) b) "\
396 "WHERE date='%s'" 490 "WHERE date='%s'"
397 self.engine_simul.execute(query%(0, rows[i][0])) 491 self.engine_simul.execute(query%(0, rows[i][0]))
398 492
399 # total_profitcut : 총 익절한 금액 (매도가 - 매수가) 493 # total_profitcut : 총 익절한 금액 (매도가 - 매수가)
400 - query = "update jango " \ 494 + profitcut=self.engine_simul.execute(
495 + f"select sum(sell_price-purchase_price) from all_stocks "
496 + f"where sell_price>purchase_price and sell_date<='{rows[i][0]}'").fetchall()
497 + if profitcut[0][0]!=None:
498 + tot_profitcut=int(profitcut[0][0])
499 + query = "update jango_data " \
401 "set " \ 500 "set " \
402 - "total_profitcut=sum" \ 501 + "total_profitcut=%s " \
403 - "(select sell_price-purchase_price from all_stocks " \
404 - "where sell_price>=purchase_price group by code))" \
405 "WHERE date = '%s'" 502 "WHERE date = '%s'"
406 - self.engine_simul.execute(query%(rows[i][0])) 503 + self.engine_simul.execute(query%(tot_profitcut,rows[i][0]))
407 504
408 # total_losscut_count : 총 손절한 종목의 수 505 # total_losscut_count : 총 손절한 종목의 수
409 query = "update jango_data " \ 506 query = "update jango_data " \
410 "set " \ 507 "set " \
411 "total_losscut_count=" \ 508 "total_losscut_count=" \
412 "(select count(*) from " \ 509 "(select count(*) from " \
413 - "(select code from all_stocks where sell_rate < '%s' group by code )) " \ 510 + "(select code from all_stocks where sell_rate < '%s' group by code ) b) " \
414 "WHERE date='%s'" 511 "WHERE date='%s'"
415 self.engine_simul.execute(query%(0,rows[i][0])) 512 self.engine_simul.execute(query%(0,rows[i][0]))
416 513
417 # total_losscut : 총 손절한 금액 (매수가 - 매도가) 514 # total_losscut : 총 손절한 금액 (매수가 - 매도가)
515 + losscut=self.engine_simul.execute(
516 + f"select sum(purchase_price-sell_price) from all_stocks "
517 + f"where purchase_price>sell_price and sell_date<='{rows[i][0]}'").fetchall()
518 + if losscut[0][0]==None:
519 + tot_losscut=int(losscut[0][0])
418 query = "update jango_data " \ 520 query = "update jango_data " \
419 "set " \ 521 "set " \
420 - "total_losscut=sum" \ 522 + "total_losscut=%s "\
421 - "(select purchase_price-sell_price from all_stocks " \
422 - "where purchase_price>=sell_price)) " \
423 "where date='%s'" 523 "where date='%s'"
424 - self.engine_simul.execute(query%(rows[i][0])) 524 + self.engine_simul.execute(query%(tot_losscut,rows[i][0]))
425 print("account balance 정산 완료") 525 print("account balance 정산 완료")
426 526
427 # jango_data에 저장된 일자를 반환하는 함수 527 # jango_data에 저장된 일자를 반환하는 함수
...@@ -476,21 +576,28 @@ class simulator_api: ...@@ -476,21 +576,28 @@ class simulator_api:
476 query = f"select * from `{date_rows_yesterday}` " \ 576 query = f"select * from `{date_rows_yesterday}` " \
477 f"where yes_clo40 > yes_clo5 and clo5 > clo40 and close < '{self.invest_unit}' group by code" 577 f"where yes_clo40 > yes_clo5 and clo5 > clo40 and close < '{self.invest_unit}' group by code"
478 realtime_daily_buy_list = self.engine_daily_buy_list.execute(query).fetchall() 578 realtime_daily_buy_list = self.engine_daily_buy_list.execute(query).fetchall()
579 + """
580 + # RSI
581 + elif self.db_to_realtime_daily_buy_list_num==3:
582 + au_query=f"select "
583 + # RMI
584 + elif self.db_to_realtime_daily_buy_list_num==4:
479 585
480 else: 586 else:
481 logger.error("Invalid Algorithm Setting...") 587 logger.error("Invalid Algorithm Setting...")
482 - 588 + """
483 # 알고리즘에 의해 선택된 항목이 존재한다면 데이터베이스에 해당 항목 업데이트 589 # 알고리즘에 의해 선택된 항목이 존재한다면 데이터베이스에 해당 항목 업데이트
484 if len(realtime_daily_buy_list) > 0: 590 if len(realtime_daily_buy_list) > 0:
485 df_realtime_daily_buy_list = DataFrame(realtime_daily_buy_list, 591 df_realtime_daily_buy_list = DataFrame(realtime_daily_buy_list,
486 columns=['index', 'index2', 'date', 'check_item', 'code', 592 columns=['index', 'index2', 'date', 'check_item', 'code',
487 - 'code_name', 'd1_diff','d1_diff_rate', 593 + 'code_name', 'd1_diff_rate',
488 'close', 'open', 'high','low', 'volume', 594 'close', 'open', 'high','low', 'volume',
489 'clo5', 'clo10', 'clo20', 'clo60', 'clo120', 595 'clo5', 'clo10', 'clo20', 'clo60', 'clo120',
490 "clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate", 596 "clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate",
491 "clo60_diff_rate", "clo120_diff_rate", 597 "clo60_diff_rate", "clo120_diff_rate",
492 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120', 598 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120',
493 - 'vol5', 'vol10', 'vol20', 'vol60', 'vol120']) 599 + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120',
600 + 'd1_diff','dn_diff'])
494 601
495 # 다음날 매수할 종목 중 code가 6자리의 정수로 된 항목만 선택 602 # 다음날 매수할 종목 중 code가 6자리의 정수로 된 항목만 선택
496 df_realtime_daily_buy_list['code'] = df_realtime_daily_buy_list['code'].apply( 603 df_realtime_daily_buy_list['code'] = df_realtime_daily_buy_list['code'].apply(
...@@ -516,6 +623,7 @@ class simulator_api: ...@@ -516,6 +623,7 @@ class simulator_api:
516 from ai_trader import ai_filter 623 from ai_trader import ai_filter
517 ai_filter(self.ai_num, engine=self.engine_simul, until=date_rows_yesterday) 624 ai_filter(self.ai_num, engine=self.engine_simul, until=date_rows_yesterday)
518 625
626 +
519 # 모의투자 / 실전투자 627 # 모의투자 / 실전투자
520 else: 628 else:
521 df_realtime_daily_buy_list['check_item'] = int(0) 629 df_realtime_daily_buy_list['check_item'] = int(0)
...@@ -535,13 +643,14 @@ class simulator_api: ...@@ -535,13 +643,14 @@ class simulator_api:
535 643
536 self.df_realtime_daily_buy_list=DataFrame(realtime_daily_buy_list, 644 self.df_realtime_daily_buy_list=DataFrame(realtime_daily_buy_list,
537 columns=['index', 'index2', 'index3','date', 'check_item', 'code', 645 columns=['index', 'index2', 'index3','date', 'check_item', 'code',
538 - 'code_name', 'd1_diff','d1_diff_rate', 646 + 'code_name', 'd1_diff_rate',
539 'close', 'open', 'high','low', 'volume', 647 'close', 'open', 'high','low', 'volume',
540 'clo5', 'clo10', 'clo20', 'clo60', 'clo120', 648 'clo5', 'clo10', 'clo20', 'clo60', 'clo120',
541 "clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate", 649 "clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate",
542 "clo60_diff_rate", "clo120_diff_rate", 650 "clo60_diff_rate", "clo120_diff_rate",
543 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120', 651 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120',
544 - 'vol5', 'vol10', 'vol20', 'vol60', 'vol120']) 652 + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120',
653 + 'd1_diff','dn_diff'])
545 654
546 self.len_df_realtime_daily_buy_list = len(self.df_realtime_daily_buy_list) 655 self.len_df_realtime_daily_buy_list = len(self.df_realtime_daily_buy_list)
547 656
...@@ -1226,13 +1335,14 @@ class simulator_api: ...@@ -1226,13 +1335,14 @@ class simulator_api:
1226 1335
1227 df_daily_buy_list = DataFrame(daily_buy_list, 1336 df_daily_buy_list = DataFrame(daily_buy_list,
1228 columns=['index', 'index2', 'date', 'check_item', 1337 columns=['index', 'index2', 'date', 'check_item',
1229 - 'code', 'code_name', 'd1_diff', 'd1_diff_rate', 1338 + 'code', 'code_name', 'd1_diff_rate',
1230 'close', 'open','high', 'low', 'volume', 1339 'close', 'open','high', 'low', 'volume',
1231 'clo5', 'clo10', 'clo20', 'clo60', 'clo120', 1340 'clo5', 'clo10', 'clo20', 'clo60', 'clo120',
1232 "clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate", 1341 "clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate",
1233 "clo60_diff_rate", "clo120_diff_rate", 1342 "clo60_diff_rate", "clo120_diff_rate",
1234 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120', 1343 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120',
1235 - 'vol5', 'vol10', 'vol20', 'vol60', 'vol120']) 1344 + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120',
1345 + 'd1_diff','dn_diff'])
1236 return df_daily_buy_list 1346 return df_daily_buy_list
1237 1347
1238 # 현재 특정 종목의 종가를 가져오는 함수 1348 # 현재 특정 종목의 종가를 가져오는 함수
......
...@@ -326,7 +326,8 @@ class collector_api(): ...@@ -326,7 +326,8 @@ class collector_api():
326 "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate", "clo60_diff_rate", 326 "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate", "clo60_diff_rate",
327 "clo120_diff_rate", 327 "clo120_diff_rate",
328 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60', 'yes_clo120', 328 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60', 'yes_clo120',
329 - 'vol5', 'vol10', 'vol20', 'vol60', 'vol120', 'vol80' 329 + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120',
330 + 'd1_diff','dn_diff'
330 ]) 331 ])
331 332
332 df_temp = df_temp.sort_values(by=['date'], ascending=True) 333 df_temp = df_temp.sort_values(by=['date'], ascending=True)
...@@ -365,6 +366,9 @@ class collector_api(): ...@@ -365,6 +366,9 @@ class collector_api():
365 df_temp['vol60'] = df_temp['volume'].rolling(window=60).mean() 366 df_temp['vol60'] = df_temp['volume'].rolling(window=60).mean()
366 df_temp['vol120'] = df_temp['volume'].rolling(window=120).mean() 367 df_temp['vol120'] = df_temp['volume'].rolling(window=120).mean()
367 368
369 + df_temp['d1_diff']=df_temp['close']-df_temp['close'].shift(1)
370 + df_temp['dn_diff']=df_temp['close']-df_temp['close'].shift(14)
371 +
368 # daily_craw테이블이 존재할 경우, 저장되어있는 날짜 이후의 값을 저장 372 # daily_craw테이블이 존재할 경우, 저장되어있는 날짜 이후의 값을 저장
369 if self.engine_bot.dialect.has_table(self.open_api.engine_daily_craw, code_name): 373 if self.engine_bot.dialect.has_table(self.open_api.engine_daily_craw, code_name):
370 df_temp = df_temp[df_temp.date > self.open_api.get_daily_craw_db_last_date(code_name)] 374 df_temp = df_temp[df_temp.date > self.open_api.get_daily_craw_db_last_date(code_name)]
...@@ -587,3 +591,39 @@ class collector_api(): ...@@ -587,3 +591,39 @@ class collector_api():
587 self.open_api.comm_rq_data("opt10074_req", "opt10074", 2, "0329") 591 self.open_api.comm_rq_data("opt10074_req", "opt10074", 2, "0329")
588 592
589 self.db_to_jango() 593 self.db_to_jango()
594 +
595 + def get_code_list(self):
596 + self.dc.get_item_kospi()
597 + self.stock_to_db(self.dc.code_df_kospi,"item_all")
598 +
599 + def stock_to_db(self,origin_df,type):
600 + checking_stocks=['kospi']
601 + stock_df=DataFrame()
602 + stock_df['code']=origin_df['code']
603 + name_list=[]
604 + for info in origin_df.itertuples():
605 + kiwoom_name = self.open_api.dynamicCall("GetMasterCodeName(QString)", info.code).strip()
606 + name_list.append(kiwoom_name)
607 + if not kiwoom_name:
608 + if type in checking_stocks:
609 + logger.error(
610 + f"종목명이 비어있습니다. - "
611 + f"종목: {info.code_name}, "
612 + f"코드: {info.code}"
613 + )
614 +
615 + stock_df['code_name']=name_list
616 + stock_df['check_item']=0
617 +
618 + if type in checking_stocks:
619 + stock_df=stock_df[stock_df['code_name'].map(len)>0]
620 +
621 + if type=="item_all":
622 + stock_df['check_daily_crawler']='0'
623 + stock_df['check_min_crawler']='0'
624 +
625 + dtypes=dict(zip(list(stock_df.columns),[Text]*len(stock_df.columns)))
626 + dtypes['check_item']=Integer
627 +
628 + stock_df.to_sql(f'stock_{type}',self.open_api.engine_daily_buy_list,if_exists='replace',dtype=dtypes)
629 + return stock_df
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -64,7 +64,7 @@ class daily_buy_list(): ...@@ -64,7 +64,7 @@ class daily_buy_list():
64 if not self.is_table_exist_daily_craw(code, code_name): 64 if not self.is_table_exist_daily_craw(code, code_name):
65 continue 65 continue
66 66
67 - query = f"select * from {self.stock_item_all[i][0]} where date = '{self.date_rows[k][0]}' " \ 67 + query = f"select * from `{self.stock_item_all[i][0]}` where date = '{self.date_rows[k][0]}' " \
68 f"group by date" 68 f"group by date"
69 rows = self.engine_daily_craw.execute(query).fetchall() 69 rows = self.engine_daily_craw.execute(query).fetchall()
70 multi_list += rows 70 multi_list += rows
...@@ -72,13 +72,14 @@ class daily_buy_list(): ...@@ -72,13 +72,14 @@ class daily_buy_list():
72 if len(multi_list) != 0: 72 if len(multi_list) != 0:
73 df_temp = DataFrame(multi_list, 73 df_temp = DataFrame(multi_list,
74 columns=['index', 'date', 'check_item', 'code', 'code_name', 74 columns=['index', 'date', 'check_item', 'code', 'code_name',
75 - 'd1_diff','d1_diff_rate', 75 + 'd1_diff_rate',
76 'close', 'open', 'high', 'low','volume', 76 'close', 'open', 'high', 'low','volume',
77 'clo5', 'clo10', 'clo20', 'clo60', 'clo120', 77 'clo5', 'clo10', 'clo20', 'clo60', 'clo120',
78 "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate", 78 "clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate",
79 "clo60_diff_rate", "clo120_diff_rate", 79 "clo60_diff_rate", "clo120_diff_rate",
80 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60', 'yes_clo120', 80 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60', 'yes_clo120',
81 - 'vol5', 'vol10', 'vol20', 'vol60', 'vol120' 81 + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120',
82 + 'd1_diff','dn_diff'
82 ]) 83 ])
83 84
84 df_temp.to_sql(name=self.date_rows[k][0], con=self.engine_daily_buy_list, if_exists='replace') 85 df_temp.to_sql(name=self.date_rows[k][0], con=self.engine_daily_buy_list, if_exists='replace')
......
...@@ -47,3 +47,15 @@ class daily_crawler(): ...@@ -47,3 +47,15 @@ class daily_crawler():
47 return True 47 return True
48 else: 48 else:
49 return False 49 return False
50 +
51 + def get_item_kospi(self):
52 + self.code_df_kospi = pd.read_html('http://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13&marketType=stockMkt',header=0)[0] # 종목코드가 6자리이기 때문에 6자리를 맞춰주기 위해 설정해줌
53 +
54 + # 6자리 만들고 앞에 0을 붙인다.
55 + self.code_df_kospi.종목코드 = self.code_df_kospi.종목코드.map('{:06d}'.format)
56 +
57 + # 회사명과 종목코드를 제외한 칼럼은 삭제
58 + self.code_df_kospi = self.code_df_kospi[['회사명', '종목코드']]
59 +
60 + # 한글로된 컬럼명을 영어로 변경
61 + self.code_df_kospi = self.code_df_kospi.rename(columns={'회사명': 'code_name', '종목코드': 'code'})
......
...@@ -126,6 +126,7 @@ class open_api(QAxWidget): ...@@ -126,6 +126,7 @@ class open_api(QAxWidget):
126 self.login_event_loop.exit() 126 self.login_event_loop.exit()
127 except Exception as e: 127 except Exception as e:
128 logger.critical(e) 128 logger.critical(e)
129 + sys.exit()
129 130
130 # 사용자의 계좌정보 저장 및 출력 131 # 사용자의 계좌정보 저장 및 출력
131 def account_info(self): 132 def account_info(self):
...@@ -243,12 +244,12 @@ class open_api(QAxWidget): ...@@ -243,12 +244,12 @@ class open_api(QAxWidget):
243 # 해당 종목의 체결 실패 내역이 없다면 244 # 해당 종목의 체결 실패 내역이 없다면
244 # all_stocks 테이블에 업데이트. 정상 체결 시 chegyul_check=0 245 # all_stocks 테이블에 업데이트. 정상 체결 시 chegyul_check=0
245 if chegyul_fail_amount=="0": 246 if chegyul_fail_amount=="0":
246 - logger.debug(code, "체결 완료") 247 + logger.debug(code+ "체결 완료")
247 self.db_to_all_stocks(order_num,code,0,purchase_price,0) 248 self.db_to_all_stocks(order_num,code,0,purchase_price,0)
248 # 체결 실패 내역이 존재한다면 249 # 체결 실패 내역이 존재한다면
249 # all_stocks 테이블에 업데이트. 미체결 시 chegyul_check=1 250 # all_stocks 테이블에 업데이트. 미체결 시 chegyul_check=1
250 else: 251 else:
251 - logger.debug(code,"미체결") 252 + logger.debug(code+"미체결")
252 self.db_to_all_stocks(order_num,code,1,purchase_price,0) 253 self.db_to_all_stocks(order_num,code,1,purchase_price,0)
253 254
254 # 매수하는 경우 255 # 매수하는 경우
...@@ -281,7 +282,7 @@ class open_api(QAxWidget): ...@@ -281,7 +282,7 @@ class open_api(QAxWidget):
281 # 국내주식 잔고전달 282 # 국내주식 잔고전달
282 elif sGubun=="1": 283 elif sGubun=="1":
283 chegyul_fail_amount=self.get_chejan_data(902) 284 chegyul_fail_amount=self.get_chejan_data(902)
284 - logger.debug("미체결 수량",chegyul_fail_amount) 285 + logger.debug("미체결 수량 : "+chegyul_fail_amount)
285 286
286 else: 287 else:
287 logger.debug("Invlid _receive_chejan_data") 288 logger.debug("Invlid _receive_chejan_data")
...@@ -784,7 +785,7 @@ class open_api(QAxWidget): ...@@ -784,7 +785,7 @@ class open_api(QAxWidget):
784 self.set_input_value("계좌번호",self.account_no) 785 self.set_input_value("계좌번호",self.account_no)
785 self.comm_rq_data("opt10076_req","opt10076",0,"0350") 786 self.comm_rq_data("opt10076_req","opt10076",0,"0350")
786 787
787 - query=f"update all_stocks set chegyul_check='0' where code='{r.code}' and sell_data='0' " \ 788 + query=f"update all_stocks set chegyul_check='0' where code='{r.code}' and sell_date='0' " \
788 f"order by buy_date desc limit 1" 789 f"order by buy_date desc limit 1"
789 # 과거에 거래한 내역이 존재하는 경우 opt10076 조회 시 주문번호 등의 데이터가 존재하지 않음 790 # 과거에 거래한 내역이 존재하는 경우 opt10076 조회 시 주문번호 등의 데이터가 존재하지 않음
790 # 거래가 완료된 항목에 대해서 contract_check항목을 '0'으로 업데이트 791 # 거래가 완료된 항목에 대해서 contract_check항목을 '0'으로 업데이트
......
...@@ -14,7 +14,7 @@ class Trader(QMainWindow): ...@@ -14,7 +14,7 @@ class Trader(QMainWindow):
14 14
15 self.market_start_time=QTime(9,0,0) # 장시작 시간 15 self.market_start_time=QTime(9,0,0) # 장시작 시간
16 self.market_end_time=QTime(15,30,0) # 장마감 시간 16 self.market_end_time=QTime(15,30,0) # 장마감 시간
17 - self.buy_end_time=QTime(9,6,0) # 매수를 몇 시까지 할지 17 + self.buy_end_time=QTime(9,30,0) # 매수를 몇 시까지 할지
18 18
19 # 매수 함수 19 # 매수 함수
20 def auto_trade_stock(self): 20 def auto_trade_stock(self):
...@@ -42,6 +42,7 @@ class Trader(QMainWindow): ...@@ -42,6 +42,7 @@ class Trader(QMainWindow):
42 self.open_api.final_chegyul_check() 42 self.open_api.final_chegyul_check()
43 # 매도리스트 저장 43 # 매도리스트 저장
44 self.get_sell_list_trade() 44 self.get_sell_list_trade()
45 + print(self.sell_list)
45 46
46 for i in range(len(self.sell_list)): 47 for i in range(len(self.sell_list)):
47 get_sell_code=self.sell_list[i][0] # 종목코드 48 get_sell_code=self.sell_list[i][0] # 종목코드
......