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

How to add my own pre-calculated indicators to bt logic as bt.Indicator

  • Hello,

    I just recently discovered the backtrader library, and I would like to add many of my own indicators (I've called them as AnalysisFilters) that I have already programmed to the backtrader logic. But I would like to add them as if they were bt.Indicator so that they can be easily plotted. (Later you will understand why I focus on saying that I want them to be bt.Indicator. Because I know how to add them as DataFeed (extra columns with my precalculated indicators values), but not as bt.Indicator).

    The problem is that all the indicators that I have programmed follow this pattern: they have a method with the following definition:

    def _calculate_indicator_at_index(data, index):
    :param data: (pd.DataFrame) with all the data and ['open', 'high', 'low', 'close'] columns.
    :param index: (int) index of the DataFrame for which we want to calculate the value of the indicator

    I've tried something like the following, but it obviously doesn't work because is not a DataFrame.

    import backtrader as bt
    from src.analysis_filters.blai5_atlas_filter import Blai5AtlasFilter
    class AtlasIndicator(bt.Indicator):
        lines = ('atlas',)
        params = (('boll_avg_value', 20), ('exp_avg_value', 120))
        def __init __(self):
            atlas_filter = Blai5AtlasFilter(self.p.boll_avg_value, self.p.exp_avg_value)
            atlas_precalculated_values = [0]*
            for i in range(
                atlas_precalculated_values[i] = atlas_filter._calculate_indicator_at_index(, i)
            self.lines.atlas = atlas_precalculated_values

    So my question would be how to convert to a DataFrame or something that my indicator can later access via data['close'], data['open'], etc.

    Greetings, and thank you very much in advance for the help.

    PS: Congratulations to the creator of the library, because the amount of possibilities it offers is impressive. I would have loved to discover it before.

  • administrators

    The assignment is meant for lazy evaluation of things which haven't been calculated yet.

    Your best bet is to feed that during each next tick in a custom indicator. Docs - Indicator Development

  • Hello, thanks for your answer. Finally what I have done is load my indicator values as a DataBase (passing first the same main data to my AnalsyisFilter and to Cerebro). Here is the code were I load my indicator values as a DataBase:

    class AnalysisFilterFakeDataLoader(bt.feeds.DataBase):
        lines = ('data_indicator',)
        def __init__(self, analysis_filter: AnalysisFilter = None):
            self.analysis_filter = analysis_filter
            self.plotinfo.plot = False
        def start(self):
            super(AnalysisFilterFakeDataLoader, self).start()
            # reset the iterator on each start
            self._rows =
        def _load(self):
                row = next(self._rows)
            except StopIteration:
                return False
            line_ind = getattr(self.lines, 'data_indicator')
            line_ind[0] = self.analysis_filter._check_filter_condition_at_index(row.Index)
            return True

    And then in my Strategy I access this data with this lines:

    class NearConfHighsBlai5Strategy(bt.Strategy):
        params = (('blai5_name', None),
                  ('near_conf_highs_name', None))
        def __init__(self):
            self.blai5_indicator = self.dnames.get(self.p.blai5_name).data_indicator
            self.near_indicator = self.dnames.get(self.p.near_conf_highs_name).data_indicator
        def next(self):
            if self.blai5_indicator[0] > 0 or self.near_indicator[0]> 0:

    But I don't know why this code does not works. Because, the next() method is never executed. The assigment of the indicator values in the __init__() is working properly, but the next() is not executing never. Why?

    EDIT: Also, when I add my own DataBase, any other strategis not related with this databases stop executing well. It seems, that when I add any data with my own implementation of bt.DataBase, the Strategies don't execute their next() method.

  • administrators

    Sorry, but that code cannot work ... an exception should have been raised. You are obviously running something else.

    @Rubén-Briones said in How to add my own pre-calculated indicators to bt logic as bt.Indicator:

    class AnalysisFilterFakeDataLoader(bt.feeds.DataBase):
        lines = ('data_indicator')

    That defines 14 lines ...

  • @backtrader Sorry, I have tried to simplify my example to make easy to understand. It's right that this code raise an exception because lines is not a tuple. In my real use case I have defined 3 lines, so the code runs. But I added a comma in the declaration of lines to convert to a tuple, and skip the exception, but I have the same problem described in my post: the strategies doesn't run.

    PD: I don't understand so much what you want to say with "That defines 14 lines ..."

Log in to reply