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

How to solve this analyzers problem?



  • Hello Guys,

    I was trying to figure out what's gone wrong when I tried to make this kind of resample:

    # Create a Data Feed
    data = btfeeds.BacktraderCSVData(dataname=datapath, timeframe = bt.TimeFrame.Days)
    
    # Add the Data Feed to Cerebro
    cerebro.adddata(data)
    
    cerebro.resampledata(data,timeframe = bt.TimeFrame.Weeks, compression = 1)    
    

    And added this analyzer:

    cerebro.addanalyzer(bt.analyzers.PositionsValue, _name = 'Positions')
    

    But got this kind of error (Array index out of range).

    IndexError                                Traceback (most recent call last)
    <ipython-input-6-cfa4078d6642> in <module>
         30 
         31 # Run over everything
    ---> 32 strats = cerebro.run(runonce = False)
         33 
         34 # Print out the final result
    
    /usr/local/lib/python3.7/site-packages/backtrader/cerebro.py in run(self, **kwargs)
       1125             # let's skip process "spawning"
       1126             for iterstrat in iterstrats:
    -> 1127                 runstrat = self.runstrategies(iterstrat)
       1128                 self.runstrats.append(runstrat)
       1129                 if self._dooptimize:
    
    /usr/local/lib/python3.7/site-packages/backtrader/cerebro.py in runstrategies(self, iterstrat, predata)
       1296                     self._runnext_old(runstrats)
       1297                 else:
    -> 1298                     self._runnext(runstrats)
       1299 
       1300             for strat in runstrats:
    
    /usr/local/lib/python3.7/site-packages/backtrader/cerebro.py in _runnext(self, runstrats)
       1628                 self._check_timers(runstrats, dt0, cheat=False)
       1629                 for strat in runstrats:
    -> 1630                     strat._next()
       1631                     if self._event_stop:  # stop if requested
       1632                         return
    
    /usr/local/lib/python3.7/site-packages/backtrader/strategy.py in _next(self)
        348 
        349         minperstatus = self._getminperstatus()
    --> 350         self._next_analyzers(minperstatus)
        351         self._next_observers(minperstatus)
        352 
    
    /usr/local/lib/python3.7/site-packages/backtrader/strategy.py in _next_analyzers(self, minperstatus, once)
        386                 analyzer._nextstart()  # only called for the 1st value
        387             else:
    --> 388                 analyzer._prenext()
        389 
        390     def _settz(self, tz):
    
    /usr/local/lib/python3.7/site-packages/backtrader/analyzer.py in _prenext(self)
        150             child._prenext()
        151 
    --> 152         self.prenext()
        153 
        154     def _notify_cashvalue(self, cash, value):
    
    /usr/local/lib/python3.7/site-packages/backtrader/analyzer.py in prenext(self)
        227         The default behavior for an analyzer is to invoke ``next``
        228         '''
    --> 229         self.next()
        230 
        231     def nextstart(self):
    
    /usr/local/lib/python3.7/site-packages/backtrader/analyzers/positions.py in next(self)
         76 
         77     def next(self):
    ---> 78         pvals = [self.strategy.broker.get_value([d]) for d in self.datas]
         79         if self.p.cash:
         80             pvals.append(self.strategy.broker.get_cash())
    
    /usr/local/lib/python3.7/site-packages/backtrader/analyzers/positions.py in <listcomp>(.0)
         76 
         77     def next(self):
    ---> 78         pvals = [self.strategy.broker.get_value([d]) for d in self.datas]
         79         if self.p.cash:
         80             pvals.append(self.strategy.broker.get_cash())
    
    /usr/local/lib/python3.7/site-packages/backtrader/brokers/bbroker.py in get_value(self, datas, mkt, lever)
        420             return self._value if not lever else self._valuelever
        421 
    --> 422         return self._get_value(datas=datas, lever=lever)
        423 
        424     getvalue = get_value
    
    /usr/local/lib/python3.7/site-packages/backtrader/brokers/bbroker.py in _get_value(self, datas, lever)
        444                 dvalue = comminfo.getvalue(position, data.close[0])
        445             else:
    --> 446                 dvalue = comminfo.getvaluesize(position.size, data.close[0])
        447 
        448             dunrealized = comminfo.profitandloss(position.size, position.price,
    
    /usr/local/lib/python3.7/site-packages/backtrader/linebuffer.py in __getitem__(self, ago)
        161 
        162     def __getitem__(self, ago):
    --> 163         return self.array[self.idx + ago]
        164 
        165     def get(self, ago=0, size=1):
    
    IndexError: array index out of range
    
    

    Does anyone have any idea of what's going on??

    Thanks



  • Since giving the whole code may be useful for debugging, here below you can find it... I'm using a sample dataframe I got from "datas" folder...

    Strategy (the same you've seen from quickstart guide)

    # Create a Stratey
    class TestStrategy(bt.Strategy):
    
        def log(self, txt, dt=None):
            ''' Logging function fot this strategy'''
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
    
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            self.dataclose = self.datas[0].close
    
            # To keep track of pending orders
            self.order = None
    
        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 enough cash
            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)
    
                self.bar_executed = len(self)
    
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Canceled/Margin/Rejected')
    
            # Write down: no pending order
            self.order = None
    
        def next(self):
            # Simply log the closing price of the series from the reference
            self.log('Close, %.2f' % self.dataclose[0])
    
            # Check if an order is pending ... if yes, we cannot send a 2nd one
            if self.order:
                return
    
            # Check if we are in the market
            if not self.position:
    
                # Not yet ... we MIGHT BUY if ...
                if self.dataclose[0] < self.dataclose[-1]:
                        # current close less than previous close
    
                        if self.dataclose[-1] < self.dataclose[-2]:
                            # previous close less than the previous close
    
                            # BUY, BUY, BUY!!! (with default parameters)
                            self.log('BUY CREATE, %.2f' % self.dataclose[0])
    
                            # Keep track of the created order to avoid a 2nd order
                            self.order = self.buy()
    
            else:
    
                # Already in the market ... we might sell
                if len(self) >= (self.bar_executed + 5):
                    # SELL, SELL, SELL!!! (with all possible default parameters)
                    self.log('SELL CREATE, %.2f' % self.dataclose[0])
    
                    # Keep track of the created order to avoid a 2nd order
                    self.order = self.sell()
    
    # Create a cerebro entity
    cerebro = bt.Cerebro(stdstats = False)
    
    # Add a strategy
    cerebro.addstrategy(TestStrategy)
    
    # Datas are in a subfolder of the samples.
    
    datapath = 'datas/2006-day-001.txt'
    
    # Create a Data Feed
    data = btfeeds.BacktraderCSVData(dataname=datapath, timeframe = bt.TimeFrame.Days)
    
    # Add the Data Feed to Cerebro
    cerebro.adddata(data)
    
    cerebro.resampledata(data,timeframe = bt.TimeFrame.Weeks, compression = 1)    
    
    ## Resample data
    
    cerebro.addanalyzer(bt.analyzers.PositionsValue, _name = 'Positions') ##If one comments this line, the code works 
    
    cerebro.addobserver(bt.observers.DrawDown,plot=True)
    
    # Set our desired cash start
    cerebro.broker.setcash(100000.0)
    
    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
    # Run over everything
    strats = cerebro.run(runonce = False)
    
    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
    # Plot the result
    cerebro.plot(style = 'candlestick', volume = False)
    

    Thanks in advance!



  • Matheus Pires ,
    I got the same problem , besides bt.analyzers.PositionsValue , bt.analyzers.PyFolio have the same issue.
    regards



  • @Matheus-Pires @Frank-L Use this:

    class adjPositionsValue(bt.analyzers.PositionsValue):
        def prenext(self):
            pvals = [0 for d in self.datas]
    
            if self.p.cash:
                pvals.append(self.strategy.broker.get_cash())
    
            if self._usedate:
                self.rets[self.strategy.datetime.date()] = pvals
            else:
                self.rets[self.strategy.datetime.datetime()] = pvals
    

Log in to reply
 

});