async def process_orderbook(self, data): """ process orderbook data """ channel = data.get("ch") symbol = self._c_to_s[channel] d = data.get("tick") asks, bids = [], [] if d.get("asks"): for item in d.get("asks")[:self._orderbook_length]: price = "%.8f" % item[0] quantity = "%.8f" % item[1] asks.append([price, quantity]) if d.get("bids"): for item in d.get("bids")[:self._orderbook_length]: price = "%.8f" % item[0] quantity = "%.8f" % item[1] bids.append([price, quantity]) info = { "platform": self._platform, "symbol": symbol, "asks": asks, "bids": bids, "timestamp": d.get("ts") } orderbook = Orderbook(**info) self._orderbooks.append(orderbook) SingleTask.run(self._orderbook_update_callback, copy.copy(orderbook)) logger.debug("symbol:", symbol, "orderbook:", orderbook, caller=self)
async def auth_callback(self, data): if data["err-code"] != 0: e = Error( "Websocket connection authorized failed: {}".format(data)) logger.error(e, caller=self) SingleTask.run(self._init_success_callback, False, e) return self._subscribe_order_ok = False self._subscribe_position_ok = False self._subscribe_asset_ok = False # subscribe order data = { "op": "sub", "cid": tools.get_uuid1(), "topic": self._order_channel } await self.ws.send_json(data) # subscribe position data = { "op": "sub", "cid": tools.get_uuid1(), "topic": self._position_channel } await self.ws.send_json(data) # subscribe asset data = { "op": "sub", "cid": tools.get_uuid1(), "topic": self._asset_channel } await self.ws.send_json(data)
async def _on_position_update_callback(self, position: Position): """ Position information update callback. Args: position: Position object. """ if self._position_update_callback: SingleTask.run(self._position_update_callback, position)
async def _on_order_update_callback(self, order: Order): """ Order information update callback. Args: order: Order object. """ if self._order_update_callback: SingleTask.run(self._order_update_callback, order)
def __init__(self, **kwargs): """Initialize.""" e = None if not kwargs.get("account"): e = Error("param account miss") if not kwargs.get("strategy"): e = Error("param strategy miss") if not kwargs.get("symbol"): e = Error("param symbol miss") if not kwargs.get("contract_type"): e = Error("param contract_type miss") if not kwargs.get("host"): kwargs["host"] = "https://api.hbdm.com" if not kwargs.get("wss"): kwargs["wss"] = "wss://api.hbdm.com" if not kwargs.get("access_key"): e = Error("param access_key miss") if not kwargs.get("secret_key"): e = Error("param secret_key miss") if e: logger.error(e, caller=self) if kwargs.get("init_success_callback"): SingleTask.run(kwargs["init_success_callback"], False, e) return self._account = kwargs["account"] self._strategy = kwargs["strategy"] self._platform = HUOBI_USDT_SWAP_CROSS self._symbol = kwargs["symbol"] self._contract_type = kwargs["contract_type"] self._host = kwargs["host"] self._wss = kwargs["wss"] self._access_key = kwargs["access_key"] self._secret_key = kwargs["secret_key"] self._order_update_callback = kwargs.get("order_update_callback") self._position_update_callback = kwargs.get("position_update_callback") self._asset_update_callback = kwargs.get("asset_update_callback") self._init_success_callback = kwargs.get("init_success_callback") url = self._wss + "/linear-swap-notification" super(HuobiUsdtSwapCrossTrade, self).__init__(url, send_hb_interval=5) self._assets = {} # Asset detail, {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }. self._orders = {} # Order objects, {"order_id": order, ...}. self._position = Position(self._platform, self._account, self._strategy, self._symbol + '/' + self._contract_type) self._order_channel = "orders_cross.{symbol}".format(symbol=self._symbol) self._position_channel = "positions_cross.{symbol}".format(symbol=self._symbol) self._asset_channel = "accounts_cross.{symbol}".format(symbol="USDT") self._subscribe_order_ok = False self._subscribe_position_ok = False self._subscribe_asset_ok = False self._rest_api = HuobiUsdtSwapCrossRestAPI(self._access_key, self._secret_key, self._host) self.initialize()
def __init__(self, strategy=None, platform=None, symbol=None, host=None, wss=None, account=None, access_key=None, secret_key=None, asset_update_callback=None, order_update_callback=None, position_update_callback=None, init_success_callback=None, **kwargs): """initialize trade object.""" kwargs["strategy"] = strategy kwargs["platform"] = platform kwargs["symbol"] = symbol kwargs["host"] = host kwargs["wss"] = wss kwargs["account"] = account kwargs["access_key"] = access_key kwargs["secret_key"] = secret_key kwargs["asset_update_callback"] = asset_update_callback kwargs["order_update_callback"] = self._on_order_update_callback kwargs["position_update_callback"] = self._on_position_update_callback kwargs["init_success_callback"] = self._on_init_success_callback self._raw_params = copy.copy(kwargs) self._order_update_callback = order_update_callback self._position_update_callback = position_update_callback self._init_success_callback = init_success_callback if platform == const.HUOBI_SWAP: from huobi.platforms.huobi_swap_trade import HuobiSwapTrade as T elif platform == const.HUOBI_FUTURE: from huobi.platforms.huobi_future_trade import HuobiFutureTrade as T elif platform == const.HUOBI_OPTION: from huobi.platforms.huobi_option_trade import HuobiOptionTrade as T elif platform == const.HUOBI_USDT_SWAP: from huobi.platforms.huobi_usdt_swap_trade import HuobiUsdtSwapTrade as T elif platform == const.HUOBI_USDT_SWAP_CROSS: from huobi.platforms.huobi_usdt_swap_cross_trade import HuobiUsdtSwapCrossTrade as T else: logger.error("platform error:", platform, caller=self) e = Error("platform error") SingleTask.run(self._init_success_callback, False, e) return kwargs.pop("platform") self._t = T(**kwargs)
async def sub_callback(self, data): if data["err-code"] != 0: e = Error("subscribe {} failed!".format(data["topic"])) logger.error(e, caller=self) SingleTask.run(self._init_success_callback, False, e) return if data["topic"] == self._order_channel: self._subscribe_order_ok = True elif data["topic"] == self._position_channel: self._subscribe_position_ok = True elif data["topic"] == self._asset_channel: self._subscribe_asset_ok = True if self._subscribe_order_ok and self._subscribe_position_ok \ and self._subscribe_asset_ok: success, error = await self._rest_api.get_open_orders(self._symbol) if error: e = Error("get open orders failed!") SingleTask.run(self._init_success_callback, False, e) elif "data" in success and "orders" in success["data"]: for order_info in success["data"]["orders"]: order_info["ts"] = order_info["created_at"] self._update_order(order_info) SingleTask.run(self._init_success_callback, True, None) else: logger.warn("get open orders:", success, caller=self) e = Error("Get Open Orders Unknown error") SingleTask.run(self._init_success_callback, False, e)
def _update_asset(self, data): """ Asset update. Args: data: asset data. Returns: None. """ assets = {} for item in data["data"]: symbol = item["margin_account"].upper() total = float(item["margin_balance"]) #free = float(item["margin_available"]) locked = float(item["margin_frozen"])+float(item["margin_position"]) free = total - locked if total > 0: assets[symbol] = { "total": "%.8f" % total, "free": "%.8f" % free, "locked": "%.8f" % locked } if assets == self._assets: update = False else: update = True if hasattr(self._assets, "assets") is False: info = { "platform": self._platform, "account": self._account, "assets": assets, "timestamp": tools.get_cur_timestamp_ms(), "update": update } asset = Asset(**info) self._assets = asset SingleTask.run(self._asset_update_callback, copy.copy(self._assets)) else: for symbol in assets: self._assets.assets.update({ symbol: assets[symbol] }) self._assets.timestamp = tools.get_cur_timestamp_ms() SingleTask.run(self._asset_update_callback, copy.copy(self._assets))
def _update_position(self, data): """ Position update. Args: position_info: Position information. Returns: None. """ for position_info in data["data"]: if position_info["contract_code"] != self._symbol: continue if position_info["direction"] == "buy": self._position.long_quantity = int(position_info["volume"]) self._position.long_avg_price = position_info["cost_open"] else: self._position.short_quantity = int(position_info["volume"]) self._position.short_avg_price = position_info["cost_open"] # self._position.liquid_price = None self._position.utime = data["ts"] SingleTask.run(self._position_update_callback, copy.copy(self._position))
async def process_kline(self, data): """ process kline data """ channel = data.get("ch") symbol = self._c_to_s[channel] d = data.get("tick") info = { "platform": self._platform, "symbol": symbol, "open": "%.8f" % d["open"], "high": "%.8f" % d["high"], "low": "%.8f" % d["low"], "close": "%.8f" % d["close"], "volume": "%.8f" % d["amount"], "timestamp": int(data.get("ts")), "kline_type": MARKET_TYPE_KLINE } kline = Kline(**info) self._klines.append(kline) SingleTask.run(self._kline_update_callback, copy.copy(kline)) logger.debug("symbol:", symbol, "kline:", kline, caller=self)
async def process_trade(self, data): """ process trade """ channel = data.get("ch") symbol = self._c_to_s[channel] ticks = data.get("tick") for tick in ticks["data"]: direction = tick.get("direction") price = tick.get("price") quantity = tick.get("amount") info = { "platform": self._platform, "symbol": symbol, "action": ORDER_ACTION_BUY if direction == "buy" else ORDER_ACTION_SELL, "price": "%.8f" % price, "quantity": "%.8f" % quantity, "timestamp": tick.get("ts") } trade = Trade(**info) self._trades.append(trade) SingleTask.run(self._trade_update_callback, copy.copy(trade)) logger.debug("symbol:", symbol, "trade:", trade, caller=self)
def _update_order(self, order_info): """ Order update. Args: order_info: Order information. """ if order_info["contract_code"] != self._symbol: return order_no = str(order_info["order_id"]) status = order_info["status"] order = self._orders.get(order_no) if not order: if order_info["direction"] == "buy": if order_info["offset"] == "open": trade_type = TRADE_TYPE_BUY_OPEN else: trade_type = TRADE_TYPE_BUY_CLOSE else: if order_info["offset"] == "close": trade_type = TRADE_TYPE_SELL_CLOSE else: trade_type = TRADE_TYPE_SELL_OPEN info = { "platform": self._platform, "account": self._account, "strategy": self._strategy, "order_no": order_no, "client_order_id": order_info.get("client_order_id"), "order_price_type": order_info.get("order_price_type"), "order_type": order_info["order_type"], "action": ORDER_ACTION_BUY if order_info["direction"] == "buy" else ORDER_ACTION_SELL, "symbol": self._symbol + '/' + self._contract_type, "price": order_info["price"], "quantity": order_info["volume"], "trade_type": trade_type } order = Order(**info) self._orders[order_no] = order order.trade_quantity = None order.trade_price = None if order_info.get("trade"): quantity = 0 price = 0 amount = 0 count = len(order_info.get("trade")) for trade in order_info.get("trade"): order.role = trade.get("role") quantity += float(trade.get("trade_volume")) amount += float( trade.get("trade_volume") * trade.get("trade_price")) price = amount / quantity order.trade_quantity = int(quantity) order.trade_price = price if status in [1, 2, 3]: order.status = ORDER_STATUS_SUBMITTED elif status == 4: order.status = ORDER_STATUS_PARTIAL_FILLED order.remain = int(order.quantity) - int( order_info["trade_volume"]) elif status == 6: order.status = ORDER_STATUS_FILLED order.remain = 0 elif status in [5, 7]: order.status = ORDER_STATUS_CANCELED order.remain = int(order.quantity) - int( order_info["trade_volume"]) else: return order.avg_price = order_info["trade_avg_price"] order.ctime = order_info["created_at"] order.utime = order_info["ts"] SingleTask.run(self._order_update_callback, copy.copy(order)) # Delete order that already completed. if order.status in [ ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED ]: self._orders.pop(order_no) # publish order logger.info("symbol:", order.symbol, "order:", order, caller=self)
def __init__(self, **kwargs): """Initialize.""" e = None if not kwargs.get("account"): e = Error("param account miss") if not kwargs.get("strategy"): e = Error("param strategy miss") if not kwargs.get("symbol"): e = Error("param symbol miss") if not kwargs.get("host"): kwargs["host"] = "https://api.hbdm.com" if not kwargs.get("wss"): kwargs["wss"] = "wss://api.hbdm.com" if not kwargs.get("access_key"): e = Error("param access_key miss") if not kwargs.get("secret_key"): e = Error("param secret_key miss") if e: logger.error(e, caller=self) if kwargs.get("init_success_callback"): SingleTask.run(kwargs["init_success_callback"], False, e) return self._account = kwargs["account"] self._strategy = kwargs["strategy"] self._platform = HUOBI_OPTION self._symbol = kwargs["symbol"] self._host = kwargs["host"] self._wss = kwargs["wss"] self._access_key = kwargs["access_key"] self._secret_key = kwargs["secret_key"] self._contract_code = kwargs.get("contract_code") self._order_update_callback = kwargs.get("order_update_callback") self._position_update_callback = kwargs.get("position_update_callback") self._asset_update_callback = kwargs.get("asset_update_callback") self._init_success_callback = kwargs.get("init_success_callback") self._lock = asyncio.Lock() url = self._wss + "/option-notification" super(HuobiOptionTrade, self).__init__(url, send_hb_interval=5) # self._raw_symbol = self._symbol.split("-")[0] # self._trade_partition = self._symbol.split("-")[1] self._assets = {} # Asset detail, {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }. self._orders = {} # Order objects, {"order_id": order, ...}. self._position = Position(self._platform, self._account, self._strategy, self._symbol) self._order_channel = "orders.{symbol}-USDT".format(symbol=self._symbol) self._position_channel = "positions.{symbol}-USDT".format(symbol=self._symbol) self._asset_channels = ["accounts.{symbol}-USDT".format(symbol=self._symbol), "accounts.USDT-USDT".format(symbol=self._symbol)] self._subscribe_order_ok = False self._subscribe_position_ok = False self._subscribe_asset_ok = False self._rest_api = HuobiOptionRestAPI(self._access_key, self._secret_key, self._host) self.initialize()
def _update_asset(self, data): """ Asset update. Args: data: asset data. Returns: None. """ assets = {} for item in data["data"]: symbol = item["symbol"].upper() total = float(item["margin_balance"]) free = float(item["margin_available"]) locked = float(item["margin_frozen"]) premium_frozen = float(item.get("premium_frozen")) if item.get("premium_frozen") else 0.0 premium_in = float(item.get("premium_in")) if item.get("premium_in") else 0.0 premium_out = float(item.get("premium_out")) if item.get("premium_out") else 0.0 delta = float(item.get("delta")) if item.get("delta") else 0.0 gamma = float(item.get("gamma")) if item.get("gamma") else 0.0 theta = float(item.get("theta")) if item.get("theta") else 0.0 vega = float(item.get("vega")) if item.get("vega") else 0.0 option_value = float(item.get("option_value")) if item.get("option_value") else 0.0 if total > 0: assets[symbol] = { "total": "%.8f" % total, "free": "%.8f" % free, "locked": "%.8f" % locked, "premium_frozen": "%.8f" % premium_frozen, "premium_in": "%.8f" % premium_in, "premium_out": "%.8f" % premium_out, "delta": "%.8f" % delta, "gamma": "%.8f" % gamma, "theta": "%.8f" % theta, "vega": "%.8f" % vega, "option_value": "%.8f" % option_value } if assets == self._assets: update = False else: update = True if hasattr(self._assets, "assets") is False: info = { "platform": self._platform, "account": self._account, "assets": assets, "timestamp": tools.get_cur_timestamp_ms(), "update": update } asset = Asset(**info) self._assets = asset if self._asset_update_callback is not None: SingleTask.run(self._asset_update_callback, copy.copy(self._assets)) else: for symbol in assets: self._assets.assets.update({ symbol: assets[symbol] }) self._assets.timestamp = tools.get_cur_timestamp_ms() if self._asset_update_callback is not None: SingleTask.run(self._asset_update_callback, copy.copy(self._assets))