def ws_connect(self): ts = -1 while (ts <= self._retry): ws = None try: ws = create_connection(self._ws_url, timeout=self._timeout) except Exception as e: logger.exception( 'connect {} websocket error, e={}, retry={}'.format( self._ws_url, e, ts)) # log_config.output2ui('connect {} websocket error, e={}, retry={}'.format(self._ws_url, e, ts), 4) if ws: ws.shutdown() time.sleep(2) if self._retry >= 0: ts += 1 else: pass else: self._ws = ws logger.info("connect web socket succeed.") log_config.output2ui("connect web socket succeed.") return True logger.critical("create connection failed.") log_config.output2ui("create connection failed.", 5) raise (Exception("connect web socket server failed.")) return False
def _http_get(self, url, params, add_to_headers=None): headers = { "Content-type": "application/x-www-form-urlencoded", 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36', 'Accept-Language': 'zh-cn' } if add_to_headers: headers.update(add_to_headers) post_data = urllib.parse.urlencode(params) try: logging.info("RESTAPI, GET: {}".format(url)) log_config.output2ui("RESTAPI, GET: {}".format(url)) response = requests.get(url, post_data, headers=headers, timeout=self._timeout) logger.debug( "RESTAPI _http_get url:{}\n post_data:{}\n response: {}". format(url, post_data, response.json())) # log_config.output2ui("RESTAPI _http_get url:{}\n post_data:{}\n response: {}".format(url, post_data, response.json())) return response.status_code, response.json() except Exception as e: logger.exception( "RESTAPI _http_getException, url:{}\n post_data:{}\n e: {}". format(url, post_data, e)) log_config.output2ui( "RESTAPI _http_get Exception, url:{}\n post_data:{}\n e: {}". format(url, post_data, e), 4) return -1, None
def get_accounts(self): """ :return: """ path = "/account/accounts" params = {} code, response = self._http_get_with_key(params, path) logger.info("get_accounts code = {c}, response={r}".format(c=code, r=response)) # logger.info("get_accounts code = %d" % code) # logger.info("get_accounts code = %d", code) if code == 200 and response["data"]: try: self._account_id = response['data'][0]['id'] self._account_state = response['data'][0]['state'] config.ACCOUNT_ID = self._account_id config.ACCOUNT_STATE = self._account_state return code, response except Exception as e: logger.exception("get_accounts failed ,e =%s" % e) log_config.output2ui("get_accounts failed ,e =%s" % e, 4) self._account_id = None self._account_state = None config.ACCOUNT_ID = None config.ACCOUNT_STATE = None return code, None
def verify_user_by_get_balance(currency, ak, sk, ws_site, rest_site, retry): from rs_util import HuobiREST config.CURRENT_WS_URL = config.WS_URLS[ws_site] config.CURRENT_REST_MARKET_URL = config.REST_URLS[rest_site][0] config.CURRENT_REST_TRADE_URL = config.REST_URLS[rest_site][1] hrs = HuobiREST(config.CURRENT_REST_MARKET_URL, config.CURRENT_REST_TRADE_URL, ak, sk, config.PRIVATE_KEY) hrs.get_accounts() # balance = strategies.get_balance( # currency, ak, sk, retry) # self.gress_bar_verify_user.quit() if hrs.account_id and hrs.account_state == config.ACCOUNT_STATE_WORKING: # if balance: self._is_user_valid = True config.ACCESS_KEY = self._user_info.get("access_key", None) config.SECRET_KEY = self._user_info.get("secret_key", None) config.NEED_TOBE_SUB_SYMBOL.clear() config.NEED_TOBE_SUB_SYMBOL.append(self._user_info.get("trade", None)) self._is_user_valid = True # self.verify_identity_button.config(state="disabled") self.init_history_button.config(state="normal") self.start_button.config(state="normal") strategies.update_balance(is_first=True) log_config.output2ui("Authentication passed!", 8) else: messagebox.showwarning("Error", "Authentication failed!") log_config.output2ui("Authentication failed!", 3)
def clean_strategy(self): logger.warning("clean_strategy...") log_config.output2ui("clean_strategy...", 2) self._strategy_pool.clean_all() self.clean_st_button.config(state="disabled") self.register_button.config(state="normal") log_config.output2ui("Clean strategy successfully!", 8)
def stop_check_strategy(self): logger.warning("stop_check_strategy...") log_config.output2ui("stop_check_strategy...", 2) self._strategy_pool.stop_work() self.start_check_strategy_button.config(state="normal") self.stop_check_strategy_button.config(state="disabled") log_config.output2ui("Stop check strategy successfully!", 8)
def _http_post(self, url, params, add_to_headers=None): headers = { "Accept": "application/json", 'Content-Type': 'application/json', 'Accept-Language': 'zh-cn' } if add_to_headers: headers.update(add_to_headers) try: post_data = json.dumps(params) logger.info("RESTAPI, POST: {}".format(url)) response = requests.post(url, post_data, headers=headers, timeout=self._timeout) logger.debug( "RESTAPI _http_post, url:{}\n post_data:{}\n response: {}". format(url, post_data, response.json())) # log_config.output2ui( # "RESTAPI _http_post, url:{}\n post_data:{}\n response: {}".format(url, post_data, response.json())) return response.status_code, response.json() except Exception as e: logger.exception( "RESTAPI _http_post Exception, url:{}\n post_data:{}\n e: {}". format(url, post_data, e)) log_config.output2ui( "RESTAPI _http_post Exception, url:{}\n post_data:{}\n e: {}". format(url, post_data, e), 4) return -1, None
def get_balance(self, acct_id=None, currency=None): ''' :param acct_id: :param currency: :return: ''' if not acct_id: acct_id = self.get_account_id() url = "/account/accounts/{0}/balance".format(acct_id) params = {"account-id": acct_id} ret = self._http_get_with_key(params, url) if not currency: return ret else: if ret[0] != 200: return ret response = ret[1] if response.get("status", None) != config.STATUS_OK: return ret[0], None data = response.get("data", None) state = data.get("state") if state != "working": logger.warning("balance is not working!!") log_config.output2ui("balance is not working!!", 2) bal_list = data.get("list", []) balance = {"trade": 0, "frozen": 0} for bal in bal_list: if bal.get("currency", "") == currency: str_balance = bal.get("balance", "0") num_balance = float(str_balance) balance[bal.get("type", "unknown")] = num_balance return 200, balance
def update_kdj(kdj_text): while True: try: kdj = process.REALTIME_KDJ.get(block=True) self.kdj_text.set("{}/{}/{}".format(round(kdj[0], 2), round(kdj[1], 2), round(kdj[2], 2))) except Exception as e: logger.exception("update_kdj exception....") log_config.output2ui("update_kdj exception....", 3)
def start_check_strategy(self): # 策略检测线程启动 logger.info("start_check_strategy...") log_config.output2ui("start_check_strategy...") self._strategy_pool.start_work() self.start_check_strategy_button.config(state="disabled") self.stop_check_strategy_button.config(state="normal") log_config.output2ui("Start check strategy successfully!", 8)
def _sub_market(self): logger.info("---start sub.") log_config.output2ui("--start sub.") for symbol in config.NEED_TOBE_SUB_SYMBOL: for kl in config.KL_ALL: channel = "market.{}.kline.{}".format(symbol, kl) logger.info("-sub_market: {}.".format(channel)) log_config.output2ui("-sub_market: {}.".format(channel)) self._hws.ws_sub(channel, process.kline_sub_msg_process)
def update_balance(bal_text): while True: try: msg = process.REALTIME_BALANCE.get(block=True) bal_text.set(str(msg)) except Exception as e: logger.exception("update_balance exception....") log_config.output2ui("update_balance exception....", 3) continue
def _init_ws(self): logger.info("-------start connect web socket server.") log_config.output2ui("-------start connect web socket server.") self._hws = HuobiWS(config.CURRENT_WS_URL) ret = self._hws.ws_connect() if not ret: logger.error("init_ws failed.") log_config.output2ui("init_ws failed.", 3) return False self._hws.start_recv() return True
def update_uml(uml_text): while True: try: global CURRENT_PRICE uml = process.REALTIME_UML.get(block=True) diff1 = uml[0] - uml[1] diff2 = uml[1] - uml[2] uml_text.set("{}/{}/{}-{}/{}-{}/{}".format(round(uml[0], 3), round(uml[1], 3), round(uml[2], 3), round(diff1, 3), round(diff2, 3), round(diff1 / CURRENT_PRICE, 4), round(diff2 / CURRENT_PRICE, 4))) except Exception as e: logger.exception("update_uml exception....") log_config.output2ui("update_uml exception....", 3)
def ws_close(self): logging.info("close web socket.") log_config.output2ui("close web socket.") self._run = False if self._ws: self._ws.shutdown() self._ws = None #断开之后,原来的注册不再生效,清空 self._sub_map.clear() self._req_map.clear()
def set_up_config(self): from popup_config import PopupConfig pop = PopupConfig(self._user_info, "Verify identity") self.root.wait_window(pop) if not self._user_info.get("ok", False): return logger.info("{}".format(self._user_info)) log_config.output2ui("{}".format(self._user_info)) self.price_text.set("") self.bal_text.set("") self.coin_text.set("") self.verify_user_information()
def init_history(hb): ret = self._hb.init() # 这一步是必须的,先同步处理 ret2 = hb.init_history() self.gress_bar_init_history.quit() if not (ret and ret2): logger.error("init service failed.") log_config.output2ui("init service failed.", 3) messagebox.showwarning("Error", "init history data failed.") return False log_config.output2ui("Init history data successfully!", 8) self.start_button.config(state="normal") self.register_button.config(state="normal") self.init_history_button.config(state="disabled")
def _req_history_kline(self): logger.info("---req_history_kline.") log_config.output2ui("---req_history_kline.") for symbol in config.NEED_TOBE_SUB_SYMBOL: for kl in config.KL_ALL: channel = "market.{}.kline.{}".format(symbol, kl) logger.info("---req_history_kline: {}.".format(channel)) log_config.output2ui( "---req_history_kline: {}.".format(channel)) #只能拿到最近的300条数据 ,可用 if self._hws: self._hws.ws_req(channel, process.kline_req_msg_process) time.sleep(1.5) return True
def ws_sub(self, channel, call_back=None, redo=False): if channel in self._sub_map.keys() and not redo: logger.info("subbed: {} had been subscribed".format(channel)) log_config.output2ui( "subbed: {} had been subscribed".format(channel)) return True if not self._ws: logger.warning("please create web socket before sub.") log_config.output2ui("please create web socket before sub.", 2) return False index = len(self._sub_map) sub_body = {"sub": channel, "id": "id{}".format(index)} str_sub_body = json.dumps(sub_body) # print("%r" %str_sub_body) ret = self._ws.send(str_sub_body) # ret = self._ws.send("""{"sub": "market.btcusdt.kline.5min","id": "id10"}""") if ret: self._sub_map[channel] = call_back logger.info("SUB: {} have subscribed successfully".format(channel)) log_config.output2ui( "SUB: {} have subscribed successfully".format(channel)) return True else: logger.error("SUB: {} failed. ret={}, request body={}".format( channel, ret, str_sub_body)) log_config.output2ui( "SUB: {} failed. ret={}, request body={}".format( channel, ret, str_sub_body), 3) return False
def update_price(price_text): while True: try: msg = process.REALTIME_PRICE.get(block=True) # print("update_price {}".format(msg)) (key, value), = msg.items() global CURRENT_PRICE CURRENT_PRICE = float(value) price_text.set("{}:{}".format(key.upper(), value)) self.update_coin(price=value) except Exception as e: logger.exception("update_price exception....") log_config.output2ui("update_price exception....", 3) continue
def ws_req(self, channel, call_back=None, t_from=None, t_to=None): if not self._ws: logger.warning("please create web socket before req.") log_config.output2ui("please create web socket before req.", 2) return False logger.info("REQ: {}".format(channel)) log_config.output2ui("REQ: {}".format(channel)) index = len(self._req_map) req_body = {"req": channel, "id": "id{}".format(index)} if t_from or t_to: req_body["from"] = t_from req_body["to"] = t_to str_req_body = json.dumps(req_body) ret = self._ws.send(str_req_body) if ret: self._req_map[channel] = call_back logger.info("REQ: {} have request successfully".format(channel)) log_config.output2ui( "REQ: {} have request successfully".format(channel), 1) return True else: logger.error( "REQ: request {} failed. ret={}, request body={}".format( channel, ret, str_req_body)) log_config.output2ui( "REQ: request {} failed. ret={}, request body={}".format( channel, ret, str_req_body), 3) return False
def ws_unsub(self, channel): if channel not in self._sub_map.keys(): logger.warning("channel: {} had not be subscribed".format(channel)) log_config.output2ui( "channel: {} had not be subscribed".format(channel), 2) return False if not self._ws: logger.warning("please create web socket before unsub.") log_config.output2ui("please create web socket before unsub.", 2) return False index = len(self._sub_map) unsub_body = {"UNSUB": channel, "id": "id{}".format(index)} str_unsub_body = json.dumps(unsub_body) ret = self._ws.send(str_unsub_body) if ret: self._sub_map.pop(channel) logger.info("{} have un-subscribed successfully".format(channel)) log_config.output2ui( "{} have un-subscribed successfully".format(channel)) return True else: logger.error("UNSUB {} failed. ret={}, request body={}".format( channel, ret, str_unsub_body)) log_config.output2ui( "UNSUB {} failed. ret={}, request body={}".format( channel, ret, str_unsub_body), 3) return False
def check_strategy(): while self._run: time.sleep(3) try: for st in self._pool: st.run() if st.state == 0: self._pool.remove(st) except Exception as e: #捕获异常,防止策略检测线程崩溃 logger.exception("run strategy [{}] failed. e = {}".format( st.name, e)) log_config.output2ui( "run strategy [{}] failed. e = {}".format(st.name, e), 4)
def stop_work(self): logger.info("stop_work!") log_config.output2ui("stop_work!") if self._hb: self._hb.exit() self.stop_check_strategy() self.stop_button.config(state="disabled") self.start_button.config(state="normal") self.register_button.config(state="normal") self.start_check_strategy_button.config(state="disabled") # self.verify_identity_button.config(state="normal") self.init_history_button.config(state="normal") self.verify_identity_button.config(state="normal") log_config.output2ui("Stop work successfully!", 8)
def ws_reconnect(self, resub=True): logger.warning("--------------reconnect .... ") log_config.output2ui("--------------reconnect .... ", 2) if self._ws: self._ws.shutdown() self._ws = None time.sleep(1) #如果连接失败,返回False if not self.ws_connect(): return False #连接成功,判断是否需要重新订阅之前的channel if resub: for k, v in self._sub_map.items(): self.ws_sub(k, v, redo=True) return True
def run(self, after=None): if not self._hws: self._init_ws() self._init_db() self._sub_market() if self._debug: self._show_result("1") self._run = True run_time = 0 log_config.output2ui("Start work successfully!", 8) while self._run: time.sleep(1) if after and run_time > after: break run_time += 1 return True
def count_depth(self, response): if response.get("status", "") != "ok": return None result = { "bids": { "total": 0, "sum_amount": 0, "avg_price": 0 }, "asks": { "total": 0, "sum_amount": 0, "avg_price": 0 } } try: tick = response.get("tick", []) bids = tick.get("bids", []) sum_bid_amount = 0 sum_bids = 0 for bid in bids: price = bid[0] amount = bid[1] sum_bid_amount += amount sum_bids += (price * amount) result["bids"]["sum_amount"] = sum_bid_amount result["bids"]["total"] = sum_bids result["bids"]["avg_price"] = sum_bids / sum_bid_amount sum_ask_amount = 0 sum_asks = 0 asks = tick.get("asks", []) for ask in asks: price = ask[0] amount = ask[1] sum_ask_amount += amount sum_asks += (price * amount) result["asks"]["sum_amount"] = sum_ask_amount result["asks"]["total"] = sum_asks result["asks"]["avg_price"] = sum_asks / sum_ask_amount except Exception as e: logger.exception("count_depth e={}".format(e)) log_config.output2ui("count_depth e={}".format(e), 4) return result
def save_history(symbols): before_time = 300 # 初始化时拿5个5分钟周期数据,因为最多只允许拿2000条 for symbol in symbols: trade_vol_list = [] num = 4 while num > 0: beg = num * before_time result = get_trade_vol_by_time(symbol, beg, before_time=before_time, big_limit=10) if result: trade_vol_list.append(result) process.TRADE_VOL_HISTORY[symbol] = trade_vol_list num -= 1 while 1: try: for symbol in symbols: trade_vol_list = process.TRADE_VOL_HISTORY.get(symbol, []) if len(trade_vol_list) > 0: last_end_time = trade_vol_list[-1].get("end_time", 0) current_time = int(time.time()) * 1000 before_time = round( (current_time - last_end_time) / 1000) + 1 result = get_trade_vol_by_time(symbol, 0, before_time=before_time, big_limit=10) logger.info( "save_history_trade_vol, symbol={}, before time={}, \nresult={}" .format(symbol, before_time, result)) if result: log_config.output2ui( "save_history_trade_vol, symbol={}, before time={}, \nresult={}" .format(symbol, before_time, result)) trade_vol_list.append(result) process.TRADE_VOL_HISTORY[symbol] = trade_vol_list logger.debug("TRADE_VOL_HISTORY={}".format( process.TRADE_VOL_HISTORY)) except Exception as e: logger.exception("get_trade_vol_by_time, e={}".format(e)) time.sleep(300)
def count_sell_buy(self, response, big_limit=10): result = {"buy": 0, "sell": 0, "big_buy": 0, "big_sell": 0} if response.get("status", "") != "ok": return None try: data = response.get("data", []) for d in data: ld = d.get("data", []) for sd in ld: amount = sd.get("amount") direction = sd.get("direction") if amount >= big_limit: result["big_" + direction] += 1 result[direction] += amount except Exception as e: logger.exception("count_sell_buy e={}".format(e)) log_config.output2ui("count_sell_buy e={}".format(e), 4) return result
def is_valid(response, type="sub"): if type == "sub": if response.get("ch", config.STATUS_ERROR) == config.STATUS_ERROR: logger.error( "check [sub msg] valid failed: response={}".format(response)) log_config.output2ui( "check [sub msg] valid failed: response={}".format(response), 3) return False elif type == "req": if response.get("status", "") != config.STATUS_OK or response.get( "rep", config.STATUS_ERROR) == config.STATUS_ERROR: logger.error( "check [req msg] valid failed: response={}".format(response)) log_config.output2ui( "check [req msg] valid failed: response={}".format(response), 3) return False return True