def update_price_db(self, filtered=False): # 다운로드 한 이후로는 설정 값 변경 불가 self.comboBox.setEnabled(False) self.checkBox.setEnabled(False) if filtered: fetch_code_df = self.f_sv_code_df db_code_df = self.f_db_code_df else: fetch_code_df = self.sv_code_df db_code_df = self.db_code_df if self.comboBox.currentIndex() == 0: # 1분봉 tick_unit = '분봉' count = 200000 # 서버 데이터 최대 reach 약 18.5만 이므로 (18/02/25 기준) tick_range = 1 elif self.comboBox.currentIndex() == 1: # 5분봉 tick_unit = '분봉' count = 100000 tick_range = 5 elif self.comboBox.currentIndex() == 2: # 일봉 tick_unit = '일봉' count = 10000 # 10000개면 현재부터 1980년 까지의 데이터에 해당함. 충분. tick_range = 1 elif self.comboBox.currentIndex() == 3: # 주봉 tick_unit = '주봉' count = 2000 else: # 월봉 tick_unit = '월봉' count = 500 if self.checkBox.isChecked(): columns = ['open', 'high', 'low', 'close', 'volume'] ohlcv_only = True else: columns = [ 'open', 'high', 'low', 'close', 'volume', '상장주식수', '외국인주문한도수량', '외국인현보유수량', '외국인현보유비율', '기관순매수', '기관누적순매수' ] ohlcv_only = False # 분봉/일봉에 대해서만 아래 코드가 효과가 있음. if not is_market_open(): latest_date = available_latest_date() if tick_unit == '일봉': latest_date = latest_date // 10000 # 이미 DB 데이터가 최신인 종목들은 가져올 목록에서 제외한다 already_up_to_date_codes = db_code_df.loc[ db_code_df['갱신날짜'] == latest_date]['종목코드'].values fetch_code_df = fetch_code_df.loc[fetch_code_df['종목코드'].apply( lambda x: x not in already_up_to_date_codes)] with sqlite3.connect(self.db_path) as con: cursor = con.cursor() tqdm_range = tqdm.trange(len(fetch_code_df), ncols=100) for i in tqdm_range: code = fetch_code_df.iloc[i] self.update_status_msg = '[{}] {}'.format(code[0], code[1]) tqdm_range.set_description( preformat_cjk(self.update_status_msg, 25)) from_date = 0 if code[0] in self.db_code_df['종목코드'].tolist(): cursor.execute( "SELECT date FROM {} ORDER BY date DESC LIMIT 1". format(code[0])) from_date = cursor.fetchall()[0][0] if tick_unit == '일봉': # 일봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('D'), count, self, from_date, ohlcv_only) == False: continue elif tick_unit == '분봉': # 분봉 데이터 받기 if self.objStockChart.RequestMT(code[0], ord('m'), tick_range, count, self, from_date, ohlcv_only) == False: continue elif tick_unit == '주봉': #주봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('W'), count, self, from_date, ohlcv_only) == False: continue elif tick_unit == '월봉': #주봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('M'), count, self, from_date, ohlcv_only) == False: continue df = pd.DataFrame(self.rcv_data, columns=columns, index=self.rcv_data['date']) # 기존 DB와 겹치는 부분 제거 if from_date != 0: df = df.loc[:from_date] df = df.iloc[:-1] # 뒤집어서 저장 (결과적으로 date 기준 오름차순으로 저장됨) df = df.iloc[::-1] df.to_sql(code[0], con, if_exists='append', index_label='date') # 메모리 overflow 방지 del df gc.collect() self.update_status_msg = '' self.connect_code_list_view()
def update_price_db(self, db_path, tick_unit='day', ohlcv_only=False): """ db_path: db 파일 경로. tick_unit: '1min', '5min', 'day'. 이미 db_path가 존재할 경우, 입력값 무시하고 기존에 사용된 값 사용. ohlcv_only: ohlcv 이외의 데이터도 저장할지 여부. 이미 db_path가 존재할 경우, 입력값 무시하고 기존에 사용된 값 사용 'day' 아닌경우 False 선택 불가 고정. """ if tick_unit != 'day': ohlcv_only = True # 로컬 DB에 저장된 종목 정보 가져와서 dataframe으로 저장 con = sqlite3.connect(db_path) cursor = con.cursor() cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") db_code_list = cursor.fetchall() for i in range(len(db_code_list)): db_code_list[i] = db_code_list[i][0] db_name_list = list(map(self.objCodeMgr.get_code_name, db_code_list)) db_latest_list = [] for db_code in db_code_list: cursor.execute( "SELECT date FROM {} ORDER BY date DESC LIMIT 1".format( db_code)) db_latest_list.append(cursor.fetchall()[0][0]) # 현재 db에 저장된 'date' column의 tick_unit 확인 # 현재 db에 저장된 column 명 확인. (ohlcv_only 여부 확인) if db_latest_list: cursor.execute( "SELECT date FROM {} ORDER BY date ASC LIMIT 2".format( db_code_list[0])) date0, date1 = cursor.fetchall() # 날짜가 분 단위 인 경우 if date0[0] > 99999999: if date1[0] - date0[0] == 5: # 5분 간격인 경우 tick_unit = '5min' else: # 1분 간격인 경우 tick_unit = '1min' elif date0[0] % 100 == 0: # 월봉인 경우 tick_unit = 'month' elif date0[0] % 10 == 0: # 주봉인 경우 tick_unit = 'week' else: # 일봉인 경우 tick_unit = 'day' # column개수로 ohlcv_only 여부 확인 cursor.execute('SELECT * FROM {}'.format(db_code_list[0])) column_names = [ description[0] for description in cursor.description ] if len(column_names) > 7: # date, o, h, l, c, v ohlcv_only = False else: ohlcv_only = True db_code_df = pd.DataFrame( { '종목코드': db_code_list, '종목명': db_name_list, '갱신날짜': db_latest_list }, columns=('종목코드', '종목명', '갱신날짜')) fetch_code_df = self.sv_code_df # 분봉/일봉에 대해서만 아래 코드가 효과가 있음. if not is_market_open(): latest_date = available_latest_date() if tick_unit == 'day': latest_date = latest_date // 10000 # 이미 DB 데이터가 최신인 종목들은 가져올 목록에서 제외한다 already_up_to_date_codes = db_code_df.loc[ db_code_df['갱신날짜'] == latest_date]['종목코드'].values fetch_code_df = fetch_code_df.loc[fetch_code_df['종목코드'].apply( lambda x: x not in already_up_to_date_codes)] if tick_unit == '1min': count = 200000 # 서버 데이터 최대 reach 약 18.5만 이므로 (18/02/25 기준) tick_range = 1 elif tick_unit == '5min': count = 100000 tick_range = 5 elif tick_unit == 'day': count = 10000 # 10000개면 현재부터 1980년 까지의 데이터에 해당함. 충분. tick_range = 1 elif tick_unit == 'week': count = 2000 elif tick_unit == 'month': count = 500 if ohlcv_only: columns = ['open', 'high', 'low', 'close', 'volume'] else: columns = [ 'open', 'high', 'low', 'close', 'volume', '상장주식수', '외국인주문한도수량', '외국인현보유수량', '외국인현보유비율', '기관순매수', '기관누적순매수' ] with sqlite3.connect(db_path) as con: cursor = con.cursor() tqdm_range = tqdm.trange(len(fetch_code_df), ncols=100) for i in tqdm_range: code = fetch_code_df.iloc[i] update_status_msg = '[{}] {}'.format(code[0], code[1]) tqdm_range.set_description(preformat_cjk( update_status_msg, 25)) from_date = 0 if code[0] in db_code_df['종목코드'].tolist(): cursor.execute( "SELECT date FROM {} ORDER BY date DESC LIMIT 1". format(code[0])) from_date = cursor.fetchall()[0][0] if tick_unit == 'day': # 일봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('D'), count, self, from_date, ohlcv_only) == False: continue elif tick_unit == '1min' or tick_unit == '5min': # 분봉 데이터 받기 if self.objStockChart.RequestMT(code[0], ord('m'), tick_range, count, self, from_date, ohlcv_only) == False: continue elif tick_unit == 'week': #주봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('W'), count, self, from_date, ohlcv_only) == False: continue elif tick_unit == 'month': #주봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('M'), count, self, from_date, ohlcv_only) == False: continue df = pd.DataFrame(self.rcv_data, columns=columns, index=self.rcv_data['date']) # 기존 DB와 겹치는 부분 제거 if from_date != 0: df = df.loc[:from_date] df = df.iloc[:-1] # 뒤집어서 저장 (결과적으로 date 기준 오름차순으로 저장됨) df = df.iloc[::-1] df.to_sql(code[0], con, if_exists='append', index_label='date') # 메모리 overflow 방지 del df gc.collect()
def update_price_db(self, filtered=False): if filtered: fetch_code_df = self.f_sv_code_df db_code_df = self.f_db_code_df else: fetch_code_df = self.sv_code_df db_code_df = self.db_code_df if not is_market_open(): latest_date = available_latest_date() print(latest_date) # 이미 DB 데이터가 최신인 종목들은 가져올 목록에서 제외한다 already_up_to_date_codes = db_code_df.loc[ db_code_df['갱신날짜'] == latest_date]['종목코드'].values fetch_code_df = fetch_code_df.loc[fetch_code_df['종목코드'].apply( lambda x: x not in already_up_to_date_codes)] if self.radioButton.isChecked(): # 1분봉 tick_unit = '분봉' count = 200000 # 서버 데이터 최대 reach 약 18.5만 이므로 (18/02/25 기준) tick_range = 1 elif self.radioButton_3.isChecked(): # 5분봉 tick_unit = '분봉' count = 100000 tick_range = 5 elif self.radioButton_2.isChecked(): # 일봉 tick_unit = '일봉' count = 10000 # 10000개면 현재부터 1980년 까지의 데이터에 해당함. 충분. tick_range = 1 elif self.radioButton_4.isChecked(): # 주봉 tick_unit = '주봉' count = 2000 else: # 월봉 tick_unit = '월봉' count = 500 with sqlite3.connect(self.db_path) as con: cursor = con.cursor() for i, (_, code) in enumerate(fetch_code_df.iterrows()): self.update_status_msg = '[{}/{}]: [{}] {}'.\ format(i+1, len(fetch_code_df), code[0], code[1]) print(self.update_status_msg) from_date = 0 if code[0] in self.db_code_df['종목코드'].tolist(): cursor.execute( "SELECT date FROM {} ORDER BY date DESC LIMIT 1". format(code[0])) from_date = cursor.fetchall()[0][0] if tick_unit == '일봉': # 일봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('D'), count, self, from_date) == False: continue elif tick_unit == '분봉': # 분봉 데이터 받기 if self.objStockChart.RequestMT(code[0], ord('m'), tick_range, count, self, from_date) == False: continue elif tick_unit == '주봉': #주봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('W'), count, self, from_date) == False: continue elif tick_unit == '월봉': #주봉 데이터 받기 if self.objStockChart.RequestDWM(code[0], ord('M'), count, self, from_date) == False: continue df = pd.DataFrame( self.rcv_data, columns=['open', 'high', 'low', 'close', 'volume'], index=self.rcv_data['date']) # 기존 DB와 겹치는 부분 제거 if from_date != 0: df = df.loc[:from_date] df = df.iloc[:-1] # 뒤집어서 저장 (결과적으로 date 기준 오름차순으로 저장됨) df = df.iloc[::-1] df.to_sql(code[0], con, if_exists='append', index_label='date') # 메모리 overflow 방지 del df gc.collect() self.update_status_msg = '' self.connect_code_list_view()
while marketOpen == True : for stock_name,tradeStatus in stockList.items(): quote = rs.stocks.get_quotes(stock_name) last_trade_price = float(quote[0]['last_trade_price']) previous_close = float(quote[0]['previous_close']) logging.info(f'{stock_name.rjust(5)}: Last trade price is {last_trade_price:10.3f} and previous close was {previous_close:10.3f}') for ctr in range(len(buyThresholds)): if last_trade_price/previous_close < buyThresholds[ctr] and tradeStatus[ctr] == True: tradeConf = utils.buy_stock_units(stock_name,buyStockUnits[ctr],last_trade_price) if tradeConf == True : logging.info(f'Bought {str(buyStockUnits[ctr]):3} stocks of {stock_name}\n') tradeStatus[ctr] = False # End If # End if # End For for ctr in range(len(sellThresholds)): if last_trade_price/previous_close > sellThresholds[ctr] and tradeStatus[ctr] == True: tradeConf = utils.sell_stock_units(stock_name,sellStockUnits[ctr],last_trade_price) if tradeConf == True : logging.info(f'Sold {str(sellStockUnits[ctr]):3} stocks of {stock_name}\n') tradeStatus[ctr] = False # End If # End If # End For #Wait for 5 minutes before running the script again. sleep(300) marketOpen = utils.is_market_open() # End If Else # End While
tradePlaced = False tradeQuantity = 2 #Quantity of trades to be placed on each stock scalpThicknessByPrice = { 10: 0.005, 20: 0.003, 30: 0.002, 40: 0.001, 50: 0.001 } # Set different scalp thicknesses for different prices. at $10, a thickness of 0.005 would create a spread of 10 c (+/- 5c) #This is the robinhood watchlist for straddle strategy straddleList = "Straddle" while tradePlaced == False: marketStatus = utils.is_market_open() if marketStatus: login() stockList = utils.build_stocklist(straddleList) for stock in stockList: quote = rs.stocks.get_quotes(stock) lastTradePrice = round(float(quote[0]['last_trade_price']), 2) scalpIndex = (int(lastTradePrice / 10) + 1) * 10 if scalpIndex > 50: scalpIndex = 50 scalpThickness = scalpThicknessByPrice[scalpIndex] buyPrice = round( lastTradePrice * (1 - scalpThickness), 2 ) # Buy order at scalp% below lower of current or last close price sellPrice = round( lastTradePrice * (1 + scalpThickness),