Showing
4 changed files
with
535 additions
and
697 deletions
... | @@ -237,8 +237,7 @@ class Simulator_Func: | ... | @@ -237,8 +237,7 @@ class Simulator_Func: |
237 | columns=['id', 'order_num', 'code', 'code_name', 'rate', 'purchase_rate', | 237 | columns=['id', 'order_num', 'code', 'code_name', 'rate', 'purchase_rate', |
238 | 'purchase_price','present_price', 'valuation_price','valuation_profit', | 238 | 'purchase_price','present_price', 'valuation_price','valuation_profit', |
239 | 'holding_amount', 'buy_date', 'item_total_purchase','chegyul_check', | 239 | 'holding_amount', 'buy_date', 'item_total_purchase','chegyul_check', |
240 | - 'invest_unit','sell_date', 'sell_price', 'sell_rate', 'rate_std', | 240 | + 'invest_unit','sell_date', 'sell_price', 'sell_rate', |
241 | - 'rate_std_mod_val','rate_std_htr', 'rate_htr','rate_std_mod_val_htr', | ||
242 | 'yes_close', 'close', 'd1_diff_rate', 'd1_diff', | 241 | 'yes_close', 'close', 'd1_diff_rate', 'd1_diff', |
243 | 'open', 'high','low','volume', | 242 | 'open', 'high','low','volume', |
244 | 'clo5', 'clo10', 'clo20', 'clo60','clo120', | 243 | 'clo5', 'clo10', 'clo20', 'clo60','clo120', |
... | @@ -1192,3 +1191,30 @@ class Simulator_Func: | ... | @@ -1192,3 +1191,30 @@ class Simulator_Func: |
1192 | else: | 1191 | else: |
1193 | if self.check_balance(): | 1192 | if self.check_balance(): |
1194 | self.auto_trade_buy_stock(str(date_rows_today) + "0900", date_rows_today, date_rows_yesterday) | 1193 | self.auto_trade_buy_stock(str(date_rows_today) + "0900", date_rows_today, date_rows_yesterday) |
1194 | + | ||
1195 | + # daily_buy_list 데이터베이스에서 가장 최근의 날짜 테이블을 가져오는 함수 | ||
1196 | + def get_recent_daily_buy_list_date(self): | ||
1197 | + query="select TABLE_NAME from information_schema.tables " \ | ||
1198 | + "where table_schema = 'daily_buy_list' and TABLE_NAME like '%s' order by table_name desc limit 1" | ||
1199 | + row = self.engine_daily_buy_list.execute(query % ("20%%")).fetchall() | ||
1200 | + | ||
1201 | + if len(row) == 0: | ||
1202 | + return False | ||
1203 | + return row[0][0] | ||
1204 | + | ||
1205 | + # 최근 daily_buy_list의 날짜 테이블에서 code에 해당하는 데이터만 가져오는 함수 | ||
1206 | + def get_daily_buy_list_by_code(self,code,date): | ||
1207 | + query = f"select * from `{date}` where code = '{code}' group by code" | ||
1208 | + | ||
1209 | + daily_buy_list = self.engine_daily_buy_list.execute(query).fetchall() | ||
1210 | + | ||
1211 | + df_daily_buy_list = DataFrame(daily_buy_list, | ||
1212 | + columns=['index', 'index2', 'date', 'check_item', | ||
1213 | + 'code', 'code_name', 'd1_diff', 'd1_diff_rate', | ||
1214 | + 'close', 'open','high', 'low', 'volume', | ||
1215 | + 'clo5', 'clo10', 'clo20', 'clo60', 'clo120', | ||
1216 | + "clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate", | ||
1217 | + "clo60_diff_rate", "clo120_diff_rate", | ||
1218 | + 'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120', | ||
1219 | + 'vol5', 'vol10', 'vol20', 'vol60', 'vol120']) | ||
1220 | + return df_daily_buy_list | ... | ... |
1 | -from Open_Api import * | ||
2 | -from collections import OrderedDict | ||
3 | -from pandas import DataFrame | ||
4 | -import time | ||
5 | - | ||
6 | -from Daily_Info import * | ||
7 | -from Stock_Info import * | ||
8 | -import config | ||
9 | - | ||
10 | -class Collector_Api(): | ||
11 | - def __init__(self): | ||
12 | - self.open_api=Open_Api() | ||
13 | - self.engine_bot=self.open_api.engine_bot | ||
14 | - self.set_variable() | ||
15 | - | ||
16 | - # 변수 설정 | ||
17 | - def set_variable(self): | ||
18 | - self.open_api.use="collector" | ||
19 | - self.stock_info=Stock_Info(config.real_bot_name,config.real_dailyInfo_name,config.real_stockInfo_name) | ||
20 | - self.daily_info=Daily_Info() | ||
21 | - | ||
22 | - def code_update_check(self): | ||
23 | - query="select code_update,balance_to_db,posses_stocks,today_profit,contract_check,db_to_daily_info," \ | ||
24 | - "today_buy_list,stock_info,min_info,daily_info from setting_data" | ||
25 | - result=self.engine_bot.execute(query).fetchall() | ||
26 | - | ||
27 | - today=self.open_api.today | ||
28 | - | ||
29 | - # 오늘 날짜에 종목리스트가 업데이트 되지 않았다면 업데이트를 실행 | ||
30 | - if result[0][0]!=today: | ||
31 | - self.open_api.get_balance() | ||
32 | - self.get_code_list() | ||
33 | - | ||
34 | - # 계좌정보 업데이트 | ||
35 | - if result[0][1]!=today or result[0][2]!=today: | ||
36 | - self.check_balance() | ||
37 | - self.open_api.set_per_invest() | ||
38 | - | ||
39 | - # 현재 보유종목 테이블 업데이트 | ||
40 | - if result[0][2]!=today: | ||
41 | - self.open_api.get_posses_item() | ||
42 | - self.open_api.setting_data_posses_stock() | ||
43 | - | ||
44 | - # 수익률 테이블 업데이트 | ||
45 | - if result[0][3]!=today: | ||
46 | - self.update_today_profit_list() | ||
47 | - | ||
48 | - # stock_info 테이블 업데이트 | ||
49 | - if result[0][7]!=today: | ||
50 | - self.check_stock_info() | ||
51 | - | ||
52 | - if result[0][9]!=today: | ||
53 | - self.check_daily_info() | ||
54 | - | ||
55 | - if result[0][4]!=today: | ||
56 | - self.open_api.check_contract() | ||
57 | - self.open_api.final_check_contract() | ||
58 | - | ||
59 | - if result[0][6]!=today: | ||
60 | - self.realtime_daily_info_check() | ||
61 | - | ||
62 | - | ||
63 | - # 코스피, 코스닥 리스트 확인 및 데이터베이스 업데이트 | ||
64 | - def get_code_list(self): | ||
65 | - self.stock_info.get_item_kospi() | ||
66 | - self.stock_info.get_item_kosdaq() | ||
67 | - | ||
68 | - stock_data=OrderedDict( | ||
69 | - kospi=self.stock_info.kospi_list, | ||
70 | - kosdaq=self.stock_info.kosdaq_list | ||
71 | - ) | ||
72 | - | ||
73 | - for s_type,data in stock_data.items(): | ||
74 | - stock_data[s_type]=self.create_stock_table(data,s_type) | ||
75 | - | ||
76 | - stock_all=stock_data['kospi'].append(stock_data['kosdaq'],ignore_index=True) | ||
77 | - self.create_stock_table(stock_all,"all") | ||
78 | - query="update setting_data set code_update='%s'" | ||
79 | - self.engine_bot.execute(query%(self.open_api.today)) | ||
80 | - | ||
81 | - # kospi, kosdaq 주식 종목을 저장하는 테이블 생성 | ||
82 | - def create_stock_table(self,data,type): | ||
83 | - checking=['kospi','kosdaq'] | ||
84 | - stock_df=DataFrame() | ||
85 | - stock_df['code']=data['code'] | ||
86 | - stock_list=list() | ||
87 | - # 주식 code를 이용하여 실제 kiwoom 증권에서 사용하는 주식이름으로 변경 | ||
88 | - for kind in data.itertuples(): | ||
89 | - kiwoom_name=self.open_api.dynamicCall("GetMasterCodeName(QString)",kind.code).strip() | ||
90 | - stock_list.append(kiwoom_name) | ||
91 | - stock_df['code_name']=stock_list | ||
92 | - stock_df['check_item']=0 | ||
93 | - | ||
94 | - if type in checking: | ||
95 | - stock_df=stock_df[stock_df['code_name'].map(len)>0] | ||
96 | - | ||
97 | - if type=="all": | ||
98 | - stock_df['check_stock']="0" | ||
99 | - stock_df['check_min']="0" | ||
100 | - | ||
101 | - # 데이터 타입을 설정 | ||
102 | - # code, code_name 칼럼은 Text. check_item 칼럼은 Integer | ||
103 | - dtypes=dict(zip(list(stock_df.columns),[Text]*len(stock_df.columns))) | ||
104 | - dtypes['check_item']=Integer | ||
105 | - | ||
106 | - table_name='stock_'+str(type) | ||
107 | - stock_df.to_sql(table_name,self.open_api.engine_daily,if_exists='replace',dtype=dtypes) | ||
108 | - return stock_df | ||
109 | - | ||
110 | - def check_balance(self): | ||
111 | - self.open_api.reset_opw00018_output() | ||
112 | - # 예수금 상세현황 요청 | ||
113 | - self.open_api.set_input_value("계좌번호",self.open_api.account_no) | ||
114 | - self.open_api.set_input_value("비밀번호입력매체구분",00) | ||
115 | - self.open_api.set_input_value("조회구분",1) | ||
116 | - self.open_api.comm_rq_data("opw00001_req","opw00001",0,"2000") | ||
117 | - # 계좌평가 잔고내역 요청 | ||
118 | - self.open_api.set_input_value("계좌번호",self.open_api.account_no) | ||
119 | - self.open_api.comm_rq_data("opw00018_req","opw00018",0,"2000") | ||
120 | - while self.open_api.remained_data: | ||
121 | - self.open_api.set_input_value("계좌번호",self.open_api.account_no) | ||
122 | - self.open_api.comm_rq_data("opw00018_req","opw00018",2,"2000") | ||
123 | - # 일자별 실현손익 요청 | ||
124 | - self.open_api.set_input_value("계좌번호",self.open_api.account_no) | ||
125 | - self.open_api.set_input_value("시작일자","20170101") | ||
126 | - self.open_api.set_input_value("종료일자",self.open_api.today) | ||
127 | - self.open_api.comm_rq_data("opt10074_req","opt10074",0,"0329") | ||
128 | - while self.open_api.remained_data: | ||
129 | - self.open_api.set_input_value("계좌번호", self.open_api.account_no) | ||
130 | - self.open_api.set_input_value("시작일자", "20170101") | ||
131 | - self.open_api.set_input_value("종료일자", self.open_api.today) | ||
132 | - self.open_api.set_input_value("구분","0") | ||
133 | - self.open_api.comm_rq_data("opt10074_req", "opt10074", 2, "0329") | ||
134 | - | ||
135 | - self.create_balance_table() | ||
136 | - | ||
137 | - # balance_data 테이블 생성 | ||
138 | - def create_balance_table(self): | ||
139 | - self.total_invest=int(self.open_api.deposit)+int(self.open_api.total_purchase) | ||
140 | - balance_data={'id':[],'date':[],'total_asset':[],'today_profit':[],"total_profit":[], | ||
141 | - 'total_invest':[],'deposit':[],'total_purchase':[],'total_evaluation':[],'today_invest':[], | ||
142 | - 'today_rate':[],'estimated_asset':[]} | ||
143 | - | ||
144 | - balance_cols=['date','today_earning_rate','total_asset','deposit', | ||
145 | - 'today_profit','total_profit','today_invest','total_invest', | ||
146 | - 'total_purchase','today_evaluation','today_sell_count', | ||
147 | - 'today_rate','estimated_asset','sell_point','per_invest','limit_money', | ||
148 | - 'today_buy_count','today_sell_count','total_posses_count','today_buy_price','today_sell_price' | ||
149 | - ] | ||
150 | - | ||
151 | - balance=DataFrame(balance_data,columns=balance_cols,index=balance_data['id']) | ||
152 | - | ||
153 | - balance.loc[0,'date']=self.open_api.today | ||
154 | - balance.loc[0,'today_profit']=self.open_api.today_profit | ||
155 | - balance.loc[0,'total_profit']=self.open_api.total_profit | ||
156 | - balance.loc[0,'total_invest']=self.open_api.total_invest | ||
157 | - balance.loc[0,'deposit']=self.open_api.deposit | ||
158 | - balance.loc[0,'total_purchase']=self.open_api.total_purchase | ||
159 | - balance.loc[0,'total_evaluation']=self.open_api.total_evaluated_price | ||
160 | - balance.loc[0,'today_invest']=self.open_api.total_valuation | ||
161 | - balance.loc[0,'today_rate']=float(self.open_api.earning_rate/self.open_api.mod_classify) | ||
162 | - balance.loc[0,'estimate_asset']=self.open_api.estimated_deposit | ||
163 | - balance.loc[0,'sell_point']=self.open_api.simul_api.sell_point | ||
164 | - balance.loc[0,'per_invest']=self.open_api.per_invest | ||
165 | - balance.loc[0,'limit_money']=self.open_api.simul_api.limit_money | ||
166 | - | ||
167 | - # balance_data 테이블 생성 | ||
168 | - balance.to_sql('balance_data', self.engine_bot, if_exists='append') | ||
169 | - | ||
170 | - query = "select date from balance_data" | ||
171 | - rows = self.engine_bot.execute(query).fetchall() | ||
172 | - | ||
173 | - for i in range(len(rows)): | ||
174 | - # today_earning_rate | ||
175 | - query = "update balance_data " \ | ||
176 | - "set " \ | ||
177 | - "today_earning_rate =round(today_profit / total_invest * '%s',2) WHERE date='%s'" | ||
178 | - self.engine_bot.execute(query % (100, rows[i][0])) | ||
179 | - # today_buy_count | ||
180 | - query = "UPDATE balance_data " \ | ||
181 | - "SET " \ | ||
182 | - "today_buy_count=" \ | ||
183 | - "(select count(*) " \ | ||
184 | - "from " \ | ||
185 | - "(select code from transaction_history where buy_date like '%s' group by code )) " \ | ||
186 | - "WHERE date='%s'" | ||
187 | - self.engine_bot.execute(query % (rows[i][0] + "%%", rows[i][0])) | ||
188 | - # today_sell_count | ||
189 | - query="UPDATE balance_data " \ | ||
190 | - "SET " \ | ||
191 | - "today_sell_count=" \ | ||
192 | - "(select count(*) " \ | ||
193 | - "from " \ | ||
194 | - "(select code from transaction_history" \ | ||
195 | - "where buy_date like '%s' and sell_date is not null group by code) temp) " \ | ||
196 | - "WHERE date='%s'" | ||
197 | - self.engine_bot.execute(query % (rows[i][0] + "%%", rows[i][0])) | ||
198 | - # today_sell_price | ||
199 | - query="UPDATE balance_data " \ | ||
200 | - "SET" \ | ||
201 | - "today_sell_price=" \ | ||
202 | - "(select sum(*) " \ | ||
203 | - "from " \ | ||
204 | - "(select sell_price from transaction_history " \ | ||
205 | - "where sell_date like '%s')" \ | ||
206 | - "where date='%s'" | ||
207 | - self.engine_bot.execute(query%(rows[i][0])+"%%",rows[i][0]) | ||
208 | - # today_buy_price | ||
209 | - query="UPDATE balance_data " \ | ||
210 | - "SET" \ | ||
211 | - "today_sell_price=" \ | ||
212 | - "(select sum(*) " \ | ||
213 | - "from " \ | ||
214 | - "(select purchase_price from transaction_history " \ | ||
215 | - "where sell_date like '%s')" \ | ||
216 | - "where date='%s'" | ||
217 | - self.engine_bot.execute(query%(rows[i][0])+"%%",rows[i][0]) | ||
218 | - # total_posses_count | ||
219 | - query="UPDATE balance_data " \ | ||
220 | - "SET" \ | ||
221 | - "total_posses_count=" \ | ||
222 | - "(select count(*) " \ | ||
223 | - "from" \ | ||
224 | - "transaction_history where sell_date is Null)" \ | ||
225 | - "where date='%s'" | ||
226 | - self.engine_bot.execute(query%(rows[i][0])) | ||
227 | - | ||
228 | - sql = "UPDATE setting_data SET balance_to_db='%s' limit 1" | ||
229 | - self.engine_bot.execute(sql % (self.open_api.today)) | ||
230 | - | ||
231 | - def is_table_exist(self,db_name,table_name): | ||
232 | - query="select 1 from information_schema.tables where table_schema='{}' and table_name='{}'" | ||
233 | - result=self.open_api.engine_minute.execute(query.format(db_name,table_name)).fetchall() | ||
234 | - if len(result)==1: | ||
235 | - return True | ||
236 | - else: | ||
237 | - return False | ||
238 | - | ||
239 | - def update_today_profit_list(self): | ||
240 | - self.open_api.reset_opt10073_output() | ||
241 | - | ||
242 | - self.open_api.set_input_value("계좌번호",self.open_api.account_no) | ||
243 | - self.open_api.set_input_value("시작일자",self.open_api.today) | ||
244 | - self.open_api.set_input_value("종료일자",self.open_api.today) | ||
245 | - self.open_api.comm_rq_data("opt10073_req","opt10073",0,"0328") | ||
246 | - | ||
247 | - while self.open_api.remained_data: | ||
248 | - self.open_api.set_input_value("계좌번호",self.open_api.account_no) | ||
249 | - self.open_api.comm_rq_data("opt10073_req","opt10073",2,"0328") | ||
250 | - | ||
251 | - today_profit_item_temp = {'date': [], 'code': [], 'code_name': [], 'amount': [], 'today_profit': [], | ||
252 | - 'earning_rate': []} | ||
253 | - | ||
254 | - today_profit_item = DataFrame(today_profit_item_temp, | ||
255 | - columns=['date', 'code', 'code_name', 'amount', 'today_profit', | ||
256 | - 'earning_rate']) | ||
257 | - | ||
258 | - item_count = len(self.open_api.opt10073_output['multi']) | ||
259 | - for i in range(item_count): | ||
260 | - row = self.open_api.opt10073_output['multi'][i] | ||
261 | - today_profit_item.loc[i, 'date'] = row[0] | ||
262 | - today_profit_item.loc[i, 'code'] = row[1] | ||
263 | - today_profit_item.loc[i, 'code_name'] = row[2] | ||
264 | - today_profit_item.loc[i, 'amount'] = int(row[3]) | ||
265 | - today_profit_item.loc[i, 'today_profit'] = float(row[4]) | ||
266 | - today_profit_item.loc[i, 'earning_rate'] = float(row[5]) | ||
267 | - | ||
268 | - if len(today_profit_item) > 0: | ||
269 | - today_profit_item.to_sql('today_profit_list', self.engine_bot, if_exists='append') | ||
270 | - query = "UPDATE setting_data SET today_profit='%s' limit 1" | ||
271 | - self.engine_bot.execute(query % (self.open_api.today)) | ||
272 | - | ||
273 | - def check_stock_info(self): | ||
274 | - self.update_daily_info() | ||
275 | - query="update setting_data set daily_info='%s'" | ||
276 | - self.engine_bot.execute(query%(self.open_api.today)) | ||
277 | - | ||
278 | - def update_daily_info(self): | ||
279 | - query="select code,code_name,check_stock from stock_all" | ||
280 | - code_list=self.open_api.engine_daily.execute(query).fetchall() | ||
281 | - num=len(code_list) | ||
282 | - query="update stock_all set check_stock='%s' where code='%s'" | ||
283 | - for i in range(num): | ||
284 | - if int(code_list[i][2] in (1,3)): | ||
285 | - continue | ||
286 | - | ||
287 | - code=code_list[i][0] | ||
288 | - code_name=code_list[i][1] | ||
289 | - | ||
290 | - check_item_sort=self.set_stock_info_table(code,code_name) | ||
291 | - | ||
292 | - self.open_api.engine_daily.execute(query%(check_item_sort,code)) | ||
293 | - | ||
294 | - # stock_info 데이터베이스에 테이블 생성 및 추가 | ||
295 | - def set_stock_info_table(self,code,code_name): | ||
296 | - df=self.open_api.get_date_data(code,code_name,self.open_api.today) | ||
297 | - | ||
298 | - df=DataFrame(df, | ||
299 | - columns=['date', 'check_item', 'code', 'code_name', 'd1_diff_rate', | ||
300 | - 'close', 'open', 'high','low','volume', | ||
301 | - 'clo5', 'clo10', 'clo20', 'clo60','clo120', | ||
302 | - 'pre_clo5', 'pre_clo10', 'pre_clo20', 'pre_clo60','pre_clo120', | ||
303 | - 'vol5', 'vol10', 'vol20', 'vol60','vol120']) | ||
304 | - | ||
305 | - df=df.sort_values(by=['date'],ascending=True) | ||
306 | - | ||
307 | - df['code']=code | ||
308 | - df['code_name']=code_name | ||
309 | - df['d1_diff_rate']=float((df['close']-df['close'].shift(1))/df['close'].shift(1)*100) | ||
310 | - | ||
311 | - df['clo5']=df['close'].rolling(window=5).mean() | ||
312 | - df['clo10']=df['close'].rolling(window=10).mean() | ||
313 | - df['clo20']=df['close'].rolling(window=20).mean() | ||
314 | - df['clo60']=df['close'].rolling(window=60).mean() | ||
315 | - df['clo120']=df['close'].rolling(window=120).mean() | ||
316 | - | ||
317 | - df['pre_col5']=df['clo5'].shift(1) | ||
318 | - df['pre_col10']=df['clo10'].shift(1) | ||
319 | - df['pre_col20']=df['clo20'].shift(1) | ||
320 | - df['pre_col60']=df['clo60'].shift(1) | ||
321 | - df['pre_col120']=df['clo120'].shift(1) | ||
322 | - | ||
323 | - df['vlo5']=df['volume'].rolling(window=5).mean() | ||
324 | - df['vlo10']=df['volume'].rolling(window=10).mean() | ||
325 | - df['vlo20']=df['volume'].rolling(window=20).mean() | ||
326 | - df['vlo60']=df['volume'].rolling(window=60).mean() | ||
327 | - df['vlo120']=df['volume'].rolling(window=120).mean() | ||
328 | - | ||
329 | - # 이미 테이블이 존재한다면 저장된 가장 최신의 날짜 이후의 데이터만 저장 | ||
330 | - if self.engine_bot.dialect.has_table(self.open_api.engine_stock,code_name): | ||
331 | - df=df[df.date>self.open_api.get_latest_date_from_stock_info(code_name)] | ||
332 | - | ||
333 | - df[['date', 'check_item', 'code', 'code_name', 'd1_diff_rate', | ||
334 | - 'close', 'open', 'high','low','volume', | ||
335 | - 'clo5', 'clo10', 'clo20', 'clo60','clo120', | ||
336 | - 'pre_clo5', 'pre_clo10', 'pre_clo20', 'pre_clo60','yes_clo120', | ||
337 | - 'vol5', 'vol10', 'vol20', 'vol60','vol120']]=\ | ||
338 | - df[['date', 'check_item', 'code', 'code_name', 'd1_diff_rate', | ||
339 | - 'close', 'open', 'high','low','volume', | ||
340 | - 'clo5', 'clo10', 'clo20', 'clo60','clo120', | ||
341 | - 'pre_clo5', 'pre_clo10', 'pre_clo20', 'pre_clo60','yes_clo120', | ||
342 | - 'vol5', 'vol10', 'vol20', 'vol60','vol120']].fillna(0).astype(int) | ||
343 | - | ||
344 | - df.to_sql(name=code_name,con=self.open_api.engine_stock,if_exists='append') | ||
345 | - | ||
346 | - check_item_sort = 1 | ||
347 | - return check_item_sort | ||
348 | - | ||
349 | - def check_daily_info(self): | ||
350 | - self.daily_info.create_daily_table() | ||
351 | - query="update setting_data set daily_info='%s'" | ||
352 | - self.engine_bot.execute(query%(self.open_api.today)) | ||
353 | - | ||
354 | - def realtime_daily_info_check(self): | ||
355 | - if self.open_api.simul_api.is_date_exist(self.open_api.today): | ||
356 | - self.open_api.simul_api.get_date_for_simul() | ||
357 | - self.open_api.simul_api.choose_to_buy_list(self.open_api.today,self.open_api.today,len(self.open_api.simul_api.date_rows)) | ||
358 | - | ||
359 | - | ||
360 | - | ||
361 | - | ||
362 | - | ||
363 | - if self.open_api.sf.is_date_exist(self.open_api.today): | ||
364 | - logger.debug("daily_buy_list DB에 {} 테이블이 있습니다. jackbot DB에 realtime_daily_buy_list 테이블을 생성합니다".format(self.open_api.today)) | ||
365 | - | ||
366 | - self.open_api.sf.get_date_for_simul() | ||
367 | - # 첫 번째 파라미터는 여기서는 의미가 없다. | ||
368 | - # 두 번째 파라미터에 오늘 일자를 넣는 이유는 매수를 하는 시점인 내일 기준으로 date_rows_yesterday가 오늘 이기 때문 | ||
369 | - 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)) | ||
370 | - | ||
371 | - | ||
372 | - # all_item_db에서 open, clo5~120, volume 등을 오늘 일자 데이터로 업데이트 한다. | ||
373 | - self.open_api.sf.update_all_db_by_date(self.open_api.today) | ||
374 | - self.open_api.rate_check() | ||
375 | - # realtime_daily_buy_list(매수 리스트) 테이블 세팅을 완료 했으면 아래 쿼리를 통해 setting_data의 today_buy_list에 오늘 날짜를 찍는다. | ||
376 | - sql = "UPDATE setting_data SET today_buy_list='%s' limit 1" | ||
377 | - self.engine_JB.execute(sql % (self.open_api.today)) | ||
378 | - else: | ||
379 | - logger.debug( | ||
380 | - """daily_buy_list DB에 {} 테이블이 없습니다. jackbot DB에 realtime_daily_buy_list 테이블을 생성 할 수 없습니다. | ||
381 | - realtime_daily_buy_list는 daily_buy_list DB 안에 오늘 날짜 테이블이 만들어져야 생성이 됩니다. | ||
382 | - realtime_daily_buy_list 테이블을 생성할 수 없는 이유는 아래와 같습니다. | ||
383 | - 1. 장이 열리지 않은 날 혹은 15시 30분 ~ 23시 59분 사이에 콜렉터를 돌리지 않은 경우 | ||
384 | - 2. 콜렉터를 오늘 날짜 까지 돌리지 않아 daily_buy_list의 오늘 날짜 테이블이 없는 경우 | ||
385 | - """.format(self.open_api.today)) | ||
386 | - | ||
387 | - | ||
388 | -app=QApplication(sys.argv) | ||
389 | -c=Collector_Api() | ||
390 | -c.get_code_list() | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
proj/library/collector_api_pre.py
deleted
100644 → 0
1 | -from sqlalchemy import * | ||
2 | - | ||
3 | -from open_api import * | ||
4 | -from daily_info import * | ||
5 | -from stock_info import * | ||
6 | -import config | ||
7 | - | ||
8 | -class CollectorApi(): | ||
9 | - def __init__(self): | ||
10 | - self.open_api=OpenApi() | ||
11 | - self.engine_bot=self.open_api.engine_bot | ||
12 | - | ||
13 | - def set_variable(self): | ||
14 | - self.open_api.sort="collector" | ||
15 | - self.stock_info=StockInfo(config.real_bot,config.real_stockInfo,config.real_dailyInofo) | ||
16 | - self.daily_info=DailyInfo() | ||
17 | - | ||
18 | - def update_code(self): | ||
19 | - print("update code") | ||
20 | - query = "select code_update,jango_data_db_check, possessed_item, today_profit, final_chegyul_check, " \ | ||
21 | - "db_to_buy_list,today_buy_list, daily_crawler , min_crawler, daily_buy_list " \ | ||
22 | - "from setting_data limit 1" | ||
23 | - result=self.engine_bot.execute(query).fetchall() | ||
24 | - | ||
25 | - print(result) | ||
26 | - | ||
27 | - if result[0][0]!=self.open_api.today(): | ||
28 | - self.open_api.check_balance() | ||
29 | - self.get_code_list() | ||
30 | - | ||
31 | - | ||
32 | - def set_db_minute_info(self): | ||
33 | - print("Make Minute Info Database") | ||
34 | - query="select code,code_name from stock_all" | ||
35 | - target=self.open_api.engine_dInfo.execute(query).fetchall() | ||
36 | - print(target) | ||
37 | - | ||
38 | -app = QApplication(sys.argv) | ||
39 | -c=CollectorApi() | ||
40 | -c.update_code() | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -6,9 +6,10 @@ import datetime | ... | @@ -6,9 +6,10 @@ import datetime |
6 | from sqlalchemy import * | 6 | from sqlalchemy import * |
7 | from collections import defaultdict | 7 | from collections import defaultdict |
8 | from pandas import DataFrame | 8 | from pandas import DataFrame |
9 | +import re | ||
9 | 10 | ||
10 | from Logger import * | 11 | from Logger import * |
11 | -import config | 12 | +import cf |
12 | from Simulator_Api import * | 13 | from Simulator_Api import * |
13 | 14 | ||
14 | pymysql.install_as_MySQLdb() | 15 | pymysql.install_as_MySQLdb() |
... | @@ -21,7 +22,7 @@ class Open_Api(QAxWidget): | ... | @@ -21,7 +22,7 @@ class Open_Api(QAxWidget): |
21 | self.login_event_loop=QEventLoop() | 22 | self.login_event_loop=QEventLoop() |
22 | self.tr_event_loop=QEventLoop() | 23 | self.tr_event_loop=QEventLoop() |
23 | 24 | ||
24 | - # open_api 호출 횟수를 저장f | 25 | + # open_api 호출 횟수를 저장 |
25 | self.rq_count=0 | 26 | self.rq_count=0 |
26 | self.set_date() | 27 | self.set_date() |
27 | self.tr_loop_count=0 | 28 | self.tr_loop_count=0 |
... | @@ -38,13 +39,14 @@ class Open_Api(QAxWidget): | ... | @@ -38,13 +39,14 @@ class Open_Api(QAxWidget): |
38 | # 변수 설정 | 39 | # 변수 설정 |
39 | self.set_variable() | 40 | self.set_variable() |
40 | 41 | ||
41 | - self.simul_api=Simulator_Api(self.simul_num,"real",self.db_name) | 42 | + self.sf=Simulator_Func(self.simul_num,"real",self.db_name) |
42 | logger.debug("알고리즘 번호 : %s",self.simul_api.simul_num) | 43 | logger.debug("알고리즘 번호 : %s",self.simul_api.simul_num) |
43 | logger.debug("매수 알고리즘 번호 : %s",self.simul_api.buy_algorithm) | 44 | logger.debug("매수 알고리즘 번호 : %s",self.simul_api.buy_algorithm) |
44 | logger.debug("매도 알고리즘 번호 : %s",self.simul_api.sell_algorithm) | 45 | logger.debug("매도 알고리즘 번호 : %s",self.simul_api.sell_algorithm) |
45 | 46 | ||
47 | + # 시뮬레이션 데이터베이스에 setting_data 테이블이 존재하지 않는다면 생성 | ||
46 | if not self.simul_api.is_table_exist(self.db_name,"setting_data"): | 48 | if not self.simul_api.is_table_exist(self.db_name,"setting_data"): |
47 | - self.create_setting_data() | 49 | + self.init_setting_data() |
48 | 50 | ||
49 | self.set_simul_variable() | 51 | self.set_simul_variable() |
50 | self.ohlcv=defaultdict(list) | 52 | self.ohlcv=defaultdict(list) |
... | @@ -88,6 +90,28 @@ class Open_Api(QAxWidget): | ... | @@ -88,6 +90,28 @@ class Open_Api(QAxWidget): |
88 | except Exception as e: | 90 | except Exception as e: |
89 | logger.critical(e) | 91 | logger.critical(e) |
90 | 92 | ||
93 | + # 사용자의 계좌정보 저장 및 출력 | ||
94 | + def get_account_info(self): | ||
95 | + account_no=self.get_login_info("ACCNO") | ||
96 | + self.account_no=account_no.split(";")[0] | ||
97 | + logger.debug(self.account_no) | ||
98 | + | ||
99 | + # 원하는 사용자 정보 반환 | ||
100 | + # param : tag - ACCNO - 보유계좌리스트 | ||
101 | + # ACCOUNT_CNT - 보유계좌 수 | ||
102 | + # USER_ID - 사용자 ID | ||
103 | + # USER_NAME - 사용자 이름 | ||
104 | + # KEY_BSECGB - 키보드 보안 해제 여부 (0 : 정상, 1: 해지) | ||
105 | + # FIREW_SECGB - 방화벽 설정여부 (0 : 미설정, 1: 설정, 2 : 해지) | ||
106 | + # GetServerGubun - 접속서버 구분 (1 : 모의투자, 나머지 : 실서버) | ||
107 | + # return : tag를 통해 요청한 정보(ret) 반환 | ||
108 | + def get_login_info(self,tag): | ||
109 | + try: | ||
110 | + ret=self.dynamicCall("GetLoginInfo(QString)",tag) | ||
111 | + return ret | ||
112 | + except Exception as e: | ||
113 | + logger.critical(e) | ||
114 | + | ||
91 | # 수동 로그인설정인 경우 로그인창을 출력해서 로그인을 시도 | 115 | # 수동 로그인설정인 경우 로그인창을 출력해서 로그인을 시도 |
92 | # 자동로그인 설정인 경우 로그인창 출력없이 로그인을 시도 | 116 | # 자동로그인 설정인 경우 로그인창 출력없이 로그인을 시도 |
93 | def comm_connect(self): | 117 | def comm_connect(self): |
... | @@ -105,7 +129,7 @@ class Open_Api(QAxWidget): | ... | @@ -105,7 +129,7 @@ class Open_Api(QAxWidget): |
105 | # sPrevNext : 다음 페이지가 있는지 여부. "2" : 다음페이지 존재, "0" or "" : 다음페이지 없음 | 129 | # sPrevNext : 다음 페이지가 있는지 여부. "2" : 다음페이지 존재, "0" or "" : 다음페이지 없음 |
106 | def _receive_tr_data(self,sScrNo,sRQName,sTrCode,sRecordName,sPrevNext): | 130 | def _receive_tr_data(self,sScrNo,sRQName,sTrCode,sRecordName,sPrevNext): |
107 | if sPrevNext=='2': | 131 | if sPrevNext=='2': |
108 | - self.remained_data=True | 132 | + self.remained_data=True # 다음 페이지가 존재하는지 확인하는 변수 |
109 | else: | 133 | else: |
110 | self.remained_data=False | 134 | self.remained_data=False |
111 | 135 | ||
... | @@ -161,14 +185,133 @@ class Open_Api(QAxWidget): | ... | @@ -161,14 +185,133 @@ class Open_Api(QAxWidget): |
161 | # GetChejanData()함수를 이용해서 상세한 정보를 얻을 수 있다 | 185 | # GetChejanData()함수를 이용해서 상세한 정보를 얻을 수 있다 |
162 | # param : sGubun - 체결구분. 접수와 체결시 '0'값, 국내주식 잔고전달은 '1'값, 파생잔고 전달은 '4' | 186 | # param : sGubun - 체결구분. 접수와 체결시 '0'값, 국내주식 잔고전달은 '1'값, 파생잔고 전달은 '4' |
163 | def _receive_chejan_data(self,sGubun,nItemCnt,sFIdList): | 187 | def _receive_chejan_data(self,sGubun,nItemCnt,sFIdList): |
164 | - # 현재 체결 진행 중인 코드 | 188 | + # 체결구분. 접수와 체결 |
165 | - print("주분번호 : ",self.get_chejan_data(9023)) | 189 | + if sGubun=="0": |
166 | - print("종목명 : ",self.get_chejan_data(302)) | 190 | + code=self.get_chejan_data(9001) # 현재 체결 진행 중인 코드 |
167 | - print("주문수량 : ",self.get_chejan_data(900)) | 191 | + code=re.compile(r'\d{6}') # 종목코드는 연속된 숫자 6자리 |
168 | - print("주문가격 : ",self.get_chejan_data(901)) | 192 | + order_num=self.get_chejan_data(9203) # 주문번호 |
193 | + | ||
194 | + # 주문번호가 존재하지 않는다면 주문실패 | ||
195 | + if not order_num: | ||
196 | + logger.debug(code,"주문 실패") | ||
197 | + return | ||
198 | + | ||
199 | + chegyul_fail_amount=self.get_chejan_data(902) # 미체결 수량 | ||
200 | + order_gubun=self.get_chejan_data(905) # 주문구분 | ||
201 | + purchase_price=self.get_chejan_data(10) # 체결가 | ||
202 | + | ||
203 | + # 종목코드가 존재한다면 | ||
204 | + if code: | ||
205 | + if chegyul_fail_amount!="": | ||
206 | + # 해당 종목을 보유하고 있지 않은 경우 | ||
207 | + if not self.is_exist_possess_item_in_transaction(code): | ||
208 | + # 해당 종목의 체결 실패 내역이 없다면 | ||
209 | + # transaction 테이블에 업데이트. 정상 체결 시 chegyul_check=0 | ||
210 | + if chegyul_fail_amount=="0": | ||
211 | + logger.debug(code, "체결 완료") | ||
212 | + self.db_to_transaction(order_num,code,0,purchase_price,0) | ||
213 | + # 체결 실패 내역이 존재한다면 | ||
214 | + # transaction 테이블에 업데이트. 미체결 시 chegyul_check=1 | ||
215 | + else: | ||
216 | + logger.debug(code,"미체결") | ||
217 | + self.db_to_transaction(order_num,code,1,purchase_price,0) | ||
218 | + | ||
219 | + # 매수하는 경우 | ||
220 | + elif order_gubun=="+매수": | ||
221 | + if chegyul_fail_amount!="0" and self.check_stock_chegyul(code): | ||
222 | + logger.debug("미체결. 매수 진행중!") | ||
223 | + pass | ||
224 | + elif chegyul_fail_amount=="0" and self.check_stock_chegyul(code): | ||
225 | + logger.debug("매수 완료") | ||
226 | + self.check_end_invest(code) | ||
227 | + else: | ||
228 | + pass | ||
229 | + | ||
230 | + # 매도하는 경우 | ||
231 | + elif order_gubun=="-매도": | ||
232 | + if chegyul_fail_amount=="0": | ||
233 | + logger.debug("전량 매도") | ||
234 | + self.check_end_sell(code) | ||
235 | + else: | ||
236 | + logger.debug("부분 매도") | ||
237 | + self.check_sell_chegyul_fail(code) | ||
238 | + | ||
239 | + else: | ||
240 | + logger.debug("Invalid order_gubun") | ||
241 | + else: | ||
242 | + logger.debug("Invalid chegyul_fail_amount value") | ||
243 | + else: | ||
244 | + logger.debug("can't receive code value") | ||
245 | + | ||
246 | + # 국내주식 잔고전달 | ||
247 | + elif sGubun=="1": | ||
248 | + chegyul_fail_amount=self.get_chejan_data(902) | ||
249 | + logger.debug("미체결 수량",chegyul_fail_amount) | ||
250 | + | ||
251 | + else: | ||
252 | + logger.debug("Invlid _receive_chejan_data") | ||
253 | + | ||
254 | + # 특정 종목을 보유하고 있는지 확인하는 함수 | ||
255 | + def is_exist_possess_item_in_transaction(self,code): | ||
256 | + query = "select code from transaction " \ | ||
257 | + "where code='%s' and (sell_date ='%s' or sell_date='%s') ORDER BY buy_date desc LIMIT 1" | ||
258 | + result = self.engine_bot.execute(query % (code, 0, "")).fetchall() | ||
259 | + if len(result) != 0: | ||
260 | + return True | ||
261 | + else: | ||
262 | + return False | ||
263 | + | ||
264 | + # 해당 종목이 체결되었는지 확인하는 함수 | ||
265 | + def check_stock_chegyul(self,code): | ||
266 | + query = "SELECT chegyul_check FROM transaction " \ | ||
267 | + "where code='%s' and sell_date = '%s' ORDER BY buy_date desc LIMIT 1" | ||
268 | + result = self.engine_bot.execute(query % (code, 0)).fetchall() | ||
269 | + if result[0][0] == 1: | ||
270 | + return True | ||
271 | + else: | ||
272 | + return False | ||
273 | + | ||
274 | + # 체결 완료 시 transaction 테이블의 chegyul_check항목을 업데이트 | ||
275 | + def check_end_invest(self,code): | ||
276 | + query = "UPDATE transaction " \ | ||
277 | + "SET " \ | ||
278 | + "chegyul_check='%s' WHERE code='%s' and sell_date = '%s' ORDER BY buy_date desc LIMIT 1" | ||
279 | + self.engine_bot.execute(query % (0, code, 0)) | ||
280 | + | ||
281 | + # 매도 완료 후 DB 업데이트트 | ||
282 | + def check_sell_end(self,code): | ||
283 | + query="select valuation_profit,rate,item_total_urchase,present_price" \ | ||
284 | + "from possessed_item" \ | ||
285 | + "where code={} limit 1" | ||
286 | + get_list=self.engine_bot.execute(query.format(code)).fetchall() | ||
287 | + | ||
288 | + # 매도 완료 종목에 대해 DB 업데이트 | ||
289 | + if get_list: | ||
290 | + item = get_list[0] | ||
291 | + query = f"""UPDATE transaction | ||
292 | + SET | ||
293 | + item_total_purchase = {item.item_total_purchase}, chegyul_check = 0, | ||
294 | + sell_date = '{self.today_detail}', valuation_profit = {item.valuation_profit}, | ||
295 | + sell_rate = {item.rate}, sell_price = {item.present_price} | ||
296 | + WHERE code = '{code}' and sell_date = '0' ORDER BY buy_date desc LIMIT 1""" | ||
297 | + self.engine_bot.execute(query) | ||
298 | + | ||
299 | + # 매도 완료 후 possessd_item 테이블에서 해당 종목 삭제 | ||
300 | + self.engine_bot.execute(f"DELETE FROM possessed_item WHERE code = '{code}'") | ||
301 | + else: | ||
302 | + logger.debug("보유 종목이 없습니다.") | ||
303 | + | ||
304 | + # 매도 체결 실패시 DB 업데이트 | ||
305 | + def check_sell_chegyul_fail(self,code): | ||
306 | + query = "UPDATE transaction SET chegyul_check='%s' " \ | ||
307 | + "WHERE code='%s' and sell_date = '%s' ORDER BY buy_date desc LIMIT 1" | ||
308 | + self.engine_bot.execute(query % (1, code, 0)) | ||
169 | 309 | ||
170 | # OnReceiveChejan()이벤트가 호출될때 체결정보나 잔고정보를 얻어오는 함수 | 310 | # OnReceiveChejan()이벤트가 호출될때 체결정보나 잔고정보를 얻어오는 함수 |
171 | # param : nFid - 실시간 타입에 포함된 FID | 311 | # param : nFid - 실시간 타입에 포함된 FID |
312 | + # FID List | ||
313 | + # (FID, 설명) : (9023, 주문번호), (302, 종목명), (900, 주문수량), (901,주문가격), (902,미체결수량), (904,원주문번호), | ||
314 | + # (905, 주문구분), (908, 주문/체결시간), (909, 체결번호), (910, 체결가), (911, 체결량), (10, 현재가/체결가/실시간종가) | ||
172 | def get_chejan_data(self,nFid): | 315 | def get_chejan_data(self,nFid): |
173 | try: | 316 | try: |
174 | ret=self.dynamicCall("GetChejanData(int)",nFid) | 317 | ret=self.dynamicCall("GetChejanData(int)",nFid) |
... | @@ -176,27 +319,15 @@ class Open_Api(QAxWidget): | ... | @@ -176,27 +319,15 @@ class Open_Api(QAxWidget): |
176 | except Exception as e: | 319 | except Exception as e: |
177 | logger.critical(e) | 320 | logger.critical(e) |
178 | 321 | ||
179 | - # 사용자의 계좌정보 저장 및 출력 | 322 | + # 거래이력(transaction)테이블에 현재 보유중인 종목이 있는지 확인하는 함수 |
180 | - def get_account_info(self): | 323 | + def is_transaction_check(self,code): |
181 | - account_no=self.get_login_info("ACCNO") | 324 | + query = "select code from transaction " \ |
182 | - self.account_no=account_no.split(";")[0] | 325 | + "where code='%s' and (sell_date ='%s' or sell_date='%s') ORDER BY buy_date desc LIMIT 1" |
183 | - logger.debug(self.account_no) | 326 | + rows = self.engine_bot.execute(query % (code, 0, "")).fetchall() |
184 | - | 327 | + if len(rows) != 0: |
185 | - # 원하는 사용자 정보 반환 | 328 | + return True |
186 | - # param : tag - ACCNO - 보유계좌리스트 | 329 | + else: |
187 | - # ACCOUNT_CNT - 보유계좌 수 | 330 | + return False |
188 | - # USER_ID - 사용자 ID | ||
189 | - # USER_NAME - 사용자 이름 | ||
190 | - # KEY_BSECGB - 키보드 보안 해제 여부 (0 : 정상, 1: 해지) | ||
191 | - # FIREW_SECGB - 방화벽 설정여부 (0 : 미설정, 1: 설정, 2 : 해지) | ||
192 | - # GetServerGubun - 접속서버 구분 (1 : 모의투자, 나머지 : 실서버) | ||
193 | - # return : tag를 통해 요청한 정보(ret) 반환 | ||
194 | - def get_login_info(self,tag): | ||
195 | - try: | ||
196 | - ret=self.dynamicCall("GetLoginInfo(QString)",tag) | ||
197 | - return ret | ||
198 | - except Exception as e: | ||
199 | - logger.critical(e) | ||
200 | 331 | ||
201 | # 조회요청시 TR의 Input값을 지정하는 함수 | 332 | # 조회요청시 TR의 Input값을 지정하는 함수 |
202 | # param : sId - TR에 명시된 Input이름 | 333 | # param : sId - TR에 명시된 Input이름 |
... | @@ -240,55 +371,56 @@ class Open_Api(QAxWidget): | ... | @@ -240,55 +371,56 @@ class Open_Api(QAxWidget): |
240 | # 변수 설정 | 371 | # 변수 설정 |
241 | # 실전투자인지 모의투자인지 여부를 확인하고 그에 해당하는 데이터베이스를 생성하는 함수 | 372 | # 실전투자인지 모의투자인지 여부를 확인하고 그에 해당하는 데이터베이스를 생성하는 함수 |
242 | def set_variable(self): | 373 | def set_variable(self): |
243 | - self.config=config | 374 | + self.cf=cf |
375 | + self.get_today_buy_list_code=0 | ||
244 | self.reset_opw00018_output() | 376 | self.reset_opw00018_output() |
245 | 377 | ||
246 | - if self.account_no==self.config.real_account_no: | 378 | + if self.account_no==self.cf.real_account_no: |
247 | logger.debug("실전투자") | 379 | logger.debug("실전투자") |
248 | - self.simul_num=self.config.real_num | 380 | + self.simul_num=self.cf.real_num |
249 | - self.set_database(self.config.real_bot_name) | 381 | + self.set_database(cf.real_bot_name) |
250 | - self.mod_classify=100 | 382 | + self.mod_gubun=100 # 실전투자와 모의투자를 구분하는 변수 |
251 | 383 | ||
252 | - elif self.account_no==self.config.test_account_no: | 384 | + elif self.account_no==self.cf.test_account_no: |
253 | logger.debug("모의투자") | 385 | logger.debug("모의투자") |
254 | - self.simul_num=self.config.test_num | 386 | + self.simul_num=self.cf.test_num |
255 | - self.set_database(self.config.test_bot_name) | 387 | + self.set_database(cf.test_bot_name) |
256 | - self.mod_classify=1 | 388 | + self.mod_gubun=1 |
257 | 389 | ||
258 | else: | 390 | else: |
259 | logger.debug("Invalid Account Number. Check the Config.py") | 391 | logger.debug("Invalid Account Number. Check the Config.py") |
260 | exit(1) | 392 | exit(1) |
261 | 393 | ||
262 | self.is_balance_null=True | 394 | self.is_balance_null=True |
263 | - self.use=False | 395 | + self.py_gubun=False |
264 | 396 | ||
265 | # 데이터베이스 생성 및 엔진 설정 | 397 | # 데이터베이스 생성 및 엔진 설정 |
266 | def set_database(self,db_name): | 398 | def set_database(self,db_name): |
267 | self.db_name=db_name | 399 | self.db_name=db_name |
268 | conn=pymysql.connect( | 400 | conn=pymysql.connect( |
269 | - host=config.db_ip, | 401 | + host=cf.db_ip, |
270 | - port=int(config.db_port), | 402 | + port=int(cf.db_port), |
271 | - user=config.db_id, | 403 | + user=cf.db_id, |
272 | - password=config.db_pw, | 404 | + password=cf.db_pw, |
273 | - charset='utf8' | 405 | + charset='utf8mb4' |
274 | ) | 406 | ) |
275 | cursor=conn.cursor() | 407 | cursor=conn.cursor() |
276 | if not self.is_database_exist(cursor): | 408 | if not self.is_database_exist(cursor): |
277 | self.create_database(cursor) | 409 | self.create_database(cursor) |
278 | - self.engine_bot=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+ | 410 | + self.engine_bot=create_engine("mysql+pymysql://"+self.cf.db_id+":"+self.cf.db_pw+"@"+ |
279 | - self.config.db_ip + ":" + self.config.db_port+"/"+db_name,encoding='utf-8') | 411 | + self.cf.db_ip + ":" + self.cf.db_port+"/"+db_name,encoding='utf-8') |
280 | - self.create_info_database(cursor) | 412 | + self.create_basic_database(cursor) |
281 | 413 | ||
282 | conn.commit() | 414 | conn.commit() |
283 | cursor.close() | 415 | cursor.close() |
284 | conn.close() | 416 | conn.close() |
285 | 417 | ||
286 | - self.engine_daily=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+ | 418 | + self.engine_craw = create_engine("mysql+pymysql://" + cf.db_id + ":" + cf.db_pw + "@" + cf.db_ip + ":" + |
287 | - self.config.db_ip + ":" + self.config.db_port+"/daily_info",encoding='utf-8') | 419 | + cf.db_port + "/min_craw",encoding='utf-8') |
288 | - self.engine_stock=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+ | 420 | + self.engine_daily_craw = create_engine("mysql+pymysql://" + cf.db_id + ":" + cf.db_pw + "@" + cf.db_ip + ":" + |
289 | - self.config.db_ip + ":" + self.config.db_port+"/stock_info",encoding='utf-8') | 421 | + cf.db_port + "/daily_craw",encoding='utf-8') |
290 | - self.engine_minute=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+ | 422 | + self.engine_daily_buy_list = create_engine("mysql+pymysql://" + cf.db_id + ":" + cf.db_pw + "@" + cf.db_ip + ":" |
291 | - self.config.db_ip + ":" + self.config.db_port+"/minute_info",encoding='utf-8') | 423 | + + cf.db_port + "/daily_buy_list",encoding='utf-8') |
292 | 424 | ||
293 | # Bot Database가 존재하는지 확인하는 함수 | 425 | # Bot Database가 존재하는지 확인하는 함수 |
294 | def is_database_exist(self,cursor): | 426 | def is_database_exist(self,cursor): |
... | @@ -304,123 +436,183 @@ class Open_Api(QAxWidget): | ... | @@ -304,123 +436,183 @@ class Open_Api(QAxWidget): |
304 | query="create database {}" | 436 | query="create database {}" |
305 | cursor.execute(query.format(self.db_name)) | 437 | cursor.execute(query.format(self.db_name)) |
306 | 438 | ||
307 | - # information 데이터베이스가 존재하는지 확인 | 439 | + # daily_craw(종목의 날짜별 데이터), daily_buy_list(날짜별 종목 데이터), min_craw(종목의 분별 데이터) 가 존재하는지 확인하는 함수 |
308 | # 존재하지 않는다면 새로 생성 | 440 | # 존재하지 않는다면 새로 생성 |
309 | - def create_info_database(self,cursor): | 441 | + def create_basic_database(self,cursor): |
310 | - info_list=['daily_info','stock_info','minute_info'] | 442 | + check_list = ['daily_craw', 'daily_buy_list', 'min_craw'] |
311 | - query="select schema_name from information_schema.schemata" | 443 | + query = "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA" |
312 | cursor.execute(query) | 444 | cursor.execute(query) |
313 | - result=cursor.fetchall() | 445 | + result = cursor.fetchall() |
314 | - print(result) | 446 | + db_list = [n['SCHEMA_NAME'].lower() for n in result] |
315 | - exist_list=[item[0].lower() for item in result] | 447 | + create_db_query = "CREATE DATABASE {}" |
316 | - create_query="create database {}" | 448 | + has_created = False |
317 | - has_created=False | 449 | + for check_name in check_list: |
318 | - for db in info_list: | 450 | + if check_name not in db_list: |
319 | - if db not in exist_list: | 451 | + has_created = True |
320 | - has_created=True | 452 | + logger.debug(check_name,"데이터베이스 생성...") |
321 | - logger.debug(db,"Database not exist. Create the Database.") | 453 | + create_db_sql = create_db_query.format(check_name) |
322 | - cursor.execute(create_query.format(db)) | 454 | + cursor.execute(create_db_sql) |
323 | - logger.debug(db,"Creation Completed!") | ||
324 | 455 | ||
325 | if has_created and self.engine_bot.has_table('setting_data'): | 456 | if has_created and self.engine_bot.has_table('setting_data'): |
326 | - print("exist") | 457 | + self.engine_bot.execute("UPDATE setting_data SET code_update = '0';") |
327 | - self.engine_bot.execute("update setting_data set code_update='0") | 458 | + |
328 | - | 459 | + # setting_data 테이블 생성 및 초기화하는 함수 |
329 | - def create_setting_data(self): | 460 | + def init_setting_data(self): |
330 | - df_data={"limit_money":[],"per_invest":[],"max_per_invest":[],"min_per_invest":[],"set_per_invest":[], | 461 | + df_setting_data_temp = {'limit_money': [], 'invest_unit': [], 'max_invest_unit': [], |
331 | - "code_update":[],"today_finish":[],"balance_to_db":[],"posses_stocks":[],"today_profit":[], | 462 | + 'min_invest_unit': [],'set_invest_unit': [], 'code_update': [], |
332 | - "contract_check":[],"final_contract_check":[],"db_to_daily_info":[],"today_buy_list":[], | 463 | + 'today_buy_stop': [],'account_balance_db_check': [], 'possessed_item': [], |
333 | - "stock_info":[],"min_info":[],"daily_info":[]} | 464 | + 'today_profit': [],'final_chegyul_check': [],'db_to_buy_list': [], 'today_buy_list': [], |
334 | - df_setting_data=DataFrame(df_data, | 465 | + 'daily_crawler': [],'daily_buy_list': []} |
335 | - columns=['limit_money','per_invest','max_per_invest','min_per_invest','set_per_invest', | 466 | + |
336 | - 'code_update','today_finish','balance_to_db','posses_stocks','today_profit', | 467 | + df_setting_data = DataFrame(df_setting_data_temp, |
337 | - 'contract_check','final_contract_check','db_to_daily_info','today_buy_list', | 468 | + columns=['limit_money', 'invest_unit', 'max_invest_unit','min_invest_unit', |
338 | - 'stock_info','min_info','daily_info']) | 469 | + 'set_invest_unit', 'code_update', 'today_buy_stop', |
339 | - | 470 | + 'account_balance_db_check', 'possessed_item', 'today_profit', |
340 | - df_setting_data.loc[0,'limit_money']=int(0) | 471 | + 'final_chegyul_check','db_to_buy_list', 'today_buy_list', 'daily_crawler', |
341 | - df_setting_data.loc[0,'per_invest']=int(0) | 472 | + 'daily_buy_list']) |
342 | - df_setting_data.loc[0,'max_per_invest']=int(0) | 473 | + |
343 | - df_setting_data.loc[0,'min_per_invest']=int(0) | 474 | + # 칼럼 자료형 설정 |
344 | - df_setting_data.loc[0,'set_per_invest']=str(0) | 475 | + df_setting_data.loc[0, 'limit_money'] = int(0) # 잔고에 최소한으로 남겨놓을 금액 |
345 | - | 476 | + df_setting_data.loc[0, 'invest_unit'] = int(0) # 기준 투자금액 |
346 | - df_setting_data.loc[0,'code_update']=str(0) | 477 | + df_setting_data.loc[0, 'max_invest_unit'] = int(0) # 최대 투자금액 |
347 | - df_setting_data.loc[0,'today_finish']=str(0) | 478 | + df_setting_data.loc[0, 'min_invest_unit'] = int(0) # 최소 투자금액 |
348 | - df_setting_data.loc[0,'balance_to_db']=str(0) | 479 | + df_setting_data.loc[0, 'set_invest_unit'] = str(0) # 기준 투자금액 설정 날짜 |
349 | - df_setting_data.loc[0,'posses_stocks']=str(0) | 480 | + |
350 | - df_setting_data.loc[0,'today_profit']=float(0) | 481 | + df_setting_data.loc[0, 'code_update'] = str(0) # setting_data의 데이터를 업데이트 한 날짜 |
351 | - | 482 | + df_setting_data.loc[0, 'today_buy_stop'] = str(0) # 당일 구매 종료 설정 시간 |
352 | - df_setting_data.loc[0,'contract_check']=str(0) | 483 | + df_setting_data.loc[0, 'account_balance_db_check'] = str(0) # 잔고데이터 DB 업데이트 날짜 |
353 | - df_setting_data.loc[0,'final_contract_check']=str(0) | 484 | + df_setting_data.loc[0, 'possessed_item'] = str(0) # 보유종목 DB 업데이트 날짜 |
354 | - df_setting_data.loc[0,'db_to_daily_info']=str(0) | 485 | + df_setting_data.loc[0, 'today_profit'] = str(0) # 당일 수익 |
355 | - df_setting_data.loc[0,'today_buy_list']=str(0) | 486 | + |
356 | - df_setting_data.loc[0,'stock_info']=str(0) | 487 | + df_setting_data.loc[0, 'final_chegyul_check'] = str(0) # 마지막 체결 확인 |
357 | - | 488 | + df_setting_data.loc[0, 'db_to_buy_list'] = str(0) # 구매 리스트 DB 업데이트 날짜 |
358 | - df_setting_data.loc[0,'min_info']=str(0) | 489 | + df_setting_data.loc[0, 'today_buy_list'] = str(0) # 당일 구매 리스트 DB 업데이트 날짜 |
359 | - df_setting_data.loc[0,'daily_info']=str(0) | 490 | + df_setting_data.loc[0, 'daily_crawler'] = str(0) # daily_crawler(종목의 일별 데이터) 업데이트 날짜 |
360 | - | 491 | + df_setting_data.loc[0, 'min_crawler'] = str(0) # min_crawler(종목의 분별 데이터) 업데이트 날자 |
361 | - df_setting_data.to_sql("setting_data",self.engine_bot,if_exists="replace") | 492 | + df_setting_data.loc[0, 'daily_buy_list'] = str(0) # daily_buy_list(일별 종목 데이터) 업데이트 날짜 |
362 | - | 493 | + |
363 | - # 시뮬레이터에서 사용할 변수들을 설정 | 494 | + df_setting_data.to_sql('setting_data', self.engine_JB, if_exists='replace') |
495 | + | ||
496 | + # simulator_fun 에서 설정한 변수를 가져오는 함수 | ||
364 | def set_simul_variable(self): | 497 | def set_simul_variable(self): |
365 | - self.latest_date=self.simul_api.get_latest_date() | 498 | + # daily_buy_list에 저장된 가장 최신 날짜 |
366 | - if not self.simul_api.is_table_exist(self.db_name,"transaction_history"): | 499 | + self.date_rows_yesterday=self.sf.get_recent_daily_buy_list_date() |
367 | - logger.debug("create transaction_history table") | 500 | + |
368 | - self.per_invest=0 | 501 | + # AutoBot 데이터베이스에 transaction 테이블이 존재하지 않을 경우 |
369 | - self.create_transaction_history(0,0,0,0,0) | 502 | + # 테이블 생성 및 초기화 |
370 | - self.delete_item_by_code(0) | 503 | + if not self.sf.is_simul_table_exist(self.db_name,"transaction"): |
371 | - | 504 | + logger.debug("transaction 테이블을 생성합니다") |
372 | - if not self.check_per_invest(): | 505 | + self.invest_unit=0 |
373 | - self.set_per_invest() | 506 | + self.db_to_transaction(0,0,0,0,0) |
507 | + # 테이블 생성 후 초기화 | ||
508 | + self.delete_transaction_item("0") | ||
509 | + | ||
510 | + # setting_data에 invest_unit값이 없다면 설정 | ||
511 | + if not self.check_set_invest_unit(): | ||
512 | + self.set_invest_unit() | ||
513 | + # 존재한다면 해당 값을 simulator_func에 저장 | ||
374 | else: | 514 | else: |
375 | - self.per_invest=self.get_per_invest() | 515 | + self.invest_unit=self.get_invest_unit() |
376 | - self.simul_api.per_invest=self.per_invest | 516 | + self.sf.invest_unit=self.invest_unit |
377 | - | 517 | + |
378 | - # transaction_history 테이블 생성 및 column 설정 | 518 | + # transaction(거래 내역) 테이블 생성 |
379 | - def create_transaction_history(self,order_num,code,contract_check,purchase_price,rate): | 519 | + def db_to_transaction(self,order_num,code,chegyul_check,purchase_price,rate): |
380 | - logger.debug("creating transaction_history table") | 520 | + self.date_setting() |
381 | - self.set_date() | 521 | + # 거래내역 DataFrame 생성 |
382 | - self.simul_api.df_transaction_history() | 522 | + self.sf.init_df_transaction() |
383 | - self.simul_api.df_th.loc[0,'order_num']=order_num | 523 | + |
384 | - self.simul_api.df_th.loc[0,'code']=str(code) | 524 | + # dataframe에 값 할당 |
385 | - self.simul_api.df_th.loc[0,'reate']=float(rate) | 525 | + self.sf.df_transaction.loc[0, 'order_num'] = order_num # 주문번호 |
386 | - self.simul_api.df_th.loc[0,'buy_date']=self.today_time | 526 | + self.sf.df_transaction.loc[0, 'code'] = str(code) # 종목코드 |
387 | - self.simul_api.df_th.loc[0,'contract_check']=contract_check | 527 | + self.sf.df_transaction.loc[0, 'rate'] = float(rate) # 수익률 |
388 | - self.simul_api.df_th.loc[0,'per_invest']=self.per_invest | 528 | + self.sf.df_transaction.loc[0, 'buy_date'] = self.today_detail # 구매날짜 |
389 | - self.simul_api.df_th.loc[0,'purchase_price']=purchase_price | 529 | + self.sf.df_all_item.loc[0, 'chegyul_check'] = chegyul_check # 체결확인 |
390 | - | 530 | + |
391 | - self.simul_api.df_th=self.simul_api.df_th.fillna(0) | 531 | + self.sf.df_all_item.loc[0, 'invest_unit'] = self.invest_unit # 투자기준금액 |
392 | - self.simul_api.df_th.to_sql('transaction_history',self.engine_bot,if_exists='append') | 532 | + self.sf.df_all_item.loc[0, 'purchase_price'] = purchase_price # 구매금액 |
393 | - | 533 | + |
394 | - def delete_item_by_code(self,code): | 534 | + if order_num != 0: |
395 | - query="delete from transaction_history where code='%s'" | 535 | + recent_daily_buy_list_date=self.sf.get_recent_daily_buy_list_date() |
396 | - self.engine_bot.execute(query%code) | 536 | + if recent_daily_buy_list_date: |
397 | - | 537 | + # 특정 날짜, 특정 종목의 주가 데이터 |
398 | - # setting_data에 per_invest항목이 설정되어 있는지 확인하는 함수 | 538 | + df=self.sf.get_daily_buy_list_by_code(code,recent_daily_buy_list_date) |
399 | - def check_per_invest(self): | 539 | + if not df.empty: |
400 | - query="select per_invest, set_per_invest from setting_data" | 540 | + self.sf.df_transaction.loc[0, 'code_name'] = df.loc[0, 'code_name'] # 종목명 |
541 | + | ||
542 | + self.sf.df_transaction.loc[0, 'close'] = df.loc[0, 'close'] # 종가 | ||
543 | + self.sf.df_transaction.loc[0, 'open'] = df.loc[0, 'open'] # 시가 | ||
544 | + self.sf.df_transaction.loc[0, 'high'] = df.loc[0, 'high'] # 고가 | ||
545 | + self.sf.df_transaction.loc[0, 'low'] = df.loc[0, 'low'] # 저가 | ||
546 | + self.sf.df_transaction.loc[0, 'volume'] = df.loc[0, 'volume'] # 거래량 | ||
547 | + | ||
548 | + self.sf.df_transaction.loc[0,'d1_diff']=float(df.loc[0,'d1_diff']) # 전날대비 가격변동 | ||
549 | + self.sf.df_transaction.loc[0, 'd1_diff_rate'] = float(df.loc[0, 'd1_diff_rate']) # 전날대비 가격변동률 | ||
550 | + | ||
551 | + self.sf.df_transaction.loc[0, 'clo5'] = df.loc[0, 'clo5'] # 5일 이동평균선 | ||
552 | + self.sf.df_transaction.loc[0, 'clo10'] = df.loc[0, 'clo10'] # 10일 이동평균선 | ||
553 | + self.sf.df_transaction.loc[0, 'clo20'] = df.loc[0, 'clo20'] # 20일 이동평균선 | ||
554 | + self.sf.df_transaction.loc[0, 'clo60'] = df.loc[0, 'clo60'] # 60일 이동평균선 | ||
555 | + self.sf.df_transaction.loc[0, 'clo120'] = df.loc[0, 'clo120'] # 120일 이동평균선 | ||
556 | + | ||
557 | + if df.loc[0, 'clo5_diff_rate'] is not None: | ||
558 | + self.sf.df_transaction.loc[0, 'clo5_diff_rate'] = float(df.loc[0, 'clo5_diff_rate']) # 5일 이동평균선 변동률 | ||
559 | + if df.loc[0, 'clo10_diff_rate'] is not None: | ||
560 | + self.sf.df_transaction.loc[0, 'clo10_diff_rate'] = float(df.loc[0, 'clo10_diff_rate']) | ||
561 | + if df.loc[0, 'clo20_diff_rate'] is not None: | ||
562 | + self.sf.df_transaction.loc[0, 'clo20_diff_rate'] = float(df.loc[0, 'clo20_diff_rate']) | ||
563 | + if df.loc[0, 'clo60_diff_rate'] is not None: | ||
564 | + self.sf.df_transaction.loc[0, 'clo60_diff_rate'] = float(df.loc[0, 'clo60_diff_rate']) | ||
565 | + if df.loc[0, 'clo120_diff_rate'] is not None: | ||
566 | + self.sf.df_transaction.loc[0, 'clo120_diff_rate'] = float(df.loc[0, 'clo120_diff_rate']) | ||
567 | + | ||
568 | + # null값을 0으로 변환 | ||
569 | + self.sf.df_all_item = self.sf.df_all_item.fillna(0) | ||
570 | + self.sf.df_all_item.to_sql('transaction', self.engine_bot, if_exists='append', dtype={ | ||
571 | + 'code_name': Text, | ||
572 | + 'rate': Float, | ||
573 | + 'sell_rate': Float, | ||
574 | + 'purchase_rate': Float, | ||
575 | + 'sell_date': Text, | ||
576 | + 'd1_diff': Integer, | ||
577 | + 'd1_diff_rate': Float, | ||
578 | + 'clo5_diff_rate': Float, | ||
579 | + 'clo10_diff_rate': Float, | ||
580 | + 'clo20_diff_rate': Float, | ||
581 | + 'clo60_diff_rate': Float, | ||
582 | + 'clo120_diff_rate': Float, | ||
583 | + }) | ||
584 | + | ||
585 | + # 거래내역(transaction) 테이블에서 특정 종목을 삭제하는 함수 | ||
586 | + def delete_transaction_item(self,code): | ||
587 | + query=f"delete from transaction where code={code}" | ||
588 | + self.engine_bot.execute(query) | ||
589 | + | ||
590 | + # setting_data 테이블에 invest_unit이 오늘 업데이트 되었는지 확인 | ||
591 | + def check_set_invest_unit(self): | ||
592 | + query="select invest_unit, set_invest_unit from setting_data" | ||
401 | result=self.engine_bot.execute(query).fetchall() | 593 | result=self.engine_bot.execute(query).fetchall() |
402 | if result[0][1]==self.today: | 594 | if result[0][1]==self.today: |
403 | - self.per_invest=result[0][0] | 595 | + self.invest_unit=result[0][0] |
404 | return True | 596 | return True |
405 | else: | 597 | else: |
406 | return False | 598 | return False |
407 | 599 | ||
408 | - # 데이터베이스에서 per_invest항목을 반환 | 600 | + # 데이터베이스에서 invest_unit값을 가져오는 함수 |
409 | - def get_per_invest(self): | 601 | + def get_invest_unit(self): |
410 | - query="select per_invest from setting_data" | 602 | + query="select invest_unit from setting_data" |
411 | result=self.engine_bot.execute(query).fetchall() | 603 | result=self.engine_bot.execute(query).fetchall() |
412 | return result[0][0] | 604 | return result[0][0] |
413 | 605 | ||
414 | - # per_invest 항목 설정 | 606 | + # invest_unit 항목 업데이트 |
415 | - # per_ invest : 한 종목 당 투자할 금액 | 607 | + # 업데이트 완료 후 set_invest_unit에 업데이트 날짜 저장 |
416 | - def set_per_invest(self): | 608 | + def set_invest_unit(self): |
417 | self.get_deposit() | 609 | self.get_deposit() |
418 | self.get_balance() | 610 | self.get_balance() |
419 | - self.total_invest=self.deposit+self.total_purchase | 611 | + self.total_invest=self.deposit+self.total_purchase_price |
420 | 612 | ||
421 | - self.per_invest=self.simul_api.per_invest | 613 | + self.invest_unit=self.sf.invest_unit |
422 | - query="update setting_data set per_invest='%s', set_per_invest='%s'" | 614 | + query=f"update setting_data set invest_unit='{self.invest_unit}', set_invest_unit='{self.today}'" |
423 | - self.engine_bot.execute(query%(self.per_invest,self.today)) | 615 | + self.engine_bot.execute(query) |
424 | 616 | ||
425 | # 예수금 조회 및 저장 | 617 | # 예수금 조회 및 저장 |
426 | def get_deposit(self): | 618 | def get_deposit(self): |
... | @@ -429,11 +621,6 @@ class Open_Api(QAxWidget): | ... | @@ -429,11 +621,6 @@ class Open_Api(QAxWidget): |
429 | self.set_input_value("조회구분",1) | 621 | self.set_input_value("조회구분",1) |
430 | self.comm_rq_data("opw00001_req","opw00001",0,"2000") | 622 | self.comm_rq_data("opw00001_req","opw00001",0,"2000") |
431 | 623 | ||
432 | - # 예수금 상세현황요청 함수 | ||
433 | - def _opw00001(self,sRQName,sTrCode): | ||
434 | - self.deposit=self._get_comm_data(sTrCode,sRQName,0,"d+2출금가능금액") | ||
435 | - self.deposit=int(self.deposit) | ||
436 | - | ||
437 | # 잔고 조회 및 저장 | 624 | # 잔고 조회 및 저장 |
438 | def get_balance(self): | 625 | def get_balance(self): |
439 | self.reset_opw00018_output() | 626 | self.reset_opw00018_output() |
... | @@ -444,64 +631,6 @@ class Open_Api(QAxWidget): | ... | @@ -444,64 +631,6 @@ class Open_Api(QAxWidget): |
444 | self.set_input_value("계좌번호",self.account_no) | 631 | self.set_input_value("계좌번호",self.account_no) |
445 | self.comm_rq_data("opw00018_req","opw00018",2,"2000") | 632 | self.comm_rq_data("opw00018_req","opw00018",2,"2000") |
446 | 633 | ||
447 | - # 계좌평가 잔고내역을 저장하는 변수 초기화 | ||
448 | - def reset_opw00018_output(self): | ||
449 | - self.opw00018_output={'single':[],'multi':[]} | ||
450 | - | ||
451 | - | ||
452 | - # 계좌평가 잔고내역 요청 | ||
453 | - # 싱글데이터를 통해 계좌에 대한 평가 잔고 데이터를 제공 | ||
454 | - # 멀티데이터를 통해 보유 종목별 평가 잔고 데이터를 제공 | ||
455 | - def _opw00018(self,sRQName,sTrCode): | ||
456 | - # 계좌평가 잔고 데이터 - 싱글데이터 저장 | ||
457 | - self.total_purchase=self._get_comm_data(sTrCode,sRQName,0,"총매입금액") | ||
458 | - self.total_evaluated_price=self._get_comm_data(sTrCode,sRQName,0,"총평가금액") | ||
459 | - self.total_valuation=self._get_comm_data(sTrCode,sRQName,0,"총평가손익금액") | ||
460 | - self.earning_rate=self._get_comm_data(sTrCode,sRQName,0,"총수익률(%)") | ||
461 | - self.estimated_deposit=self._get_comm_data(sTrCode,sRQName,0,"추정예탁자산") | ||
462 | - | ||
463 | - self.total_purchase=int(self.total_purchase) | ||
464 | - self.total_evaluated_price=int(self.total_evaluated_price) | ||
465 | - self.total_valuation=int(self.total_valuation) | ||
466 | - self.earning_rate=float(self.earning_rate) | ||
467 | - self.estimated_deposit=int(self.estimated_deposit) | ||
468 | - | ||
469 | - self.opw00018_output['single'].append(self.total_purchase) | ||
470 | - self.opw00018_output['single'].append(self.total_evaluated_price) | ||
471 | - self.opw00018_output['single'].append(self.total_valuation) | ||
472 | - self.opw00018_output['single'].append(self.earning_rate) | ||
473 | - self.opw00018_output['single'].append(self.estimated_deposit) | ||
474 | - | ||
475 | - # 종목별 평가 잔고 데이터 - 멀티데이터 저장 | ||
476 | - rows=self._get_repeat_cnt(sTrCode,sRQName) | ||
477 | - | ||
478 | - for i in range(rows): | ||
479 | - code=self._get_comm_data(sTrCode,sRQName,i,"종목번호") | ||
480 | - name=self._get_comm_data(sTrCode,sRQName,i,"종목명") | ||
481 | - quantity=self._get_comm_data(sTrCode,sRQName,i,"보유수량") | ||
482 | - purchase_price=self._get_comm_data(sTrCode,sRQName,i,"매입가") | ||
483 | - current_price=self._get_comm_data(sTrCode,sRQName,i,"현재가") | ||
484 | - total_valuation=self._get_comm_data(sTrCode,sRQName,i,"평가손익") | ||
485 | - earning_rate=self._get_comm_data(sTrCode,sRQName,i,"수익률(%)") | ||
486 | - total_purchase=self._get_comm_data(sTrCode,sRQName,i,"매입금액") | ||
487 | - | ||
488 | - code=code[1:] | ||
489 | - quantity=int(quantity) | ||
490 | - purchase_price=int(purchase_price) | ||
491 | - current_price=int(current_price) | ||
492 | - total_valuation=int(total_valuation) | ||
493 | - earning_rate=float(earning_rate) | ||
494 | - total_purchase=int(total_purchase) | ||
495 | - | ||
496 | - self.opw00018_output['multi'].append( | ||
497 | - [name,quantity,purchase_price,current_price,total_valuation,earning_rate,total_purchase,code] | ||
498 | - ) | ||
499 | - | ||
500 | - # 일자별 실현 손익 요청 | ||
501 | - def _opt10074(self,sRQName,sTrCode): | ||
502 | - self.total_profit=self._get_comm_data(sTrCode,sRQName,0,"실현손익") | ||
503 | - self.today_profit=self._get_comm_data(sTrCode,sRQName,0,"당일매도손익") | ||
504 | - | ||
505 | # open_api를 통해 보유한 종목을 가져오는 함수 | 634 | # open_api를 통해 보유한 종목을 가져오는 함수 |
506 | # 가져온 정보를 posses_item이라는 테이블에 저장 | 635 | # 가져온 정보를 posses_item이라는 테이블에 저장 |
507 | def get_posses_item(self): | 636 | def get_posses_item(self): |
... | @@ -556,39 +685,11 @@ class Open_Api(QAxWidget): | ... | @@ -556,39 +685,11 @@ class Open_Api(QAxWidget): |
556 | 685 | ||
557 | self.create_transaction_history(self.not_contract['주문번호'],item.code,contract_check,self.not_contract['체결가'],item.rate) | 686 | self.create_transaction_history(self.not_contract['주문번호'],item.code,contract_check,self.not_contract['체결가'],item.rate) |
558 | 687 | ||
559 | - def _opt10076(self,sRQName,sTrCode): | ||
560 | - outputs=['주문번호','종목명','주문구분','주문가격','주문수량','체결가','체결량','미체결수량', | ||
561 | - '당일매매수수료','당일매매세금','주문상태','매매구분','원주문번호','주문시간','종목코드'] | ||
562 | - self.not_contract={} | ||
563 | - | ||
564 | - for key in outputs: | ||
565 | - if key not in ['주문번호','원주문번호','주문시간','종목코드']: | ||
566 | - self.not_contract[key]=int(self._get_comm_data(sTrCode,sRQName,0,key)) | ||
567 | - self.not_contract[key]=self._get_comm_data(sTrCode,sRQName,0,key) | ||
568 | - | ||
569 | # posses_item 테이블을 업데이트 했을 경우 setting data 테이블에 업데이트 한 날짜를 표시 | 688 | # posses_item 테이블을 업데이트 했을 경우 setting data 테이블에 업데이트 한 날짜를 표시 |
570 | def setting_data_posses_stock(self): | 689 | def setting_data_posses_stock(self): |
571 | query="update setting_data set posses_stocks='%s'" | 690 | query="update setting_data set posses_stocks='%s'" |
572 | self.engine_bot.execute(query%self.today) | 691 | self.engine_bot.execute(query%self.today) |
573 | 692 | ||
574 | - def reset_opt10073_output(self): | ||
575 | - self.opt10073_output={'single':[],'multi':[]} | ||
576 | - | ||
577 | - def _opt10073(self,sRQName,sTrCode): | ||
578 | - rows=self._get_repeat_cnt(sTrCode,sRQName) | ||
579 | - | ||
580 | - for i in range(rows): | ||
581 | - date=self._get_comm_data(sTrCode,sRQName,i,"일자") | ||
582 | - code=self._get_comm_data(sTrCode,sRQName,i,"종목코드") | ||
583 | - code_name=self._get_comm_data(sTrCode,sRQName,i,"종목명") | ||
584 | - amount=self._get_comm_data(sTrCode,sRQName,i,"체결량") | ||
585 | - today_profit=self._get_comm_data(sTrCode,sRQName,i,"당일매도손익") | ||
586 | - earning_rate=self._get_comm_data(sTrCode,sRQName,i,"손익율") | ||
587 | - | ||
588 | - code=code.lstrip('A') | ||
589 | - | ||
590 | - self.opt10073_output['multi'].append([date,code,code_name,amount,today_profit,earning_rate]) | ||
591 | - | ||
592 | # 특정 종목의 일자별 거래 데이터 조회 함수 | 693 | # 특정 종목의 일자별 거래 데이터 조회 함수 |
593 | def get_date_data(self,code,code_name,date): | 694 | def get_date_data(self,code,code_name,date): |
594 | self.ohlcv=defaultdict(list) | 695 | self.ohlcv=defaultdict(list) |
... | @@ -625,26 +726,6 @@ class Open_Api(QAxWidget): | ... | @@ -625,26 +726,6 @@ class Open_Api(QAxWidget): |
625 | else: | 726 | else: |
626 | return False | 727 | return False |
627 | 728 | ||
628 | - # 주식 일봉차트 조회 요청 | ||
629 | - # 주식의 날짜별 데이터를 저장하는 함수 | ||
630 | - def collector_opt10081(self,sRQName,sTrCode): | ||
631 | - ohlcv_cnt=self._get_repeat_cnt(sTrCode,sRQName) | ||
632 | - | ||
633 | - for i in range(ohlcv_cnt): | ||
634 | - date=self._get_comm_data(sTrCode,sRQName,i,"일자") | ||
635 | - open=self._get_comm_data(sTrCode,sRQName,i,"시가") | ||
636 | - high=self._get_comm_data(sTrCode,sRQName,i,"고가") | ||
637 | - low=self._get_comm_data(sTrCode,sRQName,i,"저가") | ||
638 | - close=self._get_comm_data(sTrCode,sRQName,i,"현재가") | ||
639 | - volume=self._get_comm_data(sTrCode,sRQName,i,"거래량") | ||
640 | - | ||
641 | - self.ohlcv['date'].append(date) | ||
642 | - self.ohlcv['open'].append(int(open)) | ||
643 | - self.ohlcv['high'].append(int(high)) | ||
644 | - self.ohlcv['low'].append(int(low)) | ||
645 | - self.ohlcv['close'].append(int(close)) | ||
646 | - self.ohlcv['volume'].append(int(volume)) | ||
647 | - | ||
648 | # stock_info의 특정 종목 테이블에서 마지막으로 저장된 날짜를 가져오는 함수 | 729 | # stock_info의 특정 종목 테이블에서 마지막으로 저장된 날짜를 가져오는 함수 |
649 | # 저장된 데이터가 없다면 '0'문자를 반환 | 730 | # 저장된 데이터가 없다면 '0'문자를 반환 |
650 | def get_latest_date_from_stock_info(self,code_name): | 731 | def get_latest_date_from_stock_info(self,code_name): |
... | @@ -697,6 +778,167 @@ class Open_Api(QAxWidget): | ... | @@ -697,6 +778,167 @@ class Open_Api(QAxWidget): |
697 | "where code='%s' and sell_date='%s'" | 778 | "where code='%s' and sell_date='%s'" |
698 | self.engine_bot.execute(query%(0,self.today_time,code,0)) | 779 | self.engine_bot.execute(query%(0,self.today_time,code,0)) |
699 | 780 | ||
781 | + # 주식일봉차트조회 요청 함수 - 하나의 데이터만 저장 | ||
782 | + def _opt10081(self, sRQName, sTrCode): | ||
783 | + code = self._get_comm_data(sTrCode, sRQName, 0, "종목코드") | ||
784 | + # 조회하는 종목이 매수하려는 종목이 아니라면 에러메세지 출력 | ||
785 | + if code != self.get_today_buy_list_code: | ||
786 | + logger.critical(f"_opt10081:({code},{self.get_today_buy_list_code})") | ||
787 | + | ||
788 | + date = self._get_comm_data(sTrCode, sRQName, 0, "일자") | ||
789 | + open = self._get_comm_data(sTrCode, sRQName, 0, "시가") | ||
790 | + high = self._get_comm_data(sTrCode, sRQName, 0, "고가") | ||
791 | + low = self._get_comm_data(sTrCode, sRQName, 0, "저가") | ||
792 | + close = self._get_comm_data(sTrCode, sRQName, 0, "현재가") | ||
793 | + volume = self._get_comm_data(sTrCode, sRQName, 0, "거래량") | ||
794 | + | ||
795 | + self.ohlcv['date'].append(date) | ||
796 | + self.ohlcv['open'].append(int(open)) | ||
797 | + self.ohlcv['high'].append(int(high)) | ||
798 | + self.ohlcv['low'].append(int(low)) | ||
799 | + self.ohlcv['close'].append(int(close)) | ||
800 | + self.ohlcv['volume'].append(int(volume)) | ||
801 | + | ||
802 | + # 주식일봉차트조회 요청 함수 - 모든 행의 데이터를 저장 | ||
803 | + def collector_opt10081(self, sRQName, sTrCode): | ||
804 | + # 몇개의 행을 읽어야 하는지 담는 변수 | ||
805 | + ohlcv_cnt = self._get_repeat_cnt(sTrCode, sRQName) | ||
806 | + | ||
807 | + for i in range(ohlcv_cnt): | ||
808 | + date = self._get_comm_data(sTrCode, sRQName, i, "일자") | ||
809 | + open = self._get_comm_data(sTrCode, sRQName, i, "시가") | ||
810 | + high = self._get_comm_data(sTrCode, sRQName, i, "고가") | ||
811 | + low = self._get_comm_data(sTrCode, sRQName, i, "저가") | ||
812 | + close = self._get_comm_data(sTrCode, sRQName, i, "현재가") | ||
813 | + volume = self._get_comm_data(sTrCode, sRQName, i, "거래량") | ||
814 | + | ||
815 | + self.ohlcv['date'].append(date) | ||
816 | + self.ohlcv['open'].append(int(open)) | ||
817 | + self.ohlcv['high'].append(int(high)) | ||
818 | + self.ohlcv['low'].append(int(low)) | ||
819 | + self.ohlcv['close'].append(int(close)) | ||
820 | + self.ohlcv['volume'].append(int(volume)) | ||
821 | + | ||
822 | + # 예수금 상세현황요청 함수 | ||
823 | + def _opw00001(self,sRQName,sTrCode): | ||
824 | + self.deposit=self._get_comm_data(sTrCode,sRQName,0,"d+2출금가능금액") | ||
825 | + self.deposit=int(self.deposit) | ||
826 | + | ||
827 | + # 계좌평가 잔고내역을 저장하는 변수 초기화 | ||
828 | + def reset_opw00018_output(self): | ||
829 | + # single data : 계좌에 대한 평가 잔고 데이터 제공 | ||
830 | + # multi data : 보유 종목별 평가 잔고 데이터 제공 | ||
831 | + self.opw00018_output={'single':[],'multi':[]} | ||
832 | + | ||
833 | + # 계좌평가 잔고내역 요청 함수 | ||
834 | + def _opw00018(self,sRQName,sTrCode): | ||
835 | + # 계좌평가 잔고 데이터 - 싱글데이터 저장 | ||
836 | + self.total_purchase_price=self._get_comm_data(sTrCode,sRQName,0,"총매입금액") | ||
837 | + self.total_eval_price=self._get_comm_data(sTrCode,sRQName,0,"총평가금액") | ||
838 | + self.total_eval_profit_loss_price=self._get_comm_data(sTrCode,sRQName,0,"총평가손익금액") | ||
839 | + self.total_earning_rate=self._get_comm_data(sTrCode,sRQName,0,"총수익률(%)") | ||
840 | + self.estimated_deposit=self._get_comm_data(sTrCode,sRQName,0,"추정예탁자산") | ||
841 | + | ||
842 | + self.total_purchase_price=int(self.total_purchase_price) | ||
843 | + self.total_eval_price=int(self.total_eval_price) | ||
844 | + self.total_eval_profit_loss_price=int(self.total_eval_profit_loss_price) | ||
845 | + self.total_earning_rate=float(self.total_earning_rate) | ||
846 | + self.estimated_deposit=int(self.estimated_deposit) | ||
847 | + | ||
848 | + self.opw00018_output['single'].append(self.total_purchase_price) | ||
849 | + self.opw00018_output['single'].append(self.total_eval_price) | ||
850 | + self.opw00018_output['single'].append(self.total_eval_profit_loss_price) | ||
851 | + self.opw00018_output['single'].append(self.total_earning_rate) | ||
852 | + self.opw00018_output['single'].append(self.estimated_deposit) | ||
853 | + | ||
854 | + # 종목별 평가 잔고 데이터 - 멀티데이터 저장 | ||
855 | + rows=self._get_repeat_cnt(sTrCode,sRQName) | ||
856 | + | ||
857 | + for i in range(rows): | ||
858 | + code=self._get_comm_data(sTrCode,sRQName,i,"종목번호") | ||
859 | + name=self._get_comm_data(sTrCode,sRQName,i,"종목명") | ||
860 | + quantity=self._get_comm_data(sTrCode,sRQName,i,"보유수량") | ||
861 | + purchase_price=self._get_comm_data(sTrCode,sRQName,i,"매입가") | ||
862 | + current_price=self._get_comm_data(sTrCode,sRQName,i,"현재가") | ||
863 | + eval_profit_loss_price=self._get_comm_data(sTrCode,sRQName,i,"평가손익") | ||
864 | + earning_rate=self._get_comm_data(sTrCode,sRQName,i,"수익률(%)") | ||
865 | + item_total_purchase=self._get_comm_data(sTrCode,sRQName,i,"매입금액") | ||
866 | + | ||
867 | + code=code[1:] | ||
868 | + quantity=int(quantity) | ||
869 | + purchase_price=int(purchase_price) | ||
870 | + current_price=int(current_price) | ||
871 | + eval_profit_loss_price=int(eval_profit_loss_price) | ||
872 | + earning_rate=float(earning_rate) | ||
873 | + item_total_purchase=int(item_total_purchase) | ||
874 | + | ||
875 | + self.opw00018_output['multi'].append( | ||
876 | + [name,quantity,purchase_price,current_price,eval_profit_loss_price,earning_rate,item_total_purchase,code] | ||
877 | + ) | ||
878 | + | ||
879 | + # 일자별 실현 손익 요청 | ||
880 | + def _opt10074(self,sRQName,sTrCode): | ||
881 | + self.total_profit=self._get_comm_data(sTrCode,sRQName,0,"실현손익") | ||
882 | + self.today_profit=self._get_comm_data(sTrCode,sRQName,0,"당일매도손익") | ||
883 | + | ||
884 | + # 위탁종합거래내역 요청 함수 | ||
885 | + def _opw00015(self,sRQName,sTrCode): | ||
886 | + rows = self._get_repeat_cnt(sTrCode, sRQName) | ||
887 | + acc_no = self._get_comm_data(sTrCode, sRQName, 1, "계좌번호") | ||
888 | + for i in range(rows): | ||
889 | + date = self._get_comm_data(sTrCode, sRQName, i, "거래일자") | ||
890 | + | ||
891 | + # 실시간체결요청 함수 | ||
892 | + def _opt10076(self,sRQName,sTrCode): | ||
893 | + outputs=['주문번호','종목명','주문구분','주문가격','주문수량','체결가','체결량','미체결수량', | ||
894 | + '당일매매수수료','당일매매세금','주문상태','매매구분','원주문번호','주문시간','종목코드'] | ||
895 | + self._data={} | ||
896 | + | ||
897 | + for key in outputs: | ||
898 | + if key not in ['주문번호','원주문번호','주문시간','종목코드']: | ||
899 | + self._data[key]=int(self._get_comm_data(sTrCode,sRQName,0,key)) | ||
900 | + continue | ||
901 | + self._data[key]=self._get_comm_data(sTrCode,sRQName,0,key) | ||
902 | + | ||
903 | + # _opt10073 결과를 담는 변수를 초기화하는 함수 | ||
904 | + def reset_opt10073_output(self): | ||
905 | + self.opt10073_output={'single':[],'multi':[]} | ||
906 | + | ||
907 | + # 일자별종목별실현손익요청 함수 | ||
908 | + def _opt10073(self,sRQName,sTrCode): | ||
909 | + rows=self._get_repeat_cnt(sTrCode,sRQName) | ||
910 | + | ||
911 | + for i in range(rows): | ||
912 | + date=self._get_comm_data(sTrCode,sRQName,i,"일자") | ||
913 | + code=self._get_comm_data(sTrCode,sRQName,i,"종목코드") | ||
914 | + code_name=self._get_comm_data(sTrCode,sRQName,i,"종목명") | ||
915 | + amount=self._get_comm_data(sTrCode,sRQName,i,"체결량") | ||
916 | + today_profit=self._get_comm_data(sTrCode,sRQName,i,"당일매도손익") | ||
917 | + earning_rate=self._get_comm_data(sTrCode,sRQName,i,"손익율") | ||
918 | + | ||
919 | + code=code.lstrip('A') | ||
920 | + | ||
921 | + self.opt10073_output['multi'].append([date,code,code_name,amount,today_profit,earning_rate]) | ||
922 | + | ||
923 | + # 주식분봉차트조회요청 함수 | ||
924 | + def _opt10080(self,sRQName,sTrCode): | ||
925 | + data_cnt = self._get_repeat_cnt(sTrCode, sRQName) | ||
926 | + for i in range(data_cnt): | ||
927 | + date = self._get_comm_data(sTrCode, sRQName, i, "체결시간") | ||
928 | + open = self._get_comm_data(sTrCode, sRQName, i, "시가") | ||
929 | + high = self._get_comm_data(sTrCode, sRQName, i, "고가") | ||
930 | + low = self._get_comm_data(sTrCode, sRQName, i, "저가") | ||
931 | + close = self._get_comm_data(sTrCode, sRQName, i, "현재가") | ||
932 | + volume = self._get_comm_data(sTrCode, sRQName, i, "거래량") | ||
933 | + | ||
934 | + self.ohlcv['date'].append(date[:-2]) | ||
935 | + self.ohlcv['open'].append(abs(int(open))) | ||
936 | + self.ohlcv['high'].append(abs(int(high))) | ||
937 | + self.ohlcv['low'].append(abs(int(low))) | ||
938 | + self.ohlcv['close'].append(abs(int(close))) | ||
939 | + self.ohlcv['volume'].append(int(volume)) | ||
940 | + self.ohlcv['sum_volume'].append(int(0)) | ||
941 | + | ||
700 | 942 | ||
701 | if __name__=="__main__": | 943 | if __name__=="__main__": |
702 | app=QApplication(sys.argv) | 944 | app=QApplication(sys.argv) | ... | ... |
-
Please register or login to post a comment