Beispiel #1
0
 async def process_kline(self, data):
     """ process kline data
     """
     if not self._klines_init:
         logger.info("klines not init. current:", len(self.klines), caller=self)
         return
     channel = data.get("ch")
     symbol = self._c_to_s[channel]
     d = data.get("tick")
     # print("process_kline", symbol)
     # print(d)
     info = {
         "platform": self._platform,
         "id": int(d["id"]),
         "symbol": symbol,
         "open": "%.8f" % d["open"],
         "high": "%.8f" % d["high"],
         "low": "%.8f" % d["low"],
         "close": "%.8f" % d["close"],
         "volume": int(d["vol"]),
         "amount": "%.8f" % d["amount"],
         "timestamp": int(data.get("ts")),
         "kline_type": MARKET_TYPE_KLINE
     }
     kline = Kline(**info)
     if kline.id == self._klines[-1].id:
         self._klines.pop()
     self._klines.append(kline)
     SingleTask.run(self._kline_update_callback, copy.copy(kline))
    def ticker(self):
        """ 启动心跳, 每interval间隔执行一次
        """
        self._count += 1

        # 打印心跳次数
        if self._print_interval > 0:
            if self._count % int(self._print_interval) == 0:
                logger.info("do server heartbeat, count:",
                            self._count,
                            caller=self)

        # 设置下一次心跳回调
        asyncio.get_event_loop().call_later(self._interval, self.ticker)

        # 执行任务回调
        for task_id, task in self._tasks.items():
            interval = task["interval"]
            if self._count % int(interval) != 0:
                continue
            func = task["func"]
            args = task["args"]
            kwargs = task["kwargs"]
            kwargs["task_id"] = task_id
            kwargs["heart_beat_count"] = self._count
            asyncio.get_event_loop().create_task(func(*args, **kwargs))
Beispiel #3
0
    async def place_orders(self):
        """ 下单
        """
        orders_data = []
        if self.trader.position and self.trader.position.short_quantity:
            # 平空单
            price = round(self.ask1_price - 0.1, 1)
            quantity = -self.trader.position.short_quantity
            action = ORDER_ACTION_BUY
            new_price = str(price)  # 将价格转换为字符串,保持精度
            if quantity:
                orders_data.append({"price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT, "lever_rate": 1})
                self.last_ask_price = self.ask1_price
        if self.trader.assets and self.trader.assets.assets.get(self.raw_symbol):
            # 开空单
            price = round(self.bid1_price + 0.1, 1)
            volume = float(self.trader.assets.assets.get(self.raw_symbol).get("free")) * price // 100 
            if volume >= 1:
                quantity = - volume #  空1张
                action = ORDER_ACTION_SELL
                new_price = str(price)  # 将价格转换为字符串,保持精度
                if quantity:
                    orders_data.append({"price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT, "lever_rate": 1})
                    self.last_bid_price = self.bid1_price

        if orders_data:
            order_nos, error = await self.trader.create_orders(orders_data)
            if error:
                logger.error(self.strategy, "create future order error! error:", error, caller=self)
            logger.info(self.strategy, "create future orders success:", order_nos, caller=self)
Beispiel #4
0
 async def on_ticker(self, *args, **kwargs):
     if not self.trade_init_result:
         logger.error("trade not init.", caller=self)
         return
     if not self.market.init_data():
         logger.error("not init market data.", caller=self)
         return
     if not self.trader.init_data():
         logger.error("not init trader data.", caller=self)
         return
     klines = self.market.klines
     if klines[-1].id == self.last_open_order_time:
         logger.info("haved order. ordertime:",
                     self.last_open_order_time,
                     caller=self)
         return
     ma_point = interval_handler(values=klines,
                                 periods=self.periods,
                                 vtype="close")
     if ma_point[self.periods[0]][1] < ma_point[self.periods[1]][1]:
         if ma_point[self.periods[0]][0] >= ma_point[self.periods[1]][0]:
             print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
                   "开多平空")
     elif ma_point[self.periods[0]][1] > ma_point[self.periods[1]][1]:
         if ma_point[self.periods[0]][0] <= ma_point[self.periods[1]][0]:
             print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
                   "开空平多")
Beispiel #5
0
 async def cancel_orders(self):
     """  取消订单
     """
     order_nos = [orderno for orderno in self.trader.orders]
     #if order_nos and self.last_mark_price != self.mark_price:
     if order_nos:
         _, errors = await self.trader.revoke_order(*order_nos)
         if errors:
             logger.error(self.strategy,
                          "cancel option order error! error:",
                          errors,
                          caller=self)
             # 出错则取消所有挂单
             _, errors = await self.trader.revoke_order()
             if errors:
                 logger.error(self.strategy,
                              "cancel all option orders error! error:",
                              errors,
                              caller=self)
             else:
                 logger.info(self.strategy,
                             "cancel all option orders success!",
                             caller=self)
         else:
             logger.info(self.strategy,
                         "cancel option order:",
                         order_nos,
                         caller=self)
Beispiel #6
0
    async def place_orders(self):
        """ 下单
        """
        orders_data = []
        if self.trader.position and self.trader.position.short_quantity:
            # 平空单
            price = round(self.mark_price - self.spread, 1)
            quantity = -self.trader.position.short_quantity
            action = ORDER_ACTION_BUY
            new_price = str(price)  # 将价格转换为字符串,保持精度
            if quantity:
                orders_data.append({"price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT })
                self.last_mark_price = self.mark_price
        if self.trader.position and self.trader.position.long_quantity:
            # 平多单
            price = round(self.mark_price + self.spread, 1)
            quantity = self.trader.position.long_quantity
            action = ORDER_ACTION_SELL
            new_price = str(price)  # 将价格转换为字符串,保持精度
            if quantity:
                orders_data.append({"price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT })
                self.last_mark_price = self.mark_price

        if self.trader.assets and self.trader.assets.assets.get(self.raw_symbol).get("free"):
            # 开空单
            if self.trader.position and  self.trader.position.short_quantity and self.trader.position.short_quantity >= self.max_quantity:
                logger.warn("option short position exceeds the max quantity: ", self.symbol, self.trader.position.short_quantity, self.max_quantity, caller=self)
            else:
                price = round(self.mark_price + self.spread, 1)
                volume = self.volume 
                if volume:
                    quantity = - volume #  空张
                    action = ORDER_ACTION_SELL
                    new_price = str(price)  # 将价格转换为字符串,保持精度
                    if quantity:
                        orders_data.append({"price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT })
                        self.last_mark_price = self.mark_price

        if self.trader.assets and self.trader.assets.assets.get(self.partition_symbol).get("free"):
            # 开多单
            if self.trader.position and  self.trader.position.long_quantity and self.trader.position.long_quantity >= self.max_quantity:
                logger.warn("option long position exceeds the max quantity: ", self.symbol, self.trader.position.long_quantity, self.max_quantity, caller=self)
            else:
                price = round(self.mark_price - self.spread, 1)
                volume = self.volume 
                if volume:
                    quantity = volume #  多张
                    action = ORDER_ACTION_BUY
                    new_price = str(price)  # 将价格转换为字符串,保持精度
                    if quantity:
                        orders_data.append({"price": new_price, "quantity": quantity, "action": action, "order_type": ORDER_TYPE_LIMIT })
                        self.last_mark_price = self.mark_price

        if orders_data:
            order_nos, error = await self.trader.create_orders(orders_data)
            if error:
                logger.error(self.strategy, "create future order error! error:", error, caller=self)
            logger.info(self.strategy, "create future orders success:", order_nos, caller=self)
Beispiel #7
0
    def start(self):
        """Start the event loop."""
        def keyboard_interrupt(s, f):
            print("KeyboardInterrupt (ID: {}) has been caught. Cleaning up...".format(s))
            self.loop.stop()
        signal.signal(signal.SIGINT, keyboard_interrupt)

        logger.info("start io loop ...", caller=self)
        self.loop.run_forever()
Beispiel #8
0
 async def cancel_orders(self):
     """  取消订单
     """
     order_nos = [ orderno for orderno in self.trader.orders ]
     if order_nos and self.last_ask_price != self.ask1_price:
         _, errors = await self.trader.revoke_order(*order_nos)
         if errors:
             logger.error(self.strategy,"cancel future order error! error:", errors, caller=self)
         else:
             logger.info(self.strategy,"cancel future order:", order_nos, caller=self)
    def on_klines_update(self, kline: Kline):
        tt = pd.to_datetime(str(kline.timestamp), unit='ms')
        # 每隔5分钟计算一次乖离率,
        if tt.minute % 2 == 0:
            logger.info("kline update:", kline, caller=self)

            mytime = pd.Timestamp(tt.year, tt.month, tt.day, tt.hour,
                                  tt.minute)
            self.df.loc[mytime, 'close'] = kline.close
            logger.info(self.df.reset_index().to_json(orient="records"))
Beispiel #10
0
 async def _connect(self):
     logger.info("url:", self._url, caller=self)
     METHOD_LOCKERS = {}
     proxy = config.proxy
     session = aiohttp.ClientSession()
     try:
         self.ws = await session.ws_connect(self._url, proxy=proxy)
     except aiohttp.client_exceptions.ClientConnectorError:
         logger.error("connect to server error! url:",
                      self._url,
                      caller=self)
         return
     asyncio.get_event_loop().create_task(self.connected_callback())
     asyncio.get_event_loop().create_task(self.receive())
Beispiel #11
0
 async def on_event_order_update(self, order: Order):
     """ 订单状态更新
     """
     logger.info("order update:", order, caller=self)
     notifyts = order.utime
     createts = order.ctime
     nowtime = time.time()
     self.total_count += 1
     if nowtime * 1000 - notifyts > 1000:
         self.exceed_1s_count += 1
         logger.error("order info:", order, caller=self)
     if nowtime * 1000 - notifyts > 100:
         self.exceed_100ms_count += 1
     if nowtime * 1000 - notifyts > 50:
         self.exceed_50ms_count += 1
 async def on_ticker(self, *args, **kwargs):
     """ 定时执行任务
     """
     ts_diff = int(time.time() * 1000) - self.last_orderbook_timestamp
     if ts_diff > self.orderbook_invalid_seconds * 1000:
         logger.warn("received orderbook timestamp exceed:",
                     self.strategy,
                     self.symbol,
                     ts_diff,
                     caller=self)
         return
     logger.info(
         f"{self.symbol}:{self.bid1_price}, {self.bid1_volume}, {self.ask1_price}, {self.ask1_volume}"
     )
     await self.cancel_orders()
     await self.place_orders()
Beispiel #13
0
def initMongodb(host="127.0.0.1", port=27017, username="", password="", dbname="admin"):
    """ Initialize a connection pool for MongoDB.

    Args:
        host: Host for MongoDB server.
        port: Port for MongoDB server.
        username: Username for MongoDB server.
        password: Username for MongoDB server.
        dbname: DB name to connect for, default is `admin`.
    """
    if username and password:
        uri = "mongodb://{username}:{password}@{host}:{port}/{dbname}".format(username=quote_plus(username),
                                                                              password=quote_plus(password),
                                                                              host=quote_plus(host),
                                                                              port=port,
                                                                              dbname=dbname)
    else:
        uri = "mongodb://{host}:{port}/{dbname}".format(host=host, port=port, dbname=dbname)
    mongo_client = motor.motor_asyncio.AsyncIOMotorClient(uri)
    global MONGO_CONN
    MONGO_CONN = mongo_client
    logger.info("create mongodb connection pool.")
Beispiel #14
0
    async def process_hist_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)
        logger.info(data)
Beispiel #15
0
 async def on_event_position_update(self, position: Position):
     """ 仓位更新
     """
     logger.info("position update:", position, caller=self)
Beispiel #16
0
 async def on_event_asset_update(self, asset: Asset):
     """ 资产更新
     """
     logger.info("asset update:", asset, caller=self)
Beispiel #17
0
 async def on_event_order_update(self, order: Order):
     """ 订单状态更新
     """
     logger.info("order update:", order, caller=self)
Beispiel #18
0
    def _update_order(self, order_info):
        # print("_update_order")
        # print(order_info)
        if order_info["symbol"] != self._symbol:
            return
        if order_info["contract_type"] != self._contract_type:
            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,
                "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

        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):
        """ 初始化
        """
        self.strategy = config.strategy
        self.platform = config.accounts[0]["platform"]
        self.account = config.accounts[0]["account"]
        self.access_key = config.accounts[0]["access_key"]
        self.secret_key = config.accounts[0]["secret_key"]
        self.host = config.accounts[0]["host"]
        self.wss = config.accounts[0]["wss"]
        self.symbol = config.symbol
        self.contract_type = config.contract_type
        self.channels = config.markets[0]["channels"]
        self.orderbook_length = config.markets[0]["orderbook_length"]
        self.orderbooks_length = config.markets[0]["orderbooks_length"]
        self.klines_length = config.markets[0]["klines_length"]
        self.trades_length = config.markets[0]["trades_length"]
        self.market_wss = config.markets[0]["wss"]

        self.contract_size = 0.01
        self.orderbook_invalid_seconds = 10

        self.last_bid_price = 0  # 上次的买入价格
        self.last_ask_price = 0  # 上次的卖出价格
        self.last_orderbook_timestamp = 0  # 上次的orderbook时间戳

        # self.raw_symbol = self.symbol.split('-')[0]

        self.ask1_price = 0
        self.bid1_price = 0
        self.ask1_volume = 0
        self.bid1_volume = 0

        self.tradeema = TradeEMA()

        # # 交易模块
        # cc = {
        #     "strategy": self.strategy,
        #     "platform": self.platform,
        #     "symbol": self.symbol,
        #     "contract_type": self.contract_type,
        #     "account": self.account,
        #     "access_key": self.access_key,
        #     "secret_key": self.secret_key,
        #     "host": self.host,
        #     "wss": self.wss,
        #     "order_update_callback": self.on_event_order_update,
        #     "asset_update_callback": self.on_event_asset_update,
        #     "position_update_callback": self.on_event_position_update,
        #     "init_success_callback": self.on_event_init_success_callback,
        # }
        # self.trader = Trade(**cc)

        # 行情模块

        for s in self.symbol:
            logger.info(s)
            cc = {
                "platform": self.platform,
                "symbols": [s],
                "channels": self.channels,
                "orderbook_length": self.orderbook_length,
                "orderbooks_length": self.orderbooks_length,
                "klines_length": self.klines_length,
                "trades_length": self.trades_length,
                "wss": self.market_wss,
                "orderbook_update_callback": self.on_event_orderbook_update,
                "kline_update_callback": self.on_event_kline_update,
                "trade_update_callback": self.on_event_trade_update
            }
            market = Market(**cc)

        # 60秒执行1次
        LoopRunTask.register(self.on_ticker, 10)
 def _get_version(self):
     """ get software version
     """
     logger.info("version:", VERSION, caller=self)
 def stop(self):
     """Stop the event loop."""
     logger.info("stop io loop.", caller=self)
     self.loop.stop()
Beispiel #22
0
async def cur_ts(**kwargs):
    logger.info(ts_to_datetime_str())
Beispiel #23
0
 def stop(self):
     """Stop the event loop."""
     logger.info("Stop \"{}\" io loop.".format(config.project), caller=self)
     self.loop.stop()
Beispiel #24
0
    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)
Beispiel #25
0
    async def delta_hedging(self, *args, **kwargs):
        """ delta hedge
        """
        logger.debug("delta hedging", caller=self)
        option_delta = 0
        assets, error = await self.trader.rest_api.get_asset_info(
            self.raw_symbol)
        if error:
            logger.error(self.strategy,
                         "get option asset error! error:",
                         error,
                         caller=self)
        else:
            for item in assets["data"]:
                if item["symbol"] == self.raw_symbol:
                    o_margin_balance = item["margin_balance"]
                    o_delta = item["delta"]
                    o_gamma = item["gamma"]
                    o_theta = item["theta"]
                    o_vega = item["vega"]
                    option_delta = o_delta + o_margin_balance

            #增加delta对冲,使用期货对冲。
            accounts, error = await self.future_trader.rest_api.get_account_position(
                self.raw_symbol)
            if error:
                logger.error(self.strategy,
                             "get future account and position error! error:",
                             error,
                             caller=self)
            else:
                margin_balance = accounts["data"][0]["margin_balance"]
                long_position = 0
                short_position = 0
                delta_long = 0
                delta_short = 0
                long_last_price = 0
                short_last_price = 0
                for position in accounts["data"][0]["positions"]:
                    if position["direction"] == "buy":
                        long_position = position["volume"]
                        long_cost_open = position["cost_open"]
                        long_last_price = position["last_price"]
                    if position["direction"] == "sell":
                        short_position = position["volume"]
                        short_cost_open = position["cost_open"]
                        short_last_price = position["last_price"]
                if long_position:
                    delta_long = self.future_volume_usd * int(
                        long_position) / float(long_last_price)
                if short_position:
                    delta_short = self.future_volume_usd * int(
                        short_position) / float(short_last_price)
                future_delta = margin_balance - delta_short + delta_long
                t_delta = option_delta + future_delta
                orders_data = []
                # 对冲对应数量的币
                if abs(t_delta) >= self.delta_limit:
                    if t_delta > 0:
                        # 开空单
                        price = 0
                        volume = int(t_delta * long_last_price /
                                     self.future_volume_usd)
                        if volume:
                            quantity = -volume  #
                            action = ORDER_ACTION_SELL
                            new_price = str(price)  # 将价格转换为字符串,保持精度
                            if quantity:
                                orders_data.append({
                                    "price":
                                    new_price,
                                    "quantity":
                                    quantity,
                                    "action":
                                    action,
                                    "order_type":
                                    ORDER_TYPE_MARKET
                                })
                    else:
                        # 开多单
                        price = 0
                        volume = abs(
                            int(t_delta * long_last_price /
                                self.future_volume_usd))
                        if volume:
                            quantity = volume  #
                            action = ORDER_ACTION_BUY
                            new_price = str(price)  # 将价格转换为字符串,保持精度
                            if quantity:
                                orders_data.append({
                                    "price":
                                    new_price,
                                    "quantity":
                                    quantity,
                                    "action":
                                    action,
                                    "order_type":
                                    ORDER_TYPE_MARKET
                                })

                if orders_data:
                    order_nos, error = await self.future_trader.create_orders(
                        orders_data)
                    if error:
                        logger.error(self.strategy,
                                     "create future order error! error:",
                                     error,
                                     caller=self)
                    else:
                        logger.info(self.strategy,
                                    "create future orders success:",
                                    order_nos,
                                    caller=self)