def __amend_order(self, ord_id, side, ord_qty, limit=0, stop=0, post_only=False): """ 주문 갱신 """ try: if limit > 0 and stop > 0: ord_type = "StopLimit" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty, price=limit, stopPx=stop).result()) elif limit > 0: ord_type = "Limit" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty, price=limit).result( )) elif stop > 0: ord_type = "Stop" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty, stopPx=stop).result( )) elif post_only: # market order with post only ord_type = "Limit" prices = self.ob.get_prices() limit = prices[1] if side == "Buy" else prices[0] retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty, price=limit).result( )) else: ord_type = "Market" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty).result()) except Exception as e: logger.error('Exception: __amend_order : %s' % e) if self.enable_trade_log: logger.info(f"========= Amend Order ==============") logger.info(f"ID : {ord_id}") logger.info(f"Type : {ord_type}") logger.info(f"Side : {side}") logger.info(f"Qty : {ord_qty}") logger.info(f"Limit : {limit}") logger.info(f"Stop : {stop}") logger.info(f"======================================") notify( f"Amend Order\nType: {ord_type}\nSide: {side}\nQty: {ord_qty}\nLimit: {limit}\nStop: {stop}" )
def __amend_order(self, ord_id, side, ord_qty, limit=0, stop=0): """ 注文を更新する """ if limit > 0 and stop > 0: ord_type = "StopLimit" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty, price=limit, stopPx=stop) .result()) elif limit > 0: ord_type = "Limit" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty, price=limit).result()) elif stop > 0: ord_type = "Stop" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty, stopPx=stop).result()) else: ord_type = "Market" retry(lambda: self.private_client.Order.Order_amend( origClOrdID=ord_id, orderQty=ord_qty).result()) if self.enable_trade_log: logger.info(f"========= Amend Order ==============") logger.info(f"ID : {ord_id}") logger.info(f"Type : {ord_type}") logger.info(f"Side : {side}") logger.info(f"Qty : {ord_qty}") logger.info(f"Limit : {limit}") logger.info(f"Stop : {stop}") logger.info(f"======================================") notify( f"Amend Order\nType: {ord_type}\nSide: {side}\nQty: {ord_qty}\nLimit: {limit}\nStop: {stop}" )
def get_account_information(self): """ get account information about all types of margin balances, assets and positions https://binance-docs.github.io/apidocs/futures/en/#account-information-v2-user_data """ self.account_information = retry(lambda: self.client.futures_account_v2()) return self.account_information
def __init_client(self): """ initialization of client """ if self.client is not None: return api_key = conf['binance_test_keys'][self.account]['API_KEY'] if self.demo else conf['binance_keys'][self.account]['API_KEY'] api_secret = conf['binance_test_keys'][self.account]['SECRET_KEY'] if self.demo else conf['binance_keys'][self.account]['SECRET_KEY'] self.client = Client(api_key=api_key, api_secret=api_secret, testnet=self.demo) if self.base_asset == None or self.asset_rounding == None or \ self.quote_asset == None or self.quote_rounding == None: exchange_info = retry(lambda: self.client.futures_exchange_info()) symbols = exchange_info['symbols'] symbol = [symbol for symbol in symbols if symbol.get('symbol')==self.pair] self.base_asset = symbol[0]['baseAsset'] self.asset_rounding = symbol[0]['quantityPrecision'] self.quote_asset = symbol[0]['quoteAsset'] self.quote_rounding = symbol[0]['pricePrecision'] logger.info(f"Asset: {self.base_asset} Rounding: {self.asset_rounding} - Quote: {self.quote_asset} Rounding: {self.quote_rounding}")
def fetch_ohlcv(self, bin_size, start_time, end_time): """ fetch OHLCV data :param start_time: start time :param end_time: end time :return: """ self.__init_client() fetch_bin_size = allowed_range[bin_size][0] left_time = start_time right_time = end_time data = to_data_frame([]) while True: source = retry(lambda: self.public_client.Trade.Trade_getBucketed( symbol=self.pair, binSize=fetch_bin_size, startTime=left_time, endTime=right_time, count=500, partial=True).result()) if len(source) == 0: break source = to_data_frame(source) data = pd.concat([data, source]) if right_time > source.iloc[-1].name + delta(fetch_bin_size): left_time = source.iloc[-1].name + delta(fetch_bin_size) time.sleep(2) else: break return resample(data, bin_size)
def cancel_all(self): """ cancel all orders """ self.__init_client() res = retry(lambda: self.client.futures_cancel_all_open_orders(symbol=self.pair)) #for order in orders: logger.info(f"Cancel all open orders: {res}")
def cancel(self, id): """ cancel a specific order by id :param id: id of the order :return: result """ self.__init_client() order = self.get_open_order(id) if order is None: return False try: retry(lambda: self.client.futures_cancel_order(symbol=self.pair, origClientOrderId=order["clientOrderId"])) except HTTPNotFound: return False logger.info(f"Cancel Order : (clientOrderId, type, side, quantity, price, stop) = " f"({order['clientOrderId']}, {order['type']}, {order['side']}, {order['origQty']}, " f"{order['price']}, {order['stopPrice']})") return True
def cancel_all(self): """ cancel all orders """ if not eval(os.environ.get("BOT_TEST", "False")): self.__init_client() res = retry(lambda: self.client.futures_cancel_all_open_orders(symbol=self.pair)) # for order in orders: logger.info(f"Cancel all open orders: {res}")
def __new_order(self, ord_id, side, ord_qty, limit=0, stop=0): """ 注文を作成する """ if limit > 0 and stop > 0: ord_type = "StopLimit" retry(lambda: self.private_client.Order.Order_new(symbol="XBTUSD", ordType=ord_type, clOrdID=ord_id, side=side, orderQty=ord_qty, price=limit, stopPx=stop). result()) elif limit > 0: ord_type = "Limit" retry(lambda: self.private_client.Order.Order_new(symbol="XBTUSD", ordType=ord_type, clOrdID=ord_id, side=side, orderQty=ord_qty, price=limit). result()) elif stop > 0: ord_type = "Stop" retry(lambda: self.private_client.Order.Order_new(symbol="XBTUSD", ordType=ord_type, clOrdID=ord_id, side=side, orderQty=ord_qty, stopPx=stop). result()) else: ord_type = "Market" retry(lambda: self.private_client.Order.Order_new(symbol="XBTUSD", ordType=ord_type, clOrdID=ord_id, side=side, orderQty=ord_qty) .result()) if self.enable_trade_log: logger.info(f"========= New Order ==============") logger.info(f"ID : {ord_id}") logger.info(f"Type : {ord_type}") logger.info(f"Side : {side}") logger.info(f"Qty : {ord_qty}") logger.info(f"Limit : {limit}") logger.info(f"Stop : {stop}") logger.info(f"======================================") notify( f"New Order\nType: {ord_type}\nSide: {side}\nQty: {ord_qty}\nLimit: {limit}\nStop: {stop}" )
def cancel(self, id): """ 注文をキャンセルする。 :param id: 注文番号 :return 成功したか: """ self.__init_client() order = self.get_open_order(id) if order is None: return False try: retry(lambda: self.private_client.Order.Order_cancel(orderID=order['orderID']).result())[0] except HTTPNotFound: return False logger.info(f"Cancel Order : (orderID, orderType, side, orderQty, limit, stop) = " f"({order['orderID']}, {order['ordType']}, {order['side']}, {order['orderQty']}, " f"{order['price']}, {order['stopPx']})") return True
def close_all(self): """ Close all positions for this pair """ self.__init_client() order = retry(lambda: self.private_client.Order.Order_closePosition(symbol=self.pair).result()) logger.info(f"Close Position : (orderID, orderType, side, orderQty, limit, stop) = " f"({order['orderID']}, {order['ordType']}, {order['side']}, {order['orderQty']}, " f"{order['price']}, {order['stopPx']})") logger.info(f"Close All Position")
def close_all(self): """ すべてのポジションを解消する。 """ self.__init_client() order = retry(lambda: self.private_client.Order.Order_closePosition(symbol="XBTUSD").result()) logger.info(f"Close Position : (orderID, orderType, side, orderQty, limit, stop) = " f"({order['orderID']}, {order['ordType']}, {order['side']}, {order['orderQty']}, " f"{order['price']}, {order['stopPx']})") logger.info(f"Close All Position")
def fetch_ohlcv(self, bin_size, start_time, end_time): """ fetch OHLCV data :param start_time: start time :param end_time: end time :return: """ self.__init_client() fetch_bin_size = allowed_range[bin_size][0] left_time = start_time right_time = end_time data = to_data_frame([]) while True: if left_time > right_time: break logger.info(f"fetching OHLCV data") left_time_to_timestamp = int(datetime.timestamp(left_time) * 1000) right_time_to_timestamp = int( datetime.timestamp(right_time) * 1000) source = retry(lambda: self.client.futures_klines( symbol=self.pair, interval=fetch_bin_size, startTime=left_time_to_timestamp, endTime=right_time_to_timestamp, limit=1500)) if len(source) == 0: break source_to_object_list = [] for s in source: timestamp_to_datetime = datetime.fromtimestamp( s[6] / 1000).astimezone(UTC) source_to_object_list.append({ "timestamp": timestamp_to_datetime, "high": float(s[2]), "low": float(s[3]), "open": float(s[1]), "close": float(s[4]), "volume": float(s[5]) }) source = to_data_frame(source_to_object_list) data = pd.concat([data, source]) if right_time > source.iloc[-1].name + delta(fetch_bin_size): left_time = source.iloc[-1].name + delta(fetch_bin_size) time.sleep(2) else: break return resample(data, bin_size)
def cancel_all(self): """ market close opened position for this pair """ self.__init_client() orders = retry(lambda: self.private_client.Order.Order_cancelAll(symbol=self.pair).result()) for order in orders: logger.info(f"Cancel Order : (orderID, orderType, side, orderQty, limit, stop) = " f"({order['orderID']}, {order['ordType']}, {order['side']}, {order['orderQty']}, " f"{order['price']}, {order['stopPx']})") logger.info(f"Cancel All Order")
def cancel(self, id): """ Cancel a specific order by id :param id: id of the order :return: result """ self.__init_client() order = self.get_open_order(id) if order is None: return False try: retry(lambda: self.private_client.Order.Order_cancel(orderID=order['orderID']).result())[0] except HTTPNotFound: return False logger.info(f"Cancel Order : (orderID, orderType, side, orderQty, limit, stop) = " f"({order['orderID']}, {order['ordType']}, {order['side']}, {order['orderQty']}, " f"{order['price']}, {order['stopPx']})") self.callbacks.pop(order['orderID']) return True
def get_market_price(self): """ get current price :return: """ self.__init_client() if self.market_price != 0: return self.market_price else: # when the WebSocket cant get it self.market_price = float(retry(lambda: self.client.futures_symbol_ticker(symbol=self.pair))["price"]) return self.market_price
def cancel_all(self): """ すべての注文をキャンセルする。 """ self.__init_client() orders = retry(lambda: self.private_client.Order.Order_cancelAll().result()) for order in orders: logger.info(f"Cancel Order : (orderID, orderType, side, orderQty, limit, stop) = " f"({order['orderID']}, {order['ordType']}, {order['side']}, {order['orderQty']}, " f"{order['price']}, {order['stopPx']})") logger.info(f"Cancel All Order")
def get_margin(self): """ マージンの取得 :return: """ self.__init_client() if self.margin is not None: return self.margin else: # WebSocketで取得できていない場合 self.margin = retry(lambda: self.private_client.User. User_getMargin(currency="XBt").result()) return self.margin
def get_margin(self): """ get margin :return: """ self.__init_client() if self.margin is not None: return self.margin else: # when the WebSocket cant get it self.margin = retry(lambda: self.private_client.User. User_getMargin(currency="XBt").result()) return self.margin
def get_margin(self): """ get margin :return: """ self.__init_client() if self.margin is not None: return self.margin else: # when the WebSocket cant get it self.margin = retry( lambda: self.client.futures_account_balance_v2()) return self.margin
def get_market_price(self): """ get current price :return: """ self.__init_client() if self.market_price != 0: return self.market_price else: # when the WebSocket cant get it self.market_price = retry(lambda: self.public_client .Instrument.Instrument_get(symbol=self.pair).result())[0]["lastPrice"] return self.market_price
def get_all_open_orders(self): """ Get all open orders for this pair :param id: Order id :return: """ self.__init_client() open_orders = retry(lambda: self.client.futures_get_open_orders(symbol=self.pair)) if len(open_orders) > 0: return open_orders else: return None
def get_balance(self): """ 残高の取得を行う。 :return: """ self.__init_client() if self.wallet is not None: return self.wallet["amount"] else: # WebSocketで取得できていない場合 self.wallet = retry(lambda: self.private_client.User. User_getWallet(currency="XBt").result()) return self.wallet["amount"]
def get_market_price(self): """ 現在の取引額を取得する。 :return: """ self.__init_client() if self.market_price != 0: return self.market_price else: # WebSocketで取得できていない場合 self.market_price = retry(lambda: self.public_client .Instrument.Instrument_get(symbol="XBTUSD").result())[0]["lastPrice"] return self.market_price
def get_open_orders(self, id): """ Get open orders for this pair by id :param id: Order id :return: """ self.__init_client() open_orders = retry(lambda: self.client.futures_get_open_orders(symbol=self.pair)) open_orders = [o for o in open_orders if o["clientOrderId"].startswith(id)] if len(open_orders) > 0: return open_orders else: return None
def get_position(self): """ 現在のポジションを取得する。 :return: """ self.__init_client() if self.position is not None: return self.position else: # WebSocketで取得できていない場合 self.position = retry( lambda: self.private_client.Position.Position_get( filter=json.dumps({"symbol": "XBTUSD"})).result())[0] return self.position
def get_position(self): """ get the current position :return: """ self.__init_client() if self.position is not None: return self.position else: # when the WebSocket cant get it ret = retry(lambda: self.private_client.Position.Position_get( filter=json.dumps({"symbol": self.pair})).result()) if len(ret) > 0: self.position = ret[0] return self.position
def get_position(self): """ 현재포지션 취득 :return: """ self.__init_client() if self.position is not None: return self.position else: # WebSocketで取得できていない場合 ret = retry(lambda: self.private_client.Position.Position_get( filter=json.dumps({"symbol": "XBTUSD"})).result()) if len(ret) > 0: self.position = ret[0] return self.position
def get_open_order(self, id): """ 注文を取得する。 :param id: 注文番号 :return: """ self.__init_client() open_orders = retry(lambda: self.private_client .Order.Order_getOrders(filter=json.dumps({"symbol": "XBTUSD", "open": True})) .result()) open_orders = [o for o in open_orders if o["clOrdID"].startswith(id)] if len(open_orders) > 0: return open_orders[0] else: return None
def get_margin(self, asset="USDT"): """ get margin :return: """ self.__init_client() # if self.margin is not None: # return self.margin[0] # else: # when the WebSocket cant get it ret = retry(lambda: self.client.futures_account_balance_v2()) if len(ret) > 0: self.margin = [m for m in ret if m["asset"] == asset] return self.margin[0] else: return None