Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Can't import a custom indicator from default folder.

    General Code/Help
    5
    8
    176
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Patrick Mermelstein
      Patrick Mermelstein last edited by

      Hi. I'm trying to write a strategy which uses a Stochastic RSI indicator which is not pre-installed in backtrader. I've created my own StochRSI indicator, placed it inside the backtrader/indicators/ folder, and edited the init.py in backtrader/indicators/ to also include the name of my custom indicator. I cannot, however, manage to import the indicator into my strategy successfully ("AttributeError: module 'backtrader.indicators' has no attribute 'StochasticRSI'"). Any help would be greatly appreciated.

      The strategy:

      #boilerplate
      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      import datetime  # For datetime objects
      import os.path  # To manage paths
      import sys  # To find out the script name (in argv[0])
      import backtrader as bt
      import backtrader.indicators as btind
      from backtrader.indicators.mabase import MovAv
      
      class ExtremeLongs(bt.Strategy):
          """
          Buy Logic:
              -No position is open on the data (one trade at a time)
              
              -Both Stochastic indicator lines are under 10 for last 3 candles
              
              -Candle under bottom the Bollinger bands
              
              -Last 4 candles have been red
              
              -Candle is green
              
              -After buying a target is set and stored as a variable based on Moving Average (9)
              
          Sell Logic
              -Target has been met
              
          """
          
          params = (
              #Stochastic RSI
              ('stoch_k_period', 3),
              ('stoch_d_period', 3),
              ('stoch_rsi_period', 14),
              ('stoch_period', 14),
              ('stoch_upperband', 90.0),
              ('stoch_lowerband', 10.0),
              ('take_profit', 0.04),
              ('stop_loss', 0.01),
              #Bollinger Bands
              ('bbands_period', 20),
              ('bbands_devfactor', 2.0),
              ('bbands_movav', MovAv.Simple)
              )
      
          def __init__(self): #intialising indicators
              
              #intitialise stochastic rsi
              self.stochrsi = btind.StochasticRSI(
                  k_period=self.stoch_k_period,
                  d_period=self.stoch_d_period,
                  rsi_period=self.stoch_rsi_period,
                  stoch_period=self.stoch_period,
                  upperband=self.p.stoch_upperband,
                  lowerband=self.p.stoch_lowerband)
              
              #initialise bollinger bands
              self.bbands = btind.BollingerBands(
                  period=self.bbands_period,
                  devfactor=self.bbands_devfactor,
                  movav=self.bbands_movav)
              
      if __name__ == '__main__':
          
          #start Cerebro and add strategy
          cerebro = bt.Cerebro()
          cerebro.addstrategy(ExtremeLongs)
          
          #find data
          modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
          datapath = os.path.join(modpath, '../../datas/orcl-1995-2014.txt')
          
          #intialise data
          data = bt.feeds.YahooFinanceCSVData(
              dataname=datapath,
              fromdate=datetime.datetime(2000, 1, 1),
              todate=datetime.datetime(2000, 12, 31),
              reverse=False)
          cerebro.adddata(data, "Oracle - Year 2000")
          
          #broker settings
          cerebro.broker.setcash(100000.0)
          
          #run cerebro
          print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
          cerebro.run()
          print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
          cerebro.plot(style='candle')
      

      The custom indicator:

      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      from . import Indicator, MovAv, RelativeStrengthIndex, Highest, Lowest
      
      import backtrader as bt
      
      class StochasticRSI(Indicator):
      	"""
      	K - The time period to be used in calculating the %K. 3 is the default.
      	D - The time period to be used in calculating the %D. 3 is the default.
      	RSI Length - The time period to be used in calculating the RSI
      	Stochastic Length - The time period to be used in calculating the Stochastic
      
      	Formula:
      	%K = SMA(100 * (RSI(n) - RSI Lowest Low(n)) / (RSI HighestHigh(n) - RSI LowestLow(n)), smoothK)
      	%D = SMA(%K, periodD)
      
      	"""
      	alias = ('StochasticRSI')
      	lines = ('fastk', 'fastd',)
      
      	params = (
      		('k_period', 3),
      		('d_period', 3),
      		('rsi_period', 14),
      		('stoch_period', 14),
      		('movav', MovAv.Simple),
      		('rsi', RelativeStrengthIndex),
      		('upperband', 80.0),
      		('lowerband', 20.0),
      	)
      
      	plotlines = dict(percD=dict(_name='%D', ls='--'),
      	percK=dict(_name='%K'))
      
      	def _plotlabel(self):
      		plabels = [self.p.k_period, self.p.d_period, self.p.rsi_period, self.p.stoch_period]
      		plabels += [self.p.movav] * self.p.notdefault('movav')
      		return plabels
      
      	def _plotinit(self):
      		self.plotinfo.plotyhlines = [self.p.upperband, self.p.lowerband]
      
      	def __init__(self):
      		rsi = bt.indicators.RSI(period=self.p.rsi_period)
      		rsi_ll = bt.indicators.Lowest(rsi, period=self.p.rsi_period)
      		rsi_hh = bt.indicators.Highest(rsi, period=self.p.rsi_period)
      		stochrsi = (rsi - rsi_ll) / (rsi_hh - rsi_ll)
      
      		self.l.fastk = k = self.p.movav(100.0 * stochrsi, period=self.p.k_period)
      		self.l.fastd = self.p.movav(k, period=self.p.d_period)
      

      The init.py file in backtrader/indicators/ (with the custom stochasticrsi added underneath stochastic):

      #!/usr/bin/env python
      # -*- coding: utf-8; py-indent-offset:4 -*-
      ###############################################################################
      #
      # Copyright (C) 2015, 2016, 2017 Daniel Rodriguez
      #
      # This program is free software: you can redistribute it and/or modify
      # it under the terms of the GNU General Public License as published by
      # the Free Software Foundation, either version 3 of the License, or
      # (at your option) any later version.
      #
      # This program is distributed in the hope that it will be useful,
      # but WITHOUT ANY WARRANTY; without even the implied warranty of
      # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      # GNU General Public License for more details.
      #
      # You should have received a copy of the GNU General Public License
      # along with this program.  If not, see <http://www.gnu.org/licenses/>.
      #
      ###############################################################################
      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      from backtrader import Indicator
      from backtrader.functions import *
      
      # The modules below should/must define __all__ with the Indicator objects
      # of prepend an "_" (underscore) to private classes/variables
      
      from .basicops import *
      
      # base for moving averages
      from .mabase import *
      
      # moving averages (so envelope and oscillators can be auto-generated)
      from .sma import *
      from .ema import *
      from .smma import *
      from .wma import *
      from .dema import *
      from .kama import *
      from .zlema import *
      from .hma import *
      from .zlind import *
      from .dma import *
      
      # depends on moving averages
      from .deviation import *
      
      # depend on basicops, moving averages and deviations
      from .atr import *
      from .aroon import *
      from .bollinger import *
      from .cci import *
      from .crossover import *
      from .dpo import *
      from .directionalmove import *
      from .envelope import *
      from .heikinashi import *
      from .lrsi import *
      from .macd import *
      from .momentum import *
      from .oscillator import *
      from .percentchange import *
      from .percentrank import *
      from .pivotpoint import *
      from .prettygoodoscillator import *
      from .priceoscillator import *
      from .psar import *
      from .rsi import *
      from .stochastic import *
      from .stochasticrsi import *
      from .trix import *
      from .tsi import *
      from .ultimateoscillator import *
      from .williams import *
      from .rmi import *
      from .awesomeoscillator import *
      from .accdecoscillator import *
      
      
      from .dv2 import *  # depends on percentrank
      
      # Depends on Momentum
      from .kst import *
      
      from .ichimoku import *
      
      from .hurst import *
      from .ols import *
      from .hadelta import *
      
      1 Reply Last reply Reply Quote 0
      • B
        benmercerdev last edited by

        Did you check your path is importing your customized bt library and not another version on your system?

        1 Reply Last reply Reply Quote 1
        • B
          benmercerdev last edited by

          @Patrick-Mermelstein said in Can't import a custom indicator from default folder.:

          class StochasticRSI(Indicator):

          As a work around you could just put your custom indicator class in your strategy file

          1 Reply Last reply Reply Quote 0
          • run-out
            run-out last edited by

            You an also put the indicator class in a local directory and import it.

            1 Reply Last reply Reply Quote 0
            • vladisld
              vladisld last edited by

              I've run your code and it is working ok (up to some syntax errors in accessing strategy parameters directly and not through self.params). So your problem seems to be an additional backtrader package installed somewhere, such that you are importing a wrong backtrader package.

              It is easy to check - just print/debug the bt.__file__ var

              stochasticrsi.png

              Patrick Mermelstein 1 Reply Last reply Reply Quote 2
              • Patrick Mermelstein
                Patrick Mermelstein @vladisld last edited by

                @vladisld sorry, I'm fairly new to backtrader. Could you expand on the syntax mistakes you mentioned about the parameters?

                1 Reply Last reply Reply Quote 0
                • vladisld
                  vladisld last edited by

                  Basically you may access the strategy parameter either through self.p or self.params.

                  Here the code that worked for me (just compare it with yours):

                  # boilerplate
                  from __future__ import (absolute_import, division, print_function,
                                          unicode_literals)
                  
                  import datetime  # For datetime objects
                  import os.path  # To manage paths
                  import sys  # To find out the script name (in argv[0])
                  import backtrader as bt
                  import backtrader.indicators as btind
                  from backtrader.indicators.mabase import MovAv
                  
                  
                  class ExtremeLongs(bt.Strategy):
                      """
                      Buy Logic:
                          -No position is open on the data (one trade at a time)
                  
                          -Both Stochastic indicator lines are under 10 for last 3 candles
                  
                          -Candle under bottom the Bollinger bands
                  
                          -Last 4 candles have been red
                  
                          -Candle is green
                  
                          -After buying a target is set and stored as a variable based on Moving Average (9)
                  
                      Sell Logic
                          -Target has been met
                  
                      """
                  
                      params = (
                          # Stochastic RSI
                          ('stoch_k_period', 3),
                          ('stoch_d_period', 3),
                          ('stoch_rsi_period', 14),
                          ('stoch_period', 14),
                          ('stoch_upperband', 90.0),
                          ('stoch_lowerband', 10.0),
                          ('take_profit', 0.04),
                          ('stop_loss', 0.01),
                          # Bollinger Bands
                          ('bbands_period', 20),
                          ('bbands_devfactor', 2.0),
                          ('bbands_movav', MovAv.Simple)
                      )
                  
                      def __init__(self):  # intialising indicators
                  
                          # intitialise stochastic rsi
                          self.stochrsi = btind.StochasticRSI(
                              k_period=self.p.stoch_k_period,
                              d_period=self.p.stoch_d_period,
                              rsi_period=self.p.stoch_rsi_period,
                              stoch_period=self.p.stoch_period,
                              upperband=self.p.stoch_upperband,
                              lowerband=self.p.stoch_lowerband)
                  
                          # initialise bollinger bands
                          self.bbands = btind.BollingerBands(
                              period=self.p.bbands_period,
                              devfactor=self.p.bbands_devfactor,
                              movav=self.p.bbands_movav)
                  
                  
                  if __name__ == '__main__':
                      # start Cerebro and add strategy
                      cerebro = bt.Cerebro()
                      cerebro.addstrategy(ExtremeLongs)
                  
                      # find data
                      modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
                      datapath = os.path.join(modpath, 'w:/backtrader/datas/orcl-1995-2014.txt')
                  
                      # intialise data
                      data = bt.feeds.YahooFinanceCSVData(
                          dataname=datapath,
                          fromdate=datetime.datetime(2000, 1, 1),
                          todate=datetime.datetime(2000, 12, 31),
                          reverse=False)
                      cerebro.adddata(data, "Oracle - Year 2000")
                  
                      # broker settings
                      cerebro.broker.setcash(100000.0)
                  
                      # run cerebro
                      print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
                      cerebro.run()
                      print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
                      cerebro.plot(style='candle')
                  
                  1 Reply Last reply Reply Quote 0
                  • B
                    booboothefool last edited by

                    Is this what you're looking for?

                    self.stochRSI = bt.talib.STOCHRSI()
                    

                    Cause you have these: https://mrjbq7.github.io/ta-lib/funcs.html

                    1 Reply Last reply Reply Quote 0
                    • 1 / 1
                    • First post
                      Last post
                    Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                    $(document).ready(function () { app.coldLoad(); }); }