Execute on bid/ask



  • First of all, many thanks to the developer and the contributors to this project!

    Hopefully somebody can help me with a problem I have and can't seem to be able to fix. I've got intra day bid/ask index data (sampled every 5 seconds for now), and I am trying to figure out how to properly execute on the bid or the offer at the next bid/ask quote coming in after order creation.

    Currently, I can sell the bid (market sell order) on the next quote, but the order to buy the offer is only executed at 23:59:55, at the end of the day (even when order creation was much earlier).

    Here is my data feed class:

    class BidAskCSV(btfeeds.GenericCSVData):
        linesoverride = True
        lines = ('bid', 'ask', 'datetime', 'close', 'open', 'high', 'low')
        params = (('datetime', 0), ('bid', 2), ('ask', 3), ('close', 3), ('open', 2), ('low', 2), ('high',3))
    
        def __init__(self):
            super(BidAskCSV, self).__init__()
    

    And some toy order creation/execution logic in a strategy class:

    
            # Check if we are in the market
            position = self.getposition(data=self.datas[0])
            rand = random.random()
            if rand < 0.2:
                if position:
                    # SELL (with all possible default parameters)
                    self.log('SELL CREATE {}'.format(self.datas[0].bid[0]))
    
                    # Keep track of the created order to avoid a 2nd order
                    self.order = self.sell(data=self.datas[0])
            elif rand > 0.8:
                if not position:
                    # BUY (with all possible default parameters)
                    self.log('BUY CREATE {}'.format(self.datas[0].ask[0]))
    
                    # Keep track of the created order to avoid a 2nd order
                    self.order = self.buy(data=self.datas[0], exectype=bt.Order.Close)
    

    The sell order gets executed on the bid of the next quote. It is a market order and the 'open' price is set to the bid-column of my data in the data feed class. Everything is fine so far....

    But, for buy orders I am trying to take the offer with a 'close' order (the 'close' price being set to the ask column). However, this order gets executed at 23:59:55 and not at the quote following the order generation. I would like it to be executed at the offer of the following quote that comes in.

    Should I be using a different order type, structure the CSV differently, is there an extra parameter to pass, etc? I much appreciate any help!

    Cheers,
    N


  • administrators

    Glad to see that linesoverride has found a use case.

    The problem here is the interpretation of the execution type Order.Close you are making. This is not going to give you the close price of a specific bar. It is meant to give you the close price which corresponds to the end of the session.

    Each broker/platform has a naming for it. Interactive Brokers, for example, calls it Market-On-Close or MOC.

    See the description: https://www.interactivebrokers.com/en/index.php?f=599

    Quoting directly from the BackBroker (the simulation broker in backtrader):

    • Close: meant for intraday in which the order is executed with the closing price of the last bar of the session

    Or directly at the documentation: Docs - Broker

    This order execution type is for intraday data and will be translated to the proper order type if you decide to connect to a live broker (in the aforementioned Interactive Brokers case it will be translated to MOC)

    If you wish to get the close price of the bar at which the order is generated (your ask price) you have to activate the cheat-on-close mode in the broker and then simply issue a Market order, which is the default.

    See here for example: https://community.backtrader.com/topic/15/convincing-strategy-to-buy-at-close-of-current-bar-in-backtest

    Or directly at the docs: https://www.backtrader.com/docu/broker.html?highlight=cheat



  • @backtrader
    Many thanks for your reply! I experimented with the coc parameter:

    cerebro.broker.set_coc(True)
    

    This does execute a market buy order on the offer, but at the same time will also execute a market sell order on the offer price. However, the behaviour I am after is to execute a buy order on the offer and a sell order on the bid.

    An idea I've got is to just rework my data to represent the midpoint of the bid/ask data, use the cheat-on-close param and allow for the spread in the form of an extra commission charge.

    Cheers,
    N


  • administrators

    This really grants a small addition to the broker, because by activating cheat-on-close you get twice the closing price, and the 2nd price you want is the incoming opening price.

    Let's add the possibility to selectively disable coc for orders. Your sell action would now be as follows:

     self.order = self.sell(data=self.datas[0], coc=False)
    

    In regular code with coc deactivated, this plays no role. But if you activate it to get the closing price of the bar for your buy, the sell deactivates it to make sure the execution waits until the next bar.

    In the development branch now with this commit id: 959f6cf46623d750c73f75bde9457269b0d4aed2



  • This is great, thank you very much!


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.