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

Custom Observer for debug arrows on graph, to be called in stratergy, error



  • Re: Plotting a boolean indicator
    Hi,

    Been trying to make a way I can debug my algorithm visually by using a arrow like BuySell Observer. I want to be able to call addpoint which will add it to the graph, however I have ran into a few problems these include:
    Getting an error when trying to call the line outside of the next()

       self.lines.peak[index] = copy.deepcopy(yvalue)
      File "/usr/local/lib/python3.7/site-packages/backtrader/lineseries.py", line 62, in __get__
        return obj.lines[self.line]
    AttributeError: 'NoneType' object has no attribute 'lines'
    

    with example code:

    def addpoint(self, index, typepoint, yvalue):
            self.lines.peak[index] = copy.deepcopy(yvalue)
    

    Due to this I have been trying to do things through the next function with example code below:

    import math
    import copy
    
    from backtrader.observer import Observer
    
    
    class PeaksAndTroofs(Observer):
        lines = ('peak', 'troof',)
    
        plotinfo = dict(plot=True, subplot=False, plotlinelabels=True)
        plotlines = dict(
            peak=dict(marker='v', markersize=8.0, color='purple',
                     fillstyle='full', ls=''),
            troof=dict(marker='^', markersize=8.0, color='blue',
                      fillstyle='full', ls='')
        )
    
        params = (
            ('barplot', False),  # plot above/below max/min for clarity in bar plot
            ('bardist', 0.015),  # distance to max/min in absolute perc
        )
    
        typepoint = []
        yvaluepoint = []
        index = []
    
        def next(self):
    
            if self.yvaluepoint != [] and self.typepoint != [] and self.index != []:
    
                for i in range(len(self.index)):
    
                    if self.typepoint[i] == 'peak':
                        self.lines.peak[self.index[i]] = copy.deepcopy(self.yvaluepoint[i])
    
                    elif self.typepoint == 'troof':
                        self.lines.troof[self.index[i]] = copy.deepcopy(self.yvaluepoint[i])
    
                self.typepoint = []
                self.yvaluepoint = []
                self.index = []
     
    
        def addpoint(self, index, typepoint, yvalue):
            self.typepoint.append(copy.deepcopy(typepoint))
            self.yvaluepoint.append(copy.deepcopy(yvalue))
            self.index.append(copy.deepcopy(index))
    

    I don't get any results out onto the graph, I beileve its due to the.

    self.typepoint = []
    self.yvaluepoint = []
    self.index = []
    

    This is due to when removing I get the a sort of expected behavouir with plotting however, indicators are repeated and troofs don't exsist.
    This is the graph with the above code commented out.

    https://i.imgur.com/hIrdYIy.png

    I am creating my calls to addpoint like this in my stratergy.

    if len(self.dataclose) % 10 == 0:
         self.peaks_and_troofs_ob.addpoint(self.peaks_and_troofs_ob, 0, 'peak', self.dataclose[0])
    elif len(self.dataclose) % 5 == 0:
                self.peaks_and_troofs_ob.addpoint(self.peaks_and_troofs_ob, 0, 'troof', self.dataclose[0])
    

    And the way I have pulled in the new observer to the stratergy is this in the init

    # Plots peaks and troofs
    self.peaks_and_troofs_ob = PeaksAndTroofs
    self.env.addobservermulti(self.peaks_and_troofs_ob)
    


  • @HarryBurge said in Custom Observer for debug arrows on graph, to be called in strategy, error:

    I am creating my calls to addpoint like this in my strategy.

    Few points:

    1. Having a strategy dependent on specific observer is probably not the best idea design-wise.
    2. Why the same logic can't be run right inside the observer? All datas are available for observers AFAIR.

Log in to reply
 

});