For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

CCXTbt make market order if limit order is not filled in X minutes



  • Hi, I am using ccxtbt to trade on Binance. I use limit orders and trade on 1, 2 and 4 hour candles. Occasionally, limit orders might not get filled and I want to add a condition to the ccxtbroker "next" method to send market orders if the limit order is not filled within 2-3 minutes.

    Buy/sell methods take owner, data, size and exectype parameters, so I was wondering how would I specify them within the next() of the CCXTBroker class?

    My code goes in the next function after this comment: # execute order with market if limit is not filled after X amount of time

    Can anyone suggest how would I properly cancel existing limit order and create a new market buy/sell order?

    self.buy(self, owner, data, size, exectype)
    
        def next(self):
            if self.debug:
                print('Broker next() called')
    
            for o_order in list(self.open_orders):
                oID = o_order.ccxt_order['id']
    
                # Print debug before fetching so we know which order is giving an
                # issue if it crashes
                if self.debug:
                    print('Fetching Order ID: {}'.format(oID))
    
                # Get the order
                ccxt_order = self.store.fetch_order(oID, o_order.data.p.dataname,
                                                    params={'type': 'future'})  # ADDED PARAMS HERE
                # Check for new fills
                if self.debug:
                    print(f'checking for trades in ccxt_order - ccxt_order is {ccxt_order}')
    
                if ccxt_order['trades'] is not None:  # added explicit check for None otherwise it was proceeding
    
                    if self.debug:
                        print('reading trades in ccxt_order')
    
                    for fill in ccxt_order['trades']:
                        if fill not in o_order.executed_fills:
                            o_order.execute(fill['datetime'], fill['amount'], fill['price'],
                                            0, 0.0, 0.0,
                                            0, 0.0, 0.0,
                                            0.0, 0.0,
                                            0, 0.0)
                            o_order.executed_fills.append(fill['id'])
    
                # execute order with market if limit is not filled after X amount of time
                if float(ccxt_order['info']['executedQty']) < abs(float(ccxt_order['info']['origQty'])):
                    now = datetime.utcnow()
                    time_created = datetime.strptime(ccxt_order['datetime'][:-5], '%Y-%m-%dT%H:%M:%S')
                    timedelta_diff = now - time_created
                    
                    diff_s = timedelta_diff.total_seconds() / 60
                    print(f'time now: {now}, order time {time_created} and diff: {diff_s}')
                    
                    if diff_s > 0.1:
                        print(f'difference is greater than {diff_s} seconds - make market order')
                        
                        # cancel the limit order here
                        self.cancel(ccxt_order, params={'type': 'future'})
                        self.open_orders.remove(o_order)
                        o_order.cancel()
                        self.notify(o_order)
                        
                        if ccxt_order['side'] == 'buy':
                            print('send market buy order')
                            # market_order = self.buy(size=o_order.size, exectype='market')
                        elif ccxt_order['side'] == 'sell':
                            print('send market sell order')
                            # market_order = self.sell(size=o_order.size, exectype='market')
    
                if self.debug:
                    print(json.dumps(ccxt_order, indent=self.indent))
    
                # Check if the order is closed
                if ccxt_order[self.mappings['closed_order']['key']] == self.mappings['closed_order']['value']:
                    # https://github.com/Dave-Vallance/bt-ccxt-store/compare/master...robobit:master
                    # check if order is closed and add commission info
                    if self.debug:
                        print('checking for closed status to notify of trade')
                    pos = self.getposition(o_order.data, clone=False)
                    pos.update(o_order.size, o_order.price)
                    o_order.completed()
                    self.notify(o_order)
                    self.open_orders.remove(o_order)
                    self.get_balance()
    
                # Manage case when an order is being Canceled from the Exchange
                #  from https://github.com/juancols/bt-ccxt-store/
                if ccxt_order[self.mappings['canceled_order']['key']] == self.mappings['canceled_order']['value']:
                    self.open_orders.remove(o_order)
                    o_order.cancel()
                    self.notify(o_order)
    

    Thanks a lot!



  • Hello @Dimasik007 ! Maybe you should use the valid parameter for creating your orders (https://www.backtrader.com/docu/order/#order-creation)

    for example when the buy order is filled, on notify_trade function you can create a sell order with a valid in datetime (+ 2/3 minutes)



  • Hi @balibou ! thanks for your reply and suggestion. valid unfortunately doesn't work because it's not implemented in the ccxtbt. But thanks to your suggestion I decided to create limit orders in the next and add a variable valid which I am using to check how long the order was on the order book and if it wasn't filled in the required time, I am creating a new market order from the notify_order.

    The problem now is that when I am using a market order, it's executing immediately and I can't get back into the notify order until the next candle. I am using around 10 orders to scale into position when the signal is generated, so I am still stuck. If there are any other suggestions on how to solve this or that question, I would really appreciate anyones help.


Log in to reply
 

});