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/

    Custom sizer enter trades more than I wanted

    General Code/Help
    1
    1
    11
    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.
    • K
      kev_backtrader last edited by

      The strategy I'm trying to do is quite simple: Buy at -50% from a rolling 5-year peak, and sell after 2 years. Each trade will be allotted a size of 20% of the portfolio total value. Below is the code I wrote.

      My problem is that it enters into trades many more times than my intention. But this issue only happens with a part of the trades. I think the problem is mainly with the sizer, because I tried my code with the built-in percent sizer (20% of cash), and that worked perfectly fine.

      class dss(bt.Strategy):
          params = (
              ('look_back_weeks', 260),
              ('drawdown_threshold', 0.5),
              ('hold_weeks', 104)
          )
          def __init__(self):
              pass
          
          def start(self):
              self.eq_progression = []
              self.trade_dates = []
              self.bought_bars={d:0 for d in self.getdatanames()}
              self.cash_start = self.broker.get_cash()
              print("Date;Security;Size;Entry_Price;Exit_price")
      
          def next(self):
              
              self.trade_dates += [self.datetime.date()]
              self.eq_progression += [cerebro.broker.getvalue()]
              for i, d in enumerate(self.datas):
                  if not self.getposition(d).size:
                      if len(self) < self.params.look_back_weeks:
                          drawdown = d[0]/max(d.get(size = len(self)).tolist())
                      else:
                          drawdown = d[0]/max(d.get(size = self.params.look_back_weeks).tolist())
                      
                      if drawdown < self.params.drawdown_threshold:
                          self.buy(data = d)
                          self.bought_bars[self.getdatanames()[i]] = len(self)
                          
      
                  elif (len(self) - self.bought_bars[self.getdatanames()[i]]) >= self.params.hold_weeks:
      
                      print(self.datetime.date(),";",
                            self.getdatanames()[i],";",
                            self.broker.getposition(d).size,";",
                            self.broker.getposition(d).price,";",
                            d[0]
                            )
      
                      self.sell(data = d)
      
      class ValuePercentSizer(bt.Sizer):
          params = (
              ('percents', 20),
              ('retint', True),# return an int size or rather the float value
          )
      
          def __init__(self):
              pass
      
          def _getsizing(self, comminfo, cash, data, isbuy):
              position = self.broker.getposition(data)
              accvalue = self.broker.getvalue()
              if not position:
                  size = accvalue / data.close[0] * (self.params.percents / 100)
              else:
                  size = position.size
              if self.p.retint:
                  size = int(size)
              return size
      
      1 Reply Last reply Reply Quote 0
      • 1 / 1
      • First post
        Last post
      Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors