Trying to run from latest source code
-
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 usesimport backtrader as bt
throughout which was pulling in the install version. There is a function calledfindowner
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 hencefindowner
returned None which triggered the error.
Solution: I modified my Jupyter Notebook so that it too hadimport backtrader as bt
but before the import statement I addedsys.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
-
@sfkiwi said in Trying to run from latest source code:
from libs.backtrader import backtrader as bt from libs.backtrader.backtrader import indicators as btind from libs.backtrader.backtrader import feeds as btfeeds
It's not clear what you are trying to achieve, but that's clearly wrong and bound to break things.
-
@backtrader What I was trying to do was have my project import the library from the source directly rather than from the installed package. I'm fairly new to python so if there is a standard way to achieve this then please enlighten me.
For now I have just added my local source code path to the front of sys.path which works and doesn't break things.
-
@sfkiwi It's not about enlightening ... if the standard snippets using
backtrader
show (for example, there are additional import forms of course)import backtrader as bt from backtrader import indicators as btind
and your script shows
from libs.backtrader import backtrader as bt from libs.backtrader.backtrader import indicators as btind from libs.backtrader.backtrader import feeds as btfeeds
It seems like if you want to have
backtrader
inbacktrader
, like if you were trying to override things by having abacktrader
package inside anotherbacktrader
package. I cannot tell you what this breaks or of if it breaks something, but it is for sure the wrong approach and it probably breaks things (as you have experienced)There is no magic as to how to use the source, from the
README
in the repository:From source:
- Place the backtrader directory found in the sources inside your project
This is just like this for any Python package if you don't want to use
pip
orpipenv
oreasy_install
(no longer trendy these days). Of course there may be exceptions for packages which manipulate the path and do dirty things during initialization, but these are the exception andbacktrader
is for sure not amongts them.