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

Order Execution Price NAN - single column pandas data input



  • I am testing a very basic hello world script the exception being that I am using a single column pandas dataframe as my data source (because that is what I am using as the input for my strategy).

    Everything appears to be working fine, except that my the order object inside the loop shows price=nan and throws off the loop. When I check the value of the portfolio at the end of the script, it is nan. I'm assuming it is related to my data source but I cannot find the error looking through the source code.

        cerebro = bt.Cerebro()
        cerebro.addstrategy(EMACross, fast_period=11, slow_period=25)
    
        # Make data object - we only have a "close" in column 0
        data = bt.feeds.PandasData(dataname=btc_df, open=None, high=None, 
        low=None, close=0, volume=None, openinterest=None)
    
        cerebro.adddata(data) # add data to engine
        cerebro.run()
        cerebro.broker.getvalue()
    

    At this point, everything runs and prints to the console, the first order produces

    "> BUY EXECUTED, nan"

    Then, every order after produces a Rejected, Cancelled, Margin error.

    Here is my strategy object, you can see I am passing in size and price to the order function -

    class EMACross(bt.Strategy):
    
        def __init__(self, fast_period, slow_period):
            self.dataclose = self.datas[0].close
            self.order = None
            self.fastma = bt.ind.ExponentialMovingAverage(self.datas[0], period=fast_period)
            self.slowma  = bt.ind.ExponentialMovingAverage(self.datas[0], period=slow_period)
            self.buysig  = bt.ind.CrossOver(self.fastma, self.slowma)
            self.sellsig = bt.ind.CrossDown(self.fastma, self.slowma)
    
    
        def log(self, txt, dt=None):
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
    
        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                return
    
            if order.status in [order.Completed]:
                if order.isbuy():
                    self.log('BUY EXECUTED, %.2f' % order.executed.price)
                elif order.issell():
                    self.log('SELL EXECUTED, %.2f' % order.executed.price)
    
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Cancelled/Margin/Rejected')
    
            self.order = None
    
        def next(self):
            self.log('Close, %.2f' % self.dataclose[0])
    
            if self.order:
                return
    
            # Initial Order
            if not self.position:
                if self.buysig > 0:
                    self.log('BUY CREATE, %.2f' % self.dataclose[0])
                    self.order = self.buy(size=1, price=self.dataclose[0])
                    return
                elif self.sellsig > 0:
                    self.log('SELL CREATE, %.2f' % self.dataclose[0])
                    self.order = self.sell(size=1, price=self.dataclose[0])
                    return
                else: return
    
            # Find out if we are long or short
            side = self.position.size
            if side > 0: # we are long
                if self.sellsig > 0:
                    self.order = self.sell(size=2, price=self.dataclose[0])
                else:
                    return
    
            else:
                if self.buysig > 0:
                    self.order = self.buy(size=2, price=self.dataclose[0])
                else:
                    return
    
            return
    
    

    Any help is very much appreciated!! I've been debugging this for several hours. My first time using backtrader.


  • administrators

    See at the top

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

  • administrators

    See Docs - Order Execution and Management

    You want to see how Market orders are executed. This:

    @jmarks512 said in Order Execution Price NAN - single column pandas data input:

    self.order = self.buy(size=1, price=self.dataclose[0])
    

    is impossibility. You cannot specify the execution price of a Market order. Provide an opening price (you probably do also want to provide a high and low)



  • Makes perfect sense. I was able to get execution by specifying exectype=bt.Order.Close

    Thank you for the help!


  • administrators

    I think you are pretty new to trading and should take some time to understand things and grasp the concepts. Specifying exectype=bt.Order.Close has only done something which doesn't have the effect you are looking for.

    That order execution type is intended for intraday data, for orders which are issued before the trading day is over and which will be executed with the closing tick (in the most well known exchanges it does execute at the end of the auction which follows the end of regular trading)

    What you need:

    • Provide an open price (it can be the same as the close if you don't have any other) to get something realistic

    or

    • Activatecheat-on-close and work with the current close (it is calledcheat for a reason)