I am trying to run backtrader from the latest source code but am getting an error when I execute cerebro.run()
AttributeError: 'NoneType' object has no attribute '_next_stid'
Update & Solution: I resolved this issue, so posting the solution here. I have left the original question below for context. The issue was occurring because in my Jupyter Notebook I was importing from libs.backtrader
to make sure that I was importing the source code and not the installed pip install version. The source code, however uses import backtrader as bt
throughout which was pulling in the install version. There is a function called findowner
which attempts to search the call stack for the owner of the strategy and because of the different imports the stack frames were different and couldn't find the cerebro instance and hence findowner
returned None which triggered the error.
Solution: I modified my Jupyter Notebook so that it too had import backtrader as bt
but before the import statement I added sys.path = ['libs/backtrader'] + sys.path
which prepended my local directory to the sys.path which caused both my Jupyter Notebook and the source code to find the backtrader module in the local directory before searching the pip install paths.
Original Question:
I have been successfully running backtrader from a pip install inside a conda env and am running inside a Jupyter Notebook environment. Everything has been working fine using the installed version of backtrader.
I have made a couple of minor changes to the source code so I have cloned the backtrader repo to a local folder and have simlinked the folder inside my Jupyter Notebook folder.
# common root folder is 'code'
cd code/
# clone backtrader into code/backtrader
git clone https://github.com/backtrader/backtrader.git
# code/project is where the jupyter notebook is
# change directory to libs/ directory inside project directory
cd project/libs/
#inside libs/ directory create a symlink to backtrader folder
ln -s ~/.../code/backtrader backtrader
# /code/backtrader - backtrader project folder
# /code/project - my jupyter notebook folder
# /code/project/libs/backtrader - symlinked backtrader folder
# /code/project/data/equities - folder containing dataset
Inside my jupyter notebook I am importing the project as
from libs.backtrader import backtrader as bt
from libs.backtrader.backtrader import indicators as btind
from libs.backtrader.backtrader import feeds as btfeeds
I am using one of the example strategies and sample data sets
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
def next(self):
# Simply log the closing price of the series from the reference
self.log('Close, %.2f' % self.dataclose[0])
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 all possible default parameters)
self.log('BUY CREATE, %.2f' % self.dataclose[0])
self.buy()
Then I run the strategy as
cerebro = bt.Cerebro()
# Add the strategy
cerebro.addstrategy(TestStrategy)
# path to data
datapath = 'data/equities/orcl-1995-2014.txt'
# Create a Data Feed
data = bt.feeds.YahooFinanceCSVData(
dataname=datapath,
# Do not pass values before this date
fromdate=datetime.datetime(2000, 1, 1),
# Do not pass values before this date
todate=datetime.datetime(2000, 12, 31),
# Do not pass values after this date
reverse=False)
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Set up broker
cerebro.broker.setcash(100000.0)
# Run
cerebro.run()
Running this produces the following error. Running the exact same code using the pip installed version of backtrader does not cause the error
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-40-166ad5063c49> in <module>()
----> 1 cerebro.run(runonce=False)
~/Dropbox/Work/Code/Trading/strategies/libs/backtrader/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:
~/Dropbox/Work/Code/Trading/strategies/libs/backtrader/backtrader/cerebro.py in runstrategies(self, iterstrat, predata)
1215 sargs = self.datas + list(sargs)
1216 try:
-> 1217 strat = stratcls(*sargs, **skwargs)
1218 except bt.errors.StrategySkipError:
1219 continue # do not add strategy to the mix
~/Dropbox/Work/Code/Trading/strategies/libs/backtrader/backtrader/metabase.py in __call__(cls, *args, **kwargs)
84 def __call__(cls, *args, **kwargs):
85 cls, args, kwargs = cls.doprenew(*args, **kwargs)
---> 86 _obj, args, kwargs = cls.donew(*args, **kwargs)
87 _obj, args, kwargs = cls.dopreinit(_obj, *args, **kwargs)
88 _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs)
~/Dropbox/Work/Code/Trading/strategies/libs/backtrader/backtrader/strategy.py in donew(cls, *args, **kwargs)
70 # Find the owner and store it
71 _obj.env = _obj.cerebro = cerebro = findowner(_obj, bt.Cerebro)
---> 72 _obj._id = cerebro._next_stid()
73
74 return _obj, args, kwargs
AttributeError: 'NoneType' object has no attribute '_next_stid'
It seems like findowner
is not finding the cerebro instance. I am wondering if this is because of the way strategy.py it is importing backtrader and instead of using the local code, is importing the pip installed version
# strategy.py
32 from .utils.py3 import (filter, keys, integer_types, iteritems, itervalues,
33 map, MAXINT, string_types, with_metaclass)
>> 34 import backtrader as bt
35 from .lineiterator import LineIterator, StrategyBase