Esempio n. 1
0
    async def connected_callback(self):
        """ After create Websocket connection successfully, we will subscribing orderbook/trade events.
        """
        symbols = []
        for s in self._symbols:
            t = s.replace("/", "-")
            symbols.append(t)
            self._symbols_map[t] = s

        if not symbols:
            logger.warn("symbols not found in config file.", caller=self)
            return
        if not self._channels:
            logger.warn("channels not found in config file.", caller=self)
            return

        channels = []
        for ch in self._channels:
            if ch == "orderbook":
                sub = {"name": "level2", "product_ids": symbols}
                channels.append(sub)
            elif ch == "trade":
                sub = {"name": "ticker", "product_ids": symbols}
                channels.append(sub)
            else:
                logger.error("channel error! channel:", ch, caller=self)
        if channels:
            msg = {"type": "subscribe", "channels": channels}
            await self._ws.send(msg)
            logger.info("subscribe orderbook/trade success.", caller=self)
Esempio n. 2
0
    async def on_event_orderbook_update(self, orderbook: Orderbook):
        """ 订单薄更新
        """
        logger.debug("orderbook:", orderbook, caller=self)
        ask1_price = float(orderbook.asks[0][0])  # 卖一价格
        bid1_price = float(orderbook.bids[0][0])  # 买一价格
        price = (ask1_price + bid1_price) / 2  # 为了方便,这里假设盘口价格为 卖一 和 买一 的平均值

        # 判断是否需要撤单
        if self.order_no:
            if (self.create_order_price + 10 > price - 1) and (self.create_order_price + 10 < price + 1):
                return
            _, error = await self.trader.revoke_order(self.order_no)
            if error:
                logger.error("revoke order error! error:", error, caller=self)
                return
            self.order_no = None
            logger.info("revoke order:", self.order_no, caller=self)

        # 创建新订单
        new_price = price + 10
        quantity = "1"  # 委托数量为1
        action = ORDER_ACTION_BUY
        new_price = tools.float_to_str(new_price)  # 将价格转换为字符串,保持精度
        quantity = tools.float_to_str(quantity)  # 将数量转换为字符串,保持精度
        order_no, error = await self.trader.create_order(action, new_price, quantity)
        if error:
            logger.error("create order error! error:", error, caller=self)
            return
        self.order_no = order_no
        self.create_order_price = float(new_price)
        logger.info("create new order:", order_no, caller=self)
Esempio n. 3
0
 async def connected_callback(self):
     """After create Websocket connection successfully, we will subscribing orderbook/trade/kline."""
     ches = []
     for ch in self._channels:
         if ch == "orderbook":
             for symbol in self._symbols:
                 ch = "spot/depth:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         elif ch == "trade":
             for symbol in self._symbols:
                 ch = "spot/trade:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         elif ch == "kline":
             for symbol in self._symbols:
                 ch = "spot/candle60s:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         else:
             logger.error("channel error! channel:", ch, caller=self)
     if ches:
         msg = {
             "op": "subscribe",
             "args": ches
         }
         await self._ws.send(msg)
         logger.info("subscribe orderbook/trade/kline success.", caller=self)
Esempio n. 4
0
 async def connected_callback(self):
     """ After create connection to Websocket server successfully, we will subscribe orderbook event.
     """
     for ch in self._channels:
         if ch == "kline":
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "kline")
                 if not channel:
                     continue
                 kline = {"sub": channel}
                 await self._ws.send(kline)
         elif ch == "orderbook":
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "depth")
                 if not channel:
                     continue
                 data = {"sub": channel}
                 await self._ws.send(data)
         elif ch == "trade":
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "trade")
                 if not channel:
                     continue
                 data = {"sub": channel}
                 await self._ws.send(data)
         else:
             logger.error("channel error! channel:", ch, caller=self)
Esempio n. 5
0
def initialize():
    """ 初始化
    """

    for platform in config.platforms:
        if platform == OKEX or platform == OKEX_MARGIN:
            from platforms.okex import OKEx as Market
        elif platform == OKEX_FUTURE:
            from platforms.okex_ftu import OKExFuture as Market
        elif platform == BINANCE:
            from platforms.binance import Binance as Market
        elif platform == DERIBIT:
            from platforms.deribit import Deribit as Market
        elif platform == BITMEX:
            from platforms.bitmex import Bitmex as Market
        elif platform == HUOBI:
            from platforms.huobi import Huobi as Market
        elif platform == COINSUPER:
            from platforms.coinsuper import CoinsuperMarket as Market
        else:
            from quant.utils import logger
            logger.error("platform error! platform:", platform)
            continue
        cc = config.platforms[platform]
        cc["platform"] = platform
        Market(**cc)
Esempio n. 6
0
 async def create_order(self, action, price, quantity, order_type=ORDER_TYPE_LIMIT):
     """ 创建订单
     @param action 委托方向 BUY SELL
     @param price 委托价格
     @param quantity 委托数量
     @param order_type 委托类型 LIMIT / MARKET
     """
     if action == ORDER_ACTION_BUY:
         action_tmp = "Buy"
     else:
         action_tmp = "Sell"
     if int(quantity) > 0:
         if action == ORDER_ACTION_BUY:
             trade_type = TRADE_TYPE_BUY_OPEN
         else:
             trade_type = TRADE_TYPE_SELL_CLOSE
     else:
         if action == ORDER_ACTION_BUY:
             trade_type = TRADE_TYPE_BUY_CLOSE
         else:
             trade_type = TRADE_TYPE_SELL_OPEN
     if order_type == ORDER_TYPE_LIMIT:
         order_type_tmp = "Limit"
     elif order_type == ORDER_TYPE_MARKET:
         order_type_tmp = "Market"
     else:
         logger.error("order_type error! order_type:", order_type, caller=self)
         return None
     quantity = abs(int(quantity))
     success, error = await self._rest_api.create_order(action_tmp, self._symbol, price, quantity, order_type_tmp,
                                                        trade_type)
     if error:
         return None, error
     else:
         return success["orderID"], None
Esempio n. 7
0
    async def connected_callback(self):
        """ After create Websocket connection successfully, we will subscribing orderbook/trade/kline.
        """
        if not self._symbols:
            logger.warn("symbols not found in config file.", caller=self)
            return
        if not self._channels:
            logger.warn("channels not found in config file.", caller=self)
            return
        for ch in self._channels:
            if ch == "orderbook":
                # subscription = {"name": "book"}
                LoopRunTask.register(self.on_event_update_orderbook, 2)
                continue
            elif ch == "trade":
                subscription = {"name": "trade"}
            # elif ch == "kline":  # TODO: something wrong from exchange server? subscribe ohlc-1 but receive ohlc-5 ?
            #     subscription = {"name": "ohlc", "interval": 1}
            else:
                logger.error("channel error:", ch, caller=self)
                continue

            d = {
                "event": "subscribe",
                "pair": self._symbols,
                "subscription": subscription
            }
            await self.ws.send_json(d)
            logger.info("subscribe", ch, "success.", caller=self)
Esempio n. 8
0
    def __init__(self, **kwargs):
        self._platform = kwargs["platform"]
        self._host = None
        self._symbols = list(set(kwargs.get("symbols")))
        self._channels = kwargs.get("channels")
        self._access_key = None
        self._secret_key = None

        for item in config.accounts:
            if item["platform"] == self._platform:
                self._host = item.get(
                    "host", "https://api-rest.premium.coinsuper.com")
                self._access_key = item["access_key"]
                self._secret_key = item["secret_key"]
        if not self._host or not self._access_key or not self._access_key:
            logger.error(
                "no find coinsuper account in ACCOUNTS from config file.",
                caller=self)
            return

        self._orderbook_interval = kwargs.get("orderbook_interval", 2)
        self._orderbook_length = kwargs.get("orderbook_length", 10)
        self._trade_interval = kwargs.get("trade_interval", 5)

        # REST API client.
        self._rest_api = CoinsuperPreRestAPI(self._host, self._access_key,
                                             self._secret_key)

        self._initialize()
Esempio n. 9
0
    async def process_binary(self, raw):
        """ 处理websocket上接收到的消息
        @param raw 原始的压缩数据
        """
        msg = json.loads(gzip.decompress(raw).decode())
        logger.debug("msg:", msg, caller=self)

        op = msg.get("op")

        if op == "auth":  # 授权
            if msg["err-code"] != 0:
                logger.error("do auth error! error:", msg, caller=self)
                return
            await self._auth_success_callback()
        elif op == "ping":  # ping
            params = {
                "op": "pong",
                "ts": msg["ts"]
            }
            await self.ws.send_json(params)
            return
        elif op == "notify":  # 订单更新通知
            if msg["topic"] != self._order_channel:
                return
            data = msg["data"]
            data["utime"] = msg["ts"]
            self._update_order(data)
Esempio n. 10
0
    def __init__(self, **kwargs):
        self._platform = kwargs["platform"]
        self._wss = None
        self._symbols = list(set(kwargs.get("symbols")))
        self._channels = kwargs.get("channels")
        self._orderbook_length = kwargs.get("orderbook_length", 10)
        self._access_key = None
        self._secret_key = None
        self._last_msg_ts = tools.get_cur_timestamp_ms()  # 上次接收到消息的时间戳

        for item in config.accounts:
            if item["platform"] == self._platform:
                self._wss = item.get("wss", "wss://deribit.com")
                self._access_key = item["access_key"]
                self._secret_key = item["secret_key"]
        if not self._wss or not self._access_key or not self._access_key:
            logger.error(
                "no find deribit account in ACCOUNTS from config file.",
                caller=self)
            return

        url = self._wss + "/ws/api/v1/"
        self._ws = Websocket(url,
                             connected_callback=self.connected_callback,
                             process_callback=self.process)
        self._ws.initialize()
        LoopRunTask.register(self.send_heartbeat_msg, 10)
Esempio n. 11
0
 async def connected_callback(self):
     """ 订阅消息
     """
     for ch in self._channels:
         if ch == "kline":  # 订阅K线数据
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "kline")
                 if not channel:
                     continue
                 kline = {"sub": channel}
                 await self.ws.send_json(kline)
         elif ch == "orderbook":  # 订阅订单薄数据
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "depth")
                 if not channel:
                     continue
                 data = {"sub": channel}
                 await self.ws.send_json(data)
         elif ch == "trade":  # 实时交易数据
             for symbol in self._symbols:
                 channel = self._symbol_to_channel(symbol, "trade")
                 if not channel:
                     continue
                 data = {"sub": channel}
                 await self.ws.send_json(data)
         else:
             logger.error("channel error! channel:", ch, caller=self)
Esempio n. 12
0
    async def initialize(self, file_folder='.'):
        """
        """
        type_map = {'platform': str,
                    'account': str,
                    'symbol': str,
                    'strategy': str,
                    'order_no': str,
                    'fill_no': str,
                    'price': float,
                    'quantity': float,
                    'side': str,
                    'liquidity': str,
                    'fee': float,
                    'ctime': np.int64}

        trades = pd.read_csv(os.path.join(file_folder, 'trades.csv'), ',', dtype=type_map)
        if trades.empty:
            logger.error("error:", "无法读取成交列表", caller=self)
            return False
        #因为我们时间用的都是东八区时间,换成时间戳以后并不是按天对齐的,为了能够按天对齐进行运算,要先加八小时,再减八小时
        trades['trade_date'] = (trades['ctime']+CHINA_TZONE_SHIFT)//ONE_DAY*ONE_DAY-CHINA_TZONE_SHIFT
        self.trades = trades.set_index(['platform', 'symbol', 'ctime']).sort_index(axis=0)
        #保存交易符号列表
        self.trades.groupby(by=['platform', 'symbol']).apply(lambda gp_df: self.universe.append((gp_df.index.levels[0][0], gp_df.index.levels[1][0])))
        #回测天数
        self.period_day = int(config.backtest["period_day"])
        #获取每日收盘价
        closes = await self.get_daily_closes()
        if closes is None:
            logger.error("error:", "无法获取每日收盘价", caller=self)
            return False
        self.closes = closes
        #
        return True
Esempio n. 13
0
def initialize():
    """ 初始化
    """
    from quant.utils import logger
    from quant.config import config

    for platform, info in config.platforms.items():
        for item in info["assets"]:
            if platform == OKEX:
                from assets.okex import OKExAsset as AssetServer
            elif platform == BINANCE:
                from assets.binance import BinanceAsset as AssetServer
            elif platform == HUOBI:
                from assets.huobi import HuobiAsset as AssetServer
            elif platform == OKEX_FUTURE:
                from assets.okex_future import OKExFutureAsset as AssetServer
            elif platform == DERIBIT:
                from assets.deribit import DeribitAsset as AssetServer
            elif platform == BITMEX:
                from assets.bitmex import BitmexAsset as AssetServer
            elif platform == COINSUPER:
                from assets.coinsuper import CoinsuperAsset as AssetServer
            else:
                logger.error("platform error! platform:", platform)
                continue
            item["platform"] = platform
            AssetServer(**item)
Esempio n. 14
0
    async def process(self, msg):
        """ 处理websocket上接收到的消息
        """
        # logger.debug("msg:", msg, caller=self)
        if not isinstance(msg, dict):
            return

        channel = msg.get("stream")
        if channel not in self._c_to_s:
            logger.warn("unkown channel, msg:", msg, caller=self)
            return

        symbol = self._c_to_s[channel]
        data = msg.get("data")
        e = data.get("e")  # 事件名称

        # 保存数据到数据库
        if e == "kline":  # K线
            kline = {
                "platform": self._platform,
                "symbol": symbol,
                "open": data.get("k").get("o"),  # 开盘价
                "high": data.get("k").get("h"),  # 最高价
                "low": data.get("k").get("l"),  # 最低价
                "close": data.get("k").get("c"),  # 收盘价
                "volume": data.get("k").get("q"),  # 交易量
                "timestamp": data.get("k").get("t"),  # 时间戳
                "kline_type": const.MARKET_TYPE_KLINE
            }
            EventKline(**kline).publish()
            logger.info("symbol:", symbol, "kline:", kline, caller=self)
        elif channel.endswith("depth20"):  # 订单薄
            bids = []
            asks = []
            for bid in data.get("bids"):
                bids.append(bid[:2])
            for ask in data.get("asks"):
                asks.append(ask[:2])
            orderbook = {
                "platform": self._platform,
                "symbol": symbol,
                "asks": asks,
                "bids": bids,
                "timestamp": tools.get_cur_timestamp_ms()
            }
            EventOrderbook(**orderbook).publish()
            logger.info("symbol:", symbol, "orderbook:", orderbook, caller=self)
        elif e == "trade":  # 实时成交信息
            trade = {
                "platform": self._platform,
                "symbol": symbol,
                "action":  ORDER_ACTION_SELL if data["m"] else ORDER_ACTION_BUY,
                "price": data.get("p"),
                "quantity": data.get("q"),
                "timestamp": data.get("T")
            }
            EventTrade(**trade).publish()
            logger.info("symbol:", symbol, "trade:", trade, caller=self)
        else:
            logger.error("event error! msg:", msg, caller=self)
Esempio n. 15
0
 async def connected_callback(self):
     """ 建立websocket成功,发起登录请求
     """
     params = {
         "platform": self._platform,
         "access_key": self._access_key,
         "secret_key": self._secret_key
     }
     ok, result = await self.do_request(self.LOGIN, params)
     if not ok:
         logger.error("login error!",
                      "platform:",
                      self._platform,
                      "account:",
                      self._account,
                      "result:",
                      result,
                      caller=self)
     else:
         logger.debug("login success!",
                      "platform:",
                      self._platform,
                      "account:",
                      self._account,
                      caller=self)
Esempio n. 16
0
 async def create_order(self, action, symbol, price, quantity, order_type=ORDER_TYPE_LIMIT):
     """ 创建订单
     @param action 操作类型 BUY SELL
     @param symbol 交易对
     @param quantity 交易量
     @param price 交易价格
     @param order_type 订单类型 市价 / 限价
     """
     info = {
         "side": "buy" if action == ORDER_ACTION_BUY else "sell",
         "instrument_id": symbol,
         "margin_trading": 1
     }
     if order_type == ORDER_TYPE_LIMIT:
         info["type"] = "limit"
         info["price"] = price
         info["size"] = quantity
     elif order_type == ORDER_TYPE_MARKET:
         info["type"] = "market"
         if action == ORDER_ACTION_BUY:
             info["notional"] = quantity  # 买入金额,市价买入是必填notional
         else:
             info["size"] = quantity  # 卖出数量,市价卖出时必填size
     else:
         logger.error("order_type error! order_type:", order_type, caller=self)
         return None
     result, error = await self.request("POST", "/api/spot/v3/orders", body=info, auth=True)
     return result, error
Esempio n. 17
0
    def __init__(self, **kwargs):
        """ 初始化
        """
        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://www.bitmex.com"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://www.bitmex.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 = BITMEX
        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._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._position_update_callback = kwargs.get("position_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

        url = self._wss + "/realtime"
        super(BitmexTrade, self).__init__(url, send_hb_interval=5)
        self.heartbeat_msg = "ping"

        self._order_channel = "order:{symbol}".format(symbol=self._symbol)  # 订单订阅频道
        self._position_channel = "position:{symbol}".format(symbol=self._symbol)  # 持仓订阅频道

        # 标记订阅订单、持仓是否成功
        self._subscribe_order_ok = False
        self._subscribe_position_ok = False

        self._assets = {}  # 资产 {"XBT": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }
        self._orders = {}
        self._position = Position(self._platform, self._account, self._strategy, self._symbol)  # 仓位

        # 初始化REST API对象
        self._rest_api = BitmexAPI(self._host, self._access_key, self._secret_key)

        # 初始化资产订阅
        if self._asset_update_callback:
            AssetSubscribe(self._platform, self._account, self.on_event_asset_update)

        self.initialize()
Esempio n. 18
0
 async def _connect(self):
     logger.info("url:", self._url, caller=self)
     proxy = config.proxy
     if not self.session:
         self.session = aiohttp.ClientSession()
     try:
         self._ws = await self.session.ws_connect(self._url, proxy=proxy)
     except (aiohttp.client_exceptions.ClientConnectorError,
             aiohttp.client_exceptions.ClientHttpProxyError,
             aiohttp.client_exceptions.ServerDisconnectedError,
             aiohttp.client_exceptions.WSServerHandshakeError,
             asyncio.TimeoutError) as e:
         logger.error("connect to server error! url:",
                      self._url,
                      caller=self)
         state = State(
             self._platform, self._account,
             "connect to server error! url: {}, error: {}".format(
                 self._url, e), State.STATE_CODE_CONNECT_FAILED)
         SingleTask.run(self.cb.on_state_update_callback, state)
         asyncio.get_event_loop().create_task(
             self._reconnect())  #如果连接出错就重新连接
         return
     state = State(self._platform, self._account,
                   "connect to server success! url: {}".format(self._url),
                   State.STATE_CODE_CONNECT_SUCCESS)
     SingleTask.run(self.cb.on_state_update_callback, state)
     asyncio.get_event_loop().create_task(self.connected_callback())
     asyncio.get_event_loop().create_task(self.receive())
Esempio n. 19
0
    def __init__(self, **kwargs):
        """ 初始化
        """
        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://www.deribit.com"
        if not kwargs.get("wss"):
            kwargs["wss"] = "wss://deribit.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 = DERIBIT
        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._asset_update_callback = kwargs.get("asset_update_callback")
        self._order_update_callback = kwargs.get("order_update_callback")
        self._position_update_callback = kwargs.get("position_update_callback")
        self._init_success_callback = kwargs.get("init_success_callback")

        self._order_channel = "user.orders.{symbol}.raw".format(symbol=self._symbol)  # 订单订阅频道

        url = self._wss + "/ws/api/v2"
        super(DeribitTrade, self).__init__(url, send_hb_interval=5)

        self._assets = {}  # 资产 {"BTC": {"free": "1.1", "locked": "2.2", "total": "3.3"}, ... }
        self._orders = {}  # 订单
        self._position = Position(self._platform, self._account, self._strategy, self._symbol)  # 仓位

        self._query_id = 0  # 消息序号id,用来唯一标识请求消息
        self._queries = {}  # 未完成的post请求 {"request_id": future}

        self.initialize()

        # 初始化资产订阅
        if self._asset_update_callback:
            AssetSubscribe(self._platform, self._account, self.on_event_asset_update)

        # 注册定时任务
        LoopRunTask.register(self._do_auth, 60 * 60)  # 每隔1小时重新授权
        LoopRunTask.register(self._check_position_update, 1)  # 获取持仓

        self._ok = False  # 是否建立授权成功的websocket连接
Esempio n. 20
0
    async def _send_message(self, method, params):
        """ Send message.

        Args:
            method: message method.
            params: message params.

        Returns:
            success: Success results, otherwise it's None.
            error: Error information, otherwise it's None.
        """
        f = asyncio.futures.Future()
        request_id = await self._generate_query_id()
        self._queries[request_id] = f
        data = {
            "jsonrpc": "2.0",
            "id": request_id,
            "method": method,
            "params": params
        }
        await self.ws.send_json(data)
        logger.debug("send message:", data, caller=self)
        success, error = await f
        if error:
            logger.error("data:", data, "error:", error, caller=self)
        return success, error
Esempio n. 21
0
 async def connected_callback(self):
     """After create Websocket connection successfully, we will subscribing orderbook/trade/kline events."""
     if not self._symbols:
         logger.warn("symbols not found in config file.", caller=self)
         return
     if not self._channels:
         logger.warn("channels not found in config file.", caller=self)
         return
     for ch in self._channels:
         if ch == "trade":
             params = []
             for s in self._symbols:
                 params.append(s.replace("/", "_"))
             request_id = await self._generate_request_id()
             d = {"id": request_id, "method": "trades.subscribe", "params": params}
             await self._ws.send(d)
             logger.info("subscribe trade success.", caller=self)
         elif ch == "orderbook":
             await self.subscribe_orderbook()
         elif ch == "kline":
             for s in self._symbols:
                 params = [s.replace("/", "_"), 60]
                 request_id = await self._generate_request_id()
                 d = {"id": request_id, "method": "kline.subscribe", "params": params}
                 await self._ws.send(d)
                 logger.info("subscribe kline success.", caller=self)
         else:
             logger.error("channel error:", ch, caller=self)
             continue
Esempio n. 22
0
    def _update_order(self, order_info):
        """ 更新订单信息
        @param order_info 订单信息
        * NOTE:
            order-state: 订单状态, submitting , submitted 已提交, partial-filled 部分成交, partial-canceled 部分成交撤销,
                filled 完全成交, canceled 已撤销
        """
        order_no = str(order_info["order-id"])
        action = ORDER_ACTION_BUY if order_info["order-type"] in [
            "buy-market", "buy-limit"
        ] else ORDER_ACTION_SELL
        state = order_info["order-state"]
        remain = "%.8f" % float(order_info["unfilled-amount"])
        avg_price = "%.8f" % float(order_info["price"])
        ctime = order_info["created-at"]
        utime = order_info["utime"]

        if state == "canceled":
            status = ORDER_STATUS_CANCELED
        elif state == "partial-canceled":
            status = ORDER_STATUS_CANCELED
        elif state == "submitting":
            status = ORDER_STATUS_SUBMITTED
        elif state == "submitted":
            status = ORDER_STATUS_SUBMITTED
        elif state == "partical-filled":
            status = ORDER_STATUS_PARTIAL_FILLED
        elif state == "filled":
            status = ORDER_STATUS_FILLED
        else:
            logger.error("status error! order_info:", order_info, caller=self)
            return None

        order = self._orders.get(order_no)
        if not order:
            info = {
                "platform": self._platform,
                "account": self._account,
                "strategy": self._strategy,
                "order_no": order_no,
                "action": action,
                "symbol": self._symbol,
                "price": "%.8f" % float(order_info["order-price"]),
                "quantity": "%.8f" % float(order_info["order-amount"]),
                "remain": remain,
                "status": status
            }
            order = Order(**info)
            self._orders[order_no] = order
        order.remain = remain
        order.status = status
        order.avg_price = avg_price
        order.ctime = ctime
        order.utime = utime
        if status in [
                ORDER_STATUS_FAILED, ORDER_STATUS_CANCELED, ORDER_STATUS_FILLED
        ]:
            self._orders.pop(order_no)
        if order and self._order_update_callback:
            SingleTask.run(self._order_update_callback, order)
Esempio n. 23
0
    async def create_order(self, action, instrument_id, price, quantity, order_type=ORDER_TYPE_LIMIT):
        """ Create an order.
        Args:
            action: Action type, `BUY` or `SELL`.
            instrument_id: Trading pair, e.g. BTC-USDT.
            price: Order price.
            quantity: Order quantity.
            order_type: Order type, `MARKET` or `LIMIT`.

        Returns:
            success: Success results, otherwise it's None.
            error: Error information, otherwise it's None.
        """
        uri = "/api/margin/v3/orders"
        info = {
            "side": "buy" if action == ORDER_ACTION_BUY else "sell",
            "instrument_id": instrument_id,
            "margin_trading": 2
        }
        if order_type == ORDER_TYPE_LIMIT:
            info["type"] = "limit"
            info["price"] = price
            info["size"] = quantity
        elif order_type == ORDER_TYPE_MARKET:
            info["type"] = "market"
            if action == ORDER_ACTION_BUY:
                info["notional"] = quantity  # buy price
            else:
                info["size"] = quantity  # sell quantity
        else:
            logger.error("order_type error! order_type:", order_type, caller=self)
            return None
        success, error = await self.request("POST", uri, body=info, auth=True)
        return success, error
Esempio n. 24
0
 def __init__(self, **kwargs):
     """initialize trader object.
     
     Args:
         strategy: 策略名称,由哪个策略发起
         platform: 交易平台
         symbols: 策略需要订阅和交易的币种
         account: 交易所登陆账号,如果为空就只是订阅市场公共行情数据,不进行登录认证,所以也无法进行交易等
         access_key: 登录令牌
         secret_key: 令牌密钥
         cb: ExchangeGateway.ICallBack {
             on_init_success_callback: `初始化是否成功`回调通知函数
             on_kline_update_callback: `K线数据`回调通知函数 (值为None就不启用此通知回调)
             on_orderbook_update_callback: `订单簿深度数据`回调通知函数 (值为None就不启用此通知回调)
             on_trade_update_callback: `市场最新成交`回调通知函数 (值为None就不启用此通知回调)
             on_ticker_update_callback: `市场行情tick`回调通知函数 (值为None就不启用此通知回调)
             on_order_update_callback: `用户挂单`回调通知函数 (值为None就不启用此通知回调)
             on_fill_update_callback: `用户挂单成交`回调通知函数 (值为None就不启用此通知回调)
             on_position_update_callback: `用户持仓`回调通知函数 (值为None就不启用此通知回调)
             on_asset_update_callback: `用户资产`回调通知函数 (值为None就不启用此通知回调)
         }
     """
     T = gateway_class(kwargs["platform"])
     if T == None:
         logger.error("platform not found:",
                      kwargs["platform"],
                      caller=self)
         cb = kwargs["cb"]
         SingleTask.run(cb.on_init_success_callback, False,
                        Error("platform not found"))
         return
     self._t = T(**kwargs)
Esempio n. 25
0
 async def send_heartbeat_msg(self, *args, **kwargs):
     request_id = await self.generate_request_id()
     data = {"id": request_id, "type": "ping"}
     if not self._ws:
         logger.error("")
         return
     await self._ws.send(data)
Esempio n. 26
0
    async def on_event_orderbook_update(self, orderbook: Orderbook):
        """ 订单薄更新
        """
        logger.debug("orderbook:", orderbook, caller=self)
        bid3_price = orderbook.bids[2][0]  # 买三价格
        bid4_price = orderbook.bids[3][0]  # 买四价格

        # 判断是否需要撤单
        if self.order_no:
            if float(self.create_order_price) < float(bid3_price) or float(
                    self.create_order_price) > float(bid4_price):
                return
            _, error = await self.trader.revoke_order(self.order_no)
            if error:
                logger.error("revoke order error! error:", error, caller=self)
                return
            self.order_no = None
            logger.info("revoke order:", self.order_no, caller=self)

        # 创建新订单
        new_price = (float(bid3_price) + float(bid4_price)) / 2
        quantity = "0.1"  # 假设委托数量为0.1
        action = ORDER_ACTION_BUY
        price = tools.float_to_str(new_price)
        quantity = tools.float_to_str(quantity)
        order_no, error = await self.trader.create_order(
            action, price, quantity)
        if error:
            logger.error("create order error! error:", error, caller=self)
            return
        self.order_no = order_no
        self.create_order_price = price
        logger.info("create new order:", order_no, caller=self)
Esempio n. 27
0
 async def _initialize(self):
     """ Initialize of Fetching open orders information.
     """
     order_nos, error = await self._rest_api.get_open_order_nos(
         self._raw_symbol)
     if error:
         e = Error("get open order nos failed: {}".format(error))
         logger.error(e, caller=self)
         if self._init_success_callback:
             SingleTask.run(self._init_success_callback, False, e)
         return
     while order_nos:
         nos = order_nos[:50]
         order_nos = order_nos[50:]
         success, error = await self._rest_api.get_order_list(nos)
         if error:
             e = Error("get order infos failed: {}".format(error))
             logger.error(e, caller=self)
             if self._init_success_callback:
                 SingleTask.run(self._init_success_callback, False, e)
             return
         for order_info in success:
             await self._update_order(order_info)
     if self._init_success_callback:
         SingleTask.run(self._init_success_callback, True, None)
Esempio n. 28
0
    async def check_order_update(self, *args, **kwargs):
        """ 检查订单更新
        """
        # 获取需要查询的订单列表
        order_nos = list(self._orders.keys())
        logger.info('length:',
                    len(order_nos),
                    'orders:',
                    order_nos,
                    caller=self)
        if not order_nos:  # 暂时没有需要更新的委托单,那么延迟1秒,再次发布执行委托单更新事件
            logger.debug('no find any order nos', caller=self)
            return

        # 获取订单最新状态,每次最多请求50个订单
        while order_nos:
            nos = order_nos[:100]
            params = {"symbol": self._raw_symbol, "order_nos": nos}
            success, results = await self._request.do_request(
                Request.ORDER_STATUS, params)
            if not success:
                logger.error("get order status error!",
                             "symbol:",
                             self._symbol,
                             "order_nos:",
                             order_nos,
                             "results:",
                             results,
                             caller=self)
            await self._process_order_update_infos(results)
            order_nos = order_nos[100:]
Esempio n. 29
0
 async def connected_callback(self):
     """ 建立连接之后,订阅事件 ticker
     """
     ches = []
     for ch in self._channels:
         if ch == "orderbook":  # 订阅orderbook行情
             for symbol in self._symbols:
                 ch = "spot/depth:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         elif ch == "trade":
             for symbol in self._symbols:
                 ch = "spot/trade:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         elif ch == "kline":
             for symbol in self._symbols:
                 ch = "spot/candle60s:{s}".format(s=symbol.replace("/", '-'))
                 ches.append(ch)
         else:
             logger.error("channel error! channel:", ch, caller=self)
     if ches:
         msg = {
             "op": "subscribe",
             "args": ches
         }
         await self.ws.send_json(msg)
         logger.info("subscribe orderbook success.", caller=self)
Esempio n. 30
0
    async def _check_position_update(self):
        """更新持仓信息"""
        positions, error = await self._rest_api.get_position_list()
        if error:
            logger.error("get position error: {}".format(error))
            return

        for position_info in positions['data']['results']:
            if position_info['symbol'] == self._symbol:
                update = False
                if not self._position.utime:  # 如果持仓还没有被初始化,那么初始化之后推送一次
                    update = True
                    self._position.update()
                size = position_info['quantity']
                average_price = position_info['entry_price']
                liquid_price = position_info['liquidation_price']
                direction = position_info['direction']
                if direction == 'SHORT':
                    if self._position.short_quantity != size:
                        update = True
                        self._position.update(size, average_price, 0, 0,
                                              liquid_price)
                else:
                    if self._position.long_quantity != size:
                        update = True
                        self._position.update(0, 0, size, average_price,
                                              liquid_price)
                if update and self._position_update_callback:
                    SingleTask.run(self._position_update_callback,
                                   copy.copy(self._position))