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

Unable to plot 2nd level nested indicator



  • Hi guys,

    First of all, thanks for such a great tool for backtesting investing ideas!

    I try to plot a nested indicator. By nesting I mean using one's indicator data as entry data for another's indicator data.

    Here is what I do, based on the simple example from readme:

    from datetime import datetime
    import backtrader as bt
    
    class SmaCross(bt.SignalStrategy):
        def __init__(self):
            sma1, sma2 = bt.ind.SMA(period=10), bt.ind.SMA(period=30)
            crossover = bt.ind.CrossOver(sma1, sma2)
            self.signal_add(bt.SIGNAL_LONG, crossover)
    
            mom = bt.ind.Momentum()
            mommom = bt.ind.Momentum(mom)
            mommommom = bt.ind.Momentum(mommom, plotforce=True)
    
    cerebro = bt.Cerebro()
    cerebro.addstrategy(SmaCross)
    
    data0 = bt.feeds.YahooFinanceCSVData(dataname='data/GLD.csv', 
    	                             fromdate=datetime(2011, 1, 1),
    	                             todate=datetime(2012, 12, 31))
    cerebro.adddata(data0)
    
    cerebro.run()
    cerebro.plot()
    

    It crashes with:

    $ python smacross.py
    Traceback (most recent call last):
      File "smacross.py", line 21, in <module>
        cerebro.plot()
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/cerebro.py", line 991, in plot
        start=start, end=end, use=use)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/plot/plot.py", line 134, in plot
        self.sortdataindicators(strategy)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/plot/plot.py", line 856, in sortdataindicators
        if key not in strategy.datas:
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/lineroot.py", line 281, in __eq__
        return self._operation(other, operator.__eq__)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/lineroot.py", line 86, in _operation
        other, operation, r=r, intify=intify)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/lineroot.py", line 201, in _operation_stage1
        return self._makeoperation(other, operation, r, self)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/lineroot.py", line 331, in _makeoperation
        return self.lines[0]._makeoperation(other, operation, r, _ownerskip)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/linebuffer.py", line 378, in _makeoperation
        _ownerskip=_ownerskip)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/linebuffer.py", line 522, in __call__
        return super(MetaLineActions, cls).__call__(*args, **kwargs)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/metabase.py", line 89, in __call__
        _obj, args, kwargs = cls.dopostinit(_obj, *args, **kwargs)
      File "/Users/adam/.pyenv/versions/backtrader/lib/python3.5/site-packages/backtrader/linebuffer.py", line 566, in dopostinit
        _obj._owner.addindicator(_obj)
    AttributeError: 'NoneType' object has no attribute 'addindicator'
    

    Without plotforce=True it won't crash, but the plot is still not visible.

    My env is macOS Catalina 10.15.3, Python 3.5.9 with packages:

    $ pip freeze
    backtrader==1.9.74.123
    cycler==0.10.0
    kiwisolver==1.1.0
    matplotlib==3.0.3
    numpy==1.18.3
    pyparsing==2.4.7
    python-dateutil==2.8.1
    six==1.14.0
    

    Any help would be appreciated :)

    Thanks in advance and keep up the fantastic work!
    Adam



  • as a quick solution - you can put all three indicators on the same plot using plotmaster=mom parameter for 2nd and 3rd indicator.



  • Yeah that worked! Thanks a lot :)

    Meanwhile I've found another workaround, using dedicated indicator and nesting other indicator inside it:

    from datetime import datetime
    import backtrader as bt
    
    class NestedMomentum(bt.Indicator):
        lines = ('mom', 'mommom', 'mommommom')
        def __init__(self):
            self.l.mom = bt.ind.Momentum()
            self.l.mommom = bt.ind.Momentum(self.l.mom)
            self.l.mommommom = bt.ind.Momentum(self.l.mommom)
    
    class SmaCross(bt.SignalStrategy):
        def __init__(self):
            sma1, sma2 = bt.ind.SMA(period=10), bt.ind.SMA(period=30)
            crossover = bt.ind.CrossOver(sma1, sma2)
            self.signal_add(bt.SIGNAL_LONG, crossover)
    
            # plotmaster workaround
            mom = bt.ind.Momentum()
            mommom = bt.ind.Momentum(mom, plotmaster=mom)
            mommommom = bt.ind.Momentum(mommom, plotmaster=mom)
    
            # custom indicator workaround
            nested = NestedMomentum()
    
    cerebro = bt.Cerebro()
    cerebro.addstrategy(SmaCross)
    
    data0 = bt.feeds.YahooFinanceCSVData(dataname='data/GLD.csv', 
    	                                 fromdate=datetime(2011, 1, 1),
    	                                 todate=datetime(2012, 12, 31))
    cerebro.adddata(data0)
    
    cerebro.run()
    cerebro.plot()
    

    Anyway it looks like a bug, but I'm happy there are workarounds :)



  • @aartajew it seems like an issue in the bt script, but to be 100% sure we need to hear from author or get deeper into bt scripts with debugger.


Log in to reply
 

});