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

Why is the self.position always zero ?



  • Dear friend, I use a minute level data to backtest , I set the buy condition: if not self.position , but the position is always zero,but if I use the dayly level data, there are no problem. The data is from the sample . I can 't find the cause. can you help me? Thanks a lot.

    from __future__ import (absolute_import, division, print_function,unicode_literals)
    import backtrader as bt
    import backtrader.indicators as btind
    import backtrader.feeds as btfeeds
    
    import datetime
    import os.path
    import sys
    
    class Mytest(bt.Strategy):
        params = (('fast',5),('slow',20),)
        lines = ('fast','slow',)
    
        def log(self,txt,dt = None):
            '''log function for this strategy'''
            dt = dt or self.data.datetime[0]
            if isinstance(dt,float):
                dt = bt.num2date(dt)
            print('%s %s' % (dt.isoformat(),txt))
        def __init__(self):
             # To control operation entries
            self.order = None
     
            self.lines.fast = btind.SimpleMovingAverage(period = self.p.fast)
            self.lines.slow = btind.SimpleMovingAverage( period = self.p.slow)
    
            self.buysig = btind.CrossOver(self.lines.fast,self.lines.slow)
    
        def notify_order(self,order):
            if order.status in [order.Submitted, order.Accepted]:
                #buy/sell order have been submitted, nothing to do 
                return 
            self.order = None
    
        def next(self):
            if self.order:
                return  # if an order is active, no new orders are allowed
            
            self.log(self.getposition().size)# always get the zero result. why?
            if not self.position:
                if self.buysig[0] > 0:
                        self.order = self.buy(size = 100)
                        self.log('buy')
                
            else: 
                 if self.buysig[0] < 0:
                    self.order = self.sell(size = 100)
                    self.log('sell')
    
    def runstrategy():
        #args = parse_args()
    
        #create a cerebro
        cerebro = bt.Cerebro()
    
        #get the dates from the args
        #fromdate = datetime.datetime.striptime(args.fromdate,'%Y-%m-%d')
        fromdate = datetime.datetime(2006,1,2)
        #today = datetime.datetime.striptime(args.today,'%Y-%m-%d')
        today = datetime.datetime(2006,2,10)
    
        modpath=os.path.dirname(os.path.abspath(sys.argv[0]))
        datapath = os.path.join(modpath,'datas/2006-01-02-volume-min-001.txt')
        #datapath = os.path.join(modpath,'datas/yhoo-1996-2015.txt')
    
    
        data = btfeeds.BacktraderCSVData(
            dataname = datapath,
            frmodate = fromdate,
            today = today,
            timeframe=bt.TimeFrame.Minutes,
            compression = 1
            )
    
        #cerebro.adddata(data)
        cerebro.resampledata(data,
                             timeframe =  bt.TimeFrame.Minutes,
                             compression = 60,
                             )
    
        cerebro.addstrategy(Mytest)
    
        cerebro.broker.setcash(10000)
        cerebro.broker.setcommission(0.01)
        #cerebro.addsizer(bt.sizers.FixedSize,stake = 100)
    
        cerebro.run()
    
        cerebro.plot()
    
    if __name__ == '__main__':
        runstrategy()
    


  • self.position is always zero because the position is never open. it can be variety of reasons: you can't buy/sell 100 shares due to lack of funds, SMA don't cross etc. Get more outputs and check what is going on.



  • I changed the cash 100000. and the log is :
    2006-01-06T12:00:00 buy
    2006-01-06T12:00:00 0
    2006-01-09T22:00:00 buy
    2006-01-09T22:00:00 0
    2006-01-11T11:00:00 buy
    2006-01-11T11:00:00 0
    2006-01-12T18:00:00 buy
    2006-01-12T18:00:00 0
    2006-01-16T14:00:00 buy
    2006-01-16T14:00:00 0
    2006-01-19T12:00:00 buy
    2006-01-19T12:00:00 0
    2006-01-24T11:00:00 buy
    2006-01-24T11:00:00 0
    2006-01-31T19:00:00 buy
    2006-01-31T19:00:00 0
    2006-02-03T21:00:00 buy
    2006-02-03T21:00:00 0
    2006-02-08T17:00:00 buy
    2006-02-08T17:00:00 0
    2006-02-13T18:00:00 buy
    2006-02-13T18:00:00 0
    2006-02-15T17:00:00 buy
    2006-02-15T17:00:00 0
    2006-02-16T13:00:00 buy
    2006-02-16T13:00:00 0
    2006-02-20T20:00:00 buy
    2006-02-20T20:00:00 0
    2006-02-22T15:00:00 buy
    2006-02-22T15:00:00 0



  • Your trying to buy 100 shares at 3,600 per share with $10,000. That's always going to be a problem. Try using 1 share or putting a lot of money in the account.

    Try adding in these to get more information:

        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                return
    
            # Check if an order has been completed
            # Attention: broker could reject order if not enougth cash
            if order.status in [order.Canceled, order.Margin]:
                if order.isbuy():
                    self.log("BUY FAILED, Cancelled or Margin")
                self.log
            if order.status in [order.Completed, order.Canceled, order.Margin]:
                if order.isbuy():
                    self.log(
                        "BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f"
                        % (order.executed.price, order.executed.value, order.executed.comm)
                    )
    
                    self.buyprice = order.executed.price
                    self.buycomm = order.executed.comm
                else:  # Sell
                    self.log(
                        "SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f"
                        % (order.executed.price, order.executed.value, order.executed.comm)
                    )
    
                self.bar_executed = len(self)
    
            # Write down: no pending order
            self.order = None
    
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            self.log("OPERATION PROFIT, GROSS %.2f, NET %.2f" % (trade.pnl, trade.pnlcomm))
    

    Also maybe print out a OHLC log like this:

    self.log(
                "o {:5.2f}\th {:5.2f}\tl {:5.2f}\tc {:5.2f}\tv {:5.0f}".format(
                    self.datas[0].open[0],
                    self.datas[0].high[0],
                    self.datas[0].low[0],
                    self.datas[0].close[0],
                    self.datas[0].volume[0],
                )
            )
    

    Finally, if you just want to close out your long position, use self.close, not self.sell.



  • Thank You ! I got it .
    I run as your code , the log is :
    2006-01-06T12:00:00 buy
    2006-01-06T13:00:00 Buy Execute, Price: 3670,Cost:3670,Comm 36.70 ,position 1
    2006-01-09T22:00:00 Sell Execute, Price: 3684,Cost:3670,Comm 36.84 position 0
    2006-01-09T22:00:00 OPERATION PROFIT ,GROSS 14.00,Net -59.54
    2006-01-09T22:00:00 buy
    2006-01-10T10:00:00 Buy Execute, Price: 3676,Cost:3676,Comm 36.76 ,position 1
    2006-01-10T11:00:00 Sell Execute, Price: 3663,Cost:3676,Comm 36.63 position 0
    2006-01-10T11:00:00 OPERATION PROFIT ,GROSS -13.00,Net -86.39
    2006-01-11T11:00:00 buy
    2006-01-11T12:00:00 Buy Execute, Price: 3677,Cost:3677,Comm 36.77 ,position 1
    2006-01-12T15:00:00 Sell Execute, Price: 3670,Cost:3677,Comm 36.70 position 0
    2006-01-12T15:00:00 OPERATION PROFIT ,GROSS -7.00,Net -80.47
    2006-01-12T18:00:00 buy
    2006-01-12T19:00:00 Buy Execute, Price: 3687,Cost:3687,Comm 36.87 ,position 1
    2006-01-13T10:00:00 Sell Execute, Price: 3666,Cost:3687,Comm 36.66 position 0
    2006-01-13T10:00:00 OPERATION PROFIT ,GROSS -21.00,Net -94.53
    2006-01-16T14:00:00 buy
    2006-01-16T15:00:00 Buy Execute, Price: 3647,Cost:3647,Comm 36.47 ,position 1
    2006-01-17T13:00:00 Sell Execute, Price: 3624,Cost:3647,Comm 36.24 position 0
    2006-01-17T13:00:00 OPERATION PROFIT ,GROSS -23.00,Net -95.71
    2006-01-19T12:00:00 buy
    2006-01-19T13:00:00 Buy Execute, Price: 3597,Cost:3597,Comm 35.97 ,position 1
    2006-01-20T17:00:00 Sell Execute, Price: 3592,Cost:3597,Comm 35.92 position 0
    2006-01-20T17:00:00 OPERATION PROFIT ,GROSS -5.00,Net -76.89



  • Awesome!


Log in to reply
 

});