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/

    Implementing Kokers momentum strategy with improvements; error with inputs to momentum.

    Indicators/Strategies/Analyzers
    2
    3
    206
    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.
    • gjertro
      gjertro last edited by

      Hi all,

      first of all, my complements for an excellent platform.

      I am implementing Kokers momentum strategy, with suggested improvements:
      https://www.backtrader.com/blog/2019-05-20-momentum-strategy/momentum-strategy/

      When running the strategy, I get an error;
      "TypeError: momentum_func() takes 1 positional argument but 2 were given"

      I have tried for some time to fix this error, and assume it has something to do with passing "self" around.

      my code:

      def momentum_func(the_array):
      # convert 'Close' to returns, create x-axis and do linear regression on returns
      returns = np.log(the_array)
      x = np.arange(len(returns))
      slope, _, rvalue, _, _ = linregress(x, returns)

      # annualize the slope, multiply with R2 for best momentum when best linear-fit
      annualized = (1 + slope) ** 252
      momentum = annualized * (rvalue ** 2)
      return momentum
      

      class Momentum(bt.ind.OperationN):
      lines = ('trend',)
      params = {'period': 90}
      func = momentum_func

      Some of the stragegy:
      class Strategy(bt.Strategy):
      params = dict(
      momentum=Momentum, # parametrize the momentum and its period
      momentum_period=90,

          movav=bt.indicators.SMA,  # parametrize the moving average and its periods
          idx_movav_period=200,
          stock_movav_period=100,
      
          volatr=bt.indicators.ATR,  # parametrize the volatility and its period
          vol_period=20,
      
          stock_size_in_portfolio = 0.001,
          portfoliol_share_of_market = 0.4
      )
      
      def __init__(self):
          self.indicators = collections.defaultdict(dict)  # avoid per data dct in for
      
          # Use "self.data0" (or self.data) in the script to make the naming not
          # fixed on this being a "spy" strategy. Keep things generic
          self.stocks = self.datas[1:]
          self.stocks_with_data = []
          self.required_stock_history = max(self.p.momentum_period, self.p.vol_period, self.p.stock_movav_period)
      
          self.idx_mav = self.p.movav(self.data0, period=self.p.idx_movav_period)
          for stock in self.stocks:
              stock_name = stock._name
              self.indicators[stock_name]['momentum'] = self.p.momentum(stock, period=self.p.momentum_period)
              self.indicators[stock_name]['movingaverage'] = self.p.movav(stock, period=self.p.stock_movav_period)
              self.indicators[stock_name]['volatility'] = self.p.volatr(stock, period=self.p.vol_period)
      

      Any Idea why I get the error?

      1 Reply Last reply Reply Quote 0
      • A
        ab_trader last edited by

        @gjertro

        try this

        def momentum_func(the_array, period):
        
            # function body
        
        1 Reply Last reply Reply Quote 1
        • gjertro
          gjertro last edited by

          Dear @ab_trader

          Thanks for your answer. I actually solved this by declaring it as @staticmethod, even if it is outside the class definition.
          Quite weird, I think, but now it works.

          I did get some errors when the dataseries for the different stocks started at different times. I solved this by aligning the datetime indexes in the input data (pandas) and returning a very low momentum if there are nans in the array. The idea is that with the low momentum, the stocks will never be sorted at the top, so there will not be any positions in the stock. I do consider this risky though. Any idea as to how to include all data?

          The momentum function:

          @staticmethod
          def momentum_func(the_array):

          if np.nan in the_array:
              momentum = -10**10
          
          else:
              # convert 'Close' to returns, create x-axis and do linear regression on returns
              returns = np.log(the_array)
              x = np.arange(len(returns))
              slope, _, rvalue, _, _ = linregress(x, returns)
          
              # annualize the slope, multiply with R2 for best momentum when best linear-fit
              annualized = (1 + slope) ** 252
              momentum = annualized * (rvalue ** 2)
          
          return momentum
          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(); }); }