Showing
13 changed files
with
359 additions
and
77 deletions
... | @@ -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,58 +55,151 @@ class simulator_api: | ... | @@ -54,58 +55,151 @@ 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 | ||
64 | - if self.simul_num==1: | 62 | + # not using Deep Learning Algorithm |
65 | - self.simul_start_date="20190101" | 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 | ||
68 | + if self.simul_num==1: | ||
69 | + self.simul_start_date="20190101" | ||
70 | + | ||
71 | + self.db_to_realtime_daily_buy_list_num=1 # 매수리스트 설정 알고리즘 | ||
72 | + self.sell_list_num=1 # 매도리스트 설정 알고리즘 | ||
73 | + | ||
74 | + # 시뮬레이션 변수 설정 | ||
75 | + self.start_invest_price=1000000 # 초기 투자자금 | ||
76 | + self.invest_unit=100000 # 매수 금액 단위 | ||
77 | + self.limit_money=300000 # 자산 중 최소로 남겨 둘 금액 | ||
78 | + self.sell_point=10 # 익절 수익률 기준 | ||
79 | + self.losscut_point=-2 # 손절 수익률 기준 | ||
80 | + | ||
81 | + self.invest_limit_rate=1.01 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 상승했을 때는 매수하지 않음 | ||
82 | + self.invest_min_limit_rate=0.98 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 하락했을 경우 매수하지 않음 | ||
83 | + | ||
84 | + # Golden/Dead Cross(20,60) Algorithm | ||
85 | + elif self.simul_num==2: | ||
86 | + self.simul_start_date="20190101" | ||
87 | + | ||
88 | + self.db_to_realtime_daily_buy_list_num=2 | ||
89 | + self.sell_list_num=2 | ||
90 | + | ||
91 | + # 시뮬레이션 변수 설정 | ||
92 | + self.start_invest_price=1000000 | ||
93 | + self.invest_unit=100000 | ||
94 | + self.limit_money=300000 | ||
95 | + self.sell_point=10 | ||
96 | + self.losscut_point=-2 | ||
97 | + | ||
98 | + self.invest_limit_rate=1.01 | ||
99 | + self.invest_min_limit_rate=0.98 | ||
100 | + | ||
101 | + # RSI Algorithm | ||
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 | ||
66 | 116 | ||
67 | - self.db_to_realtime_daily_buy_list_num=1 # 매수리스트 설정 알고리즘 | 117 | + # RMI Algorithm |
68 | - self.sell_list_num=1 # 매도리스트 설정 알고리즘 | 118 | + elif self.simul_num==4: |
119 | + self.simul_start_date = "20190101" | ||
69 | 120 | ||
70 | - # 시뮬레이션 변수 설정 | 121 | + self.db_to_realtime_daily_buy_list_num = 4 |
71 | - self.start_invest_price=1000000 # 초기 투자자금 | 122 | + self.sell_list_num = 4 |
72 | - self.invest_unit=100000 # 매수 금액 단위 | ||
73 | - self.limit_money=300000 # 자산 중 최소로 남겨 둘 금액 | ||
74 | - self.sell_point=10 # 익절 수익률 기준 | ||
75 | - self.losscut_point=-2 # 손절 수익률 기준 | ||
76 | 123 | ||
77 | - self.invest_limit_rate=1.01 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 상승했을 때는 매수하지 않음 | 124 | + self.start_invest_price = 1000000 |
78 | - self.invest_min_limit_rate=0.98 # 매수하는 순간 종목의 최신 종가보다 가격이 n%이상 하락했을 경우 매수하지 않음 | 125 | + self.invest_unit = 100000 |
126 | + self.limit_money = 300000 | ||
127 | + self.sell_point = 10 | ||
128 | + self.losscut_point = -2 | ||
79 | 129 | ||
80 | - elif self.simul_num==2: | 130 | + self.invest_limit_rate = 1.01 |
81 | - self.simul_start_date="20190101" | 131 | + self.invest_min_limit_rate = 0.98 |
82 | 132 | ||
83 | - self.db_to_realtime_daily_buy_list_num=2 | 133 | + # using Deep Learning Algorithm |
84 | - self.sell_list_num=2 | 134 | + elif self.simul_num in (5,6,7,8): |
135 | + self.use_ai=True | ||
136 | + self.ai_num=1 | ||
85 | 137 | ||
86 | - self.start_invest_price=1000000 | 138 | + # Golden/Dead Cross Algorithm |
87 | - self.invest_unit=100000 | 139 | + if self.simul_num == 5: |
88 | - self.limit_money=300000 | 140 | + self.simul_start_date = "20190101" |
89 | - self.sell_point=10 | ||
90 | - self.losscut_point=-2 | ||
91 | 141 | ||
92 | - self.invest_limit_rate=1.01 | 142 | + self.db_to_realtime_daily_buy_list_num = 1 |
93 | - self.invest_min_limit_rate=0.98 | 143 | + self.sell_list_num = 1 |
94 | 144 | ||
95 | - elif self.simul_num==3: | 145 | + # 시뮬레이션 변수 설정 |
96 | - self.simul_start_date = "20190101" | 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 | ||
97 | 151 | ||
98 | - self.db_to_realtime_daily_buy_list_num = 3 | 152 | + self.invest_limit_rate = 1.01 |
99 | - self.sell_list_num = 3 | 153 | + self.invest_min_limit_rate = 0.98 |
100 | 154 | ||
101 | - self.start_invest_price = 1000000 | 155 | + # Golden/Dead Cross Algorithm |
102 | - self.invest_unit = 100000 | 156 | + if self.simul_num == 6: |
103 | - self.limit_money = 300000 | 157 | + self.simul_start_date = "20190101" |
104 | - self.sell_point = 10 | ||
105 | - self.losscut_point = -2 | ||
106 | 158 | ||
107 | - self.invest_limit_rate = 1.01 | 159 | + self.db_to_realtime_daily_buy_list_num = 2 |
108 | - self.invest_min_limit_rate = 0.98 | 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: | ||
174 | + self.simul_start_date = "20190101" | ||
175 | + | ||
176 | + self.db_to_realtime_daily_buy_list_num = 3 | ||
177 | + self.sell_list_num = 3 | ||
178 | + | ||
179 | + self.start_invest_price = 1000000 | ||
180 | + self.invest_unit = 100000 | ||
181 | + self.limit_money = 300000 | ||
182 | + self.sell_point = 10 | ||
183 | + self.losscut_point = -2 | ||
184 | + | ||
185 | + self.invest_limit_rate = 1.01 | ||
186 | + self.invest_min_limit_rate = 0.98 | ||
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 | ||
109 | 203 | ||
110 | else: | 204 | else: |
111 | logger.error("Invalid simul_num") | 205 | logger.error("Invalid simul_num") |
... | @@ -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( |
401 | - "set " \ | 495 | + f"select sum(sell_price-purchase_price) from all_stocks " |
402 | - "total_profitcut=sum" \ | 496 | + f"where sell_price>purchase_price and sell_date<='{rows[i][0]}'").fetchall() |
403 | - "(select sell_price-purchase_price from all_stocks " \ | 497 | + if profitcut[0][0]!=None: |
404 | - "where sell_price>=purchase_price group by code))" \ | 498 | + tot_profitcut=int(profitcut[0][0]) |
405 | - "WHERE date = '%s'" | 499 | + query = "update jango_data " \ |
406 | - self.engine_simul.execute(query%(rows[i][0])) | 500 | + "set " \ |
501 | + "total_profitcut=%s " \ | ||
502 | + "WHERE date = '%s'" | ||
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 : 총 손절한 금액 (매수가 - 매도가) |
418 | - query = "update jango_data " \ | 515 | + losscut=self.engine_simul.execute( |
419 | - "set " \ | 516 | + f"select sum(purchase_price-sell_price) from all_stocks " |
420 | - "total_losscut=sum" \ | 517 | + f"where purchase_price>sell_price and sell_date<='{rows[i][0]}'").fetchall() |
421 | - "(select purchase_price-sell_price from all_stocks " \ | 518 | + if losscut[0][0]==None: |
422 | - "where purchase_price>=sell_price)) " \ | 519 | + tot_losscut=int(losscut[0][0]) |
423 | - "where date='%s'" | 520 | + query = "update jango_data " \ |
424 | - self.engine_simul.execute(query%(rows[i][0])) | 521 | + "set " \ |
522 | + "total_losscut=%s "\ | ||
523 | + "where date='%s'" | ||
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 | # 현재 특정 종목의 종가를 가져오는 함수 | ... | ... |
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
... | @@ -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] # 종목코드 | ... | ... |
-
Please register or login to post a comment