Exemple #1
0
    def handle_remain_orders(self, bs, price):
        ideal_order_in_active = False
        for coid, o in list(self.active_orders.items()):
            if bs != o.bs:
                continue
            if price == o.entrust_price and not o.last_cancel_time:
                ideal_order_in_active = True
            else:
                now = arrow.now().float_timestamp
                if not o.first_cancel_time:
                    o.first_cancel_time = now
                factor = self.active_orders[coid].cancel_times + 1
                if not o.last_cancel_time or now - o.last_cancel_time > self.config.cancel_order_interval * factor:
                    if o.eoid:
                        qb.fut(self.cancel_order(eoid=o.eoid))
                    else:
                        qb.fut(self.cancel_order(coid=o.coid))
                    self.active_orders[coid].last_cancel_time = now
                    self.active_orders[coid].cancel_times += 1
                    if self.active_orders[
                            coid].cancel_times > self.config.max_cancel_times:
                        logging.warning(
                            f'{o.coid} {o.eoid} cancel times exceed limit')
                        self.active_orders.pop(o.coid, None)

        return ideal_order_in_active
Exemple #2
0
    async def do_action(self, bs: str, price: float, amt: float,
                        force_maker: bool):
        ideal_order_in_active = self.handle_remain_orders(bs, price)
        if ideal_order_in_active:
            return

        if len(self.active_orders) > self.config.max_pending_orders:
            return

        now = arrow.now().float_timestamp
        if now - self.last_trade_time < self.config.trade_interval:
            return
        else:
            self.last_trade_time = now
        if await self.rc_work():
            return

        if bs == 'b':
            amt = min(self.tk2.asks[0][1], self.config.place_amt)
        elif bs == 's':
            amt = min(self.tk2.bids[0][1], self.config.place_amt)

        opt = self.get_options(self.c1, bs, amt, force_maker=force_maker)
        coid = self.new_coid(self.c1, bs)
        o = Order()
        o.coid = coid
        o.entrust_price = price
        o.bs = bs
        o.entrust_amount = amt
        o.entrust_time = arrow.now().float_timestamp
        o.opt = opt
        ext = Extra()
        ext.tk1_bbo_place = self.tk1
        ext.tk2_bbo_place = self.tk2
        o.extra = ext
        self.active_orders[coid] = o
        qb.fut(self.place_maker_order(o))
Exemple #3
0
    async def run(self):
        await self.init()
        await self.update_info()
        self.asset_by_ws = self.asset_by_rest
        self.pos_by_ws = self.pos_by_rest
        await self.cancel_all()
        await self.config.sync()
        while True:
            await asyncio.sleep(1)
            if len(self.ticks) + len(self.bbo) != 2:
                logging.warning('waiting tick comes')
                continue
            else:
                break
        self.inited = True
        logging.info("all inited, start...")

        qb.fut(self.daemon_consume_update_bbo())

        qb.fut(qb.autil.loop_call(self.update_info, 30, panic_on_fail=False))
        qb.fut(qb.autil.loop_call(self.config.sync, 30))
        qb.fut(qb.autil.loop_call(self.match_pos, 10))
Exemple #4
0
    def __enter__(self):
        self.start = arrow.now()

    def __exit__(self, *args, **kwargs):
        self.end = arrow.now()
        key = 'elapse'
        diff = (self.end - self.start).total_seconds()
        timerInflux.add_point(key=key, tags=self.tags, fields={'value': diff})


async def main():
    print('main')
    # s = Strategy(stid=stid)
    # await s.run()


async def play():
    print('play demo')


if __name__ == '__main__':
    qb.init(env='prod')
    docopt = docoptinit(__doc__)
    stid = str(docopt['--stid'])
    logging.info(f'stid: {stid}')
    if docopt['--play']:
        qb.fut(play())
    else:
        qb.fut(main())
    qb.run_forever()
Exemple #5
0
    async def order_callback(self, orig: qbxt.model.OrderUpdate):
        order = orig.order
        if order.contract == self.c1:
            # 如果不在程序肯定有问题
            order_in_memory = self.active_orders.get(order.client_oid, None)
            if not order_in_memory:
                logging.warning(
                    f'{order.client_oid}, {order.exchange_oid} not in active orders'
                )
                return
            now = arrow.now().float_timestamp
            elapse = now - order_in_memory.entrust_time
            if order_in_memory.first_cancel_time:
                elapse = now - order_in_memory.first_cancel_time
            self.gauge('order-elapse', elapse, tags={'status': order.status})
        if order.status == qbxt.model.Order.PENDING and order.contract == self.c1:
            return

        if 'deal' in order.status and order.contract == self.c1:
            # 如果不在程序肯定有问题
            order_in_memory = self.active_orders.get(order.client_oid, None)
            if not order_in_memory:
                logging.warning(
                    f'{order.client_oid}, {order.exchange_oid} not in active orders'
                )
                return
            amt = order.dealt_amount - order_in_memory.dealt_amt
            self.active_orders[order.client_oid].dealt_amt = order.dealt_amount

            self.active_orders[order.client_oid].extra.tk1_bbo_dealt = self.tk1
            self.active_orders[order.client_oid].extra.tk2_bbo_dealt = self.tk2

            if amt > 0:
                bs = 'b' if order.bs == 's' else 's'
                qb.fut(
                    self.place_hedge_order(bs, amt, order.average_dealt_price))

                # c2_price = self.tk2.bid1 if order.bs == 'b' else self.tk2.ask1
                self.gauge('place-price',
                           order.entrust_price, {'bs': order.bs},
                           ts=order_in_memory.entrust_time)
                self.gauge('dealt-amt', amt, tags={'bs': order.bs})
                self.gauge_order_extra(self.active_orders[order.client_oid])
        if order.status == qbxt.model.Order.DEALT and order.contract == self.c2:
            c1_dealt_price = self.dealt_info.get(order.client_oid, None)
            if c1_dealt_price:
                self.gauge('dealt-diff',
                           c1_dealt_price / order.average_dealt_price,
                           tags={'bs': qb.util.op_bs(order.bs)})
                self.dealt_info.pop(order.client_oid, None)

        if 'deal' in order.status:
            con = 'tick1' if order.contract == self.c1 else 'tick2'
            self.gauge('dealt',
                       order.average_dealt_price,
                       tags={
                           'bs': order.bs,
                           'con_symbol': order.contract,
                           'con': con
                       })

        if order.status in qbxt.model.Order.END_SET and order.contract == self.c1:
            self.active_orders.pop(order.client_oid, None)
        return
Exemple #6
0
    async def main_callback(self):
        if not self.inited:
            return
        value = {
            'tk1-bid1': self.tk1.bid1,
            'tk1-ask1': self.tk1.ask1,
            'tk2-bid1': self.tk2.bid1,
            'tk2-ask1': self.tk2.ask1,
            'tk-diff': self.tk1.middle / self.tk2.middle,
            'bid-d-ask': self.tk1.bid1 / self.tk2.ask1,
            'ask-d-bid': self.tk1.ask1 / self.tk2.bid1
        }
        self.gauge('quote', value)
        core = math.pow(self.config.diff,
                        -self.pos1 / self.config.amt) * self.config.middle

        core_a = self.tk2.ask1 * core
        core_b = self.tk2.bid1 * core
        # logging.info('c2: ',self.tk2.ask1/self.tk2.bid1)
        # logging.info('core_a/core_b: ',core_a/core_b)
        pb = core_b / math.sqrt(self.config.earn) * self.config.taker_return
        ps = core_a * math.sqrt(self.config.earn) / self.config.taker_return
        # logging.info('ps/pb:',ps,pb, ps/pb)
        tb = pb * self.config.taker_return
        ts = ps / self.config.taker_return
        tb = self.rounding(tb, self.min_change(self.c1), math.floor)
        ts = self.rounding(ts, self.min_change(self.c1), math.ceil)

        # mb = min(self.tk1.aks1- self.min_change(self.c1), pb * self.config.maker_return)
        # ms = max(self.tk1.bid1+ self.min_change(self.c1), ps / self.config.maker_return)
        # logging.info('before rounding', mb,ms, ms/mb)
        mb = pb * self.config.maker_return
        ms = ps / self.config.maker_return
        mb = self.rounding(mb, self.min_change(self.c1), math.floor)
        ms = self.rounding(ms, self.min_change(self.c1), math.ceil)
        # logging.info('after rouding', mb,ms, ms/mb)

        self.gauge('core', core)
        self.gauge('diff-ideal-b', {
            'maker': mb / self.tk2.bid1,
            'taker': tb / self.tk2.bid1
        })
        self.gauge('diff-ideal-s', {
            'maker': ms / self.tk2.ask1,
            'taker': ts / self.tk2.ask1
        })
        # pass
        if dryrun:
            return
        if self.pos1 < self.config.amt:
            if tb >= self.tk1.ask1:
                # logging.info(f'try to place taker b {tb}')
                qb.fut(self.do_action('b', tb, self.config.place_amt, False))
            else:
                mb = min(mb, self.tk1.bid1)
                qb.fut(
                    self.do_action('b', mb, self.config.place_amt,
                                   self.config.force_maker))
        if -self.config.amt < self.pos1:
            if ts <= self.tk1.bid1:
                # logging.info(f'try to place taker s {ts}')
                qb.fut(self.do_action('s', ts, self.config.place_amt, False))
            else:
                ms = max(ms, self.tk1.ask1)
                qb.fut(
                    self.do_action('s', ms, self.config.place_amt,
                                   self.config.force_maker))
        return
Exemple #7
0
 def rc_trigger(self, second, reason):
     if not self.rc_working:
         qb.fut(self.cancel_all())
         logging.warning('rc trigger', reason, second, self.rc_until)
         self.gauge('rc-work', 1, {'type': reason})
     self.rc_until = max(self.rc_until, arrow.now().shift(seconds=second))