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/

    Position sizing and stop losses mess up trading strategy

    General Code/Help
    2
    3
    844
    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.
    • H
      howardhh last edited by

      Hi again,

      Apologies in advance but I will likely be posting a lot of questions since I am just starting out. Thanks for the help so far.

      Instead of simply buying 10 shares at a time I've added to my code a position sizing mechanism (where I risk 100 dollars per trade with a stop loss 5% below entry price). The strategy worked fine before I added this (buy when ema50 > ema200 when cci crosses up -100, sell when cci crosses down 100) but after I added in the position sizer/ stop loss, it turns weird.

      Original working code:

      class maCross(bt.Strategy):
      '''
      For an official backtrader blog on this topic please take a look at:

      https://www.backtrader.com/blog/posts/2017-04-09-multi-example/multi-example.html
      
      oneplot = Force all datas to plot on the same master.
      '''
      params = (
      ('ema50', 50),
      ('ema200', 200),
      ('cci20', 20),
      ('oneplot', True)
      )
      def __init__(self):
          '''
          Create an dictionary of indicators so that we can dynamically add the
          indicators to the strategy using a loop. This mean the strategy will
          work with any number of data feeds.
          '''
          self.inds = dict()
          for i, d in enumerate(self.datas):
              self.inds[d] = dict()
              self.inds[d]['ema50'] = bt.indicators.ExponentialMovingAverage(
                  d.close, period=self.params.ema50)
              self.inds[d]['ema200'] = bt.indicators.ExponentialMovingAverage(
                  d.close, period=self.params.ema200)
              self.inds[d]['cci20'] = bt.indicators.CommodityChannelIndex(
                  period=self.params.cci20)
              self.inds[d]['crossUp'] = bt.indicators.CrossOver(self.inds[d]['cci20'], -100)  # crossup = 1
              self.inds[d]['EMAcross'] = bt.indicators.CrossOver(self.inds[d]['ema50'], self.inds[d]['ema200'])
              self.inds[d]['crossDown'] = bt.indicators.CrossOver(self.inds[d]['cci20'], 100)  # crossdown = -1
      
              if i > 0:  # Check we are not on the first loop of data feed:
                  if self.p.oneplot == True:
                      d.plotinfo.plotmaster = self.datas[0]
      
      def prenext(self):
          self.next()
      
      def next(self):
          for i, d in enumerate(self.datas):
              dt, dn = self.datetime.date(), d._name
              pos = self.getposition(d).size
              if not pos:  # no market / no orders
                  if self.inds[d]['ema50'] >= self.inds[d]['ema200']:
                      if self.inds[d]['crossUp'][0] == 1:
                          self.buy(data=d, size=10)
                      else:
                          pass
                  else:
                      pass
      
              else:
                  if self.inds[d]['crossDown'][0] == -1:
                      self.close(data=d)
      

      I changed the next function to:

      def next(self):
      
          for i, d in enumerate(self.datas):
              #calculate risk/ stop price
              risk = 100  #risk = 100 dollars
              stop = 0.05 #stop 5% below close
              stop_price = self.datas[i].close[0]*(1-stop)
      
              dt, dn = self.datetime.date(), d._name
              pos = self.getposition(d).size
              if not pos:  # no market / no orders
                  if self.inds[d]['ema50'] >= self.inds[d]['ema200']:
                      if self.inds[d]['crossUp'][0] == 1: #if CCI crosses up -100
                          if self.datas[i].close[0] - stop_price > 0: #check if risk is acceptable/ valid
                              qty = round(risk / (self.datas[i].close[0] - stop_price),0) #get no. of shares to trade
                              self.buy_bracket(data=d, limitprice=self.datas[i].close[0], price=self.datas[i].close[0],
                                               stopprice=stop_price, exectype=bt.Order.Limit, size=qty)
                          else:
                              pass
                      else:
                          pass
                  else:
                      pass
      
              else:
                  if self.inds[d]['crossDown'][0] == -1:  #if cci crosses down 100
                      self.close(data=d)
      

      I can't tell what I've done wrong but it seems like the trades are now buy when cci20 crosses down -100 and sell when it crosses back up.

      Thanks heaps for any input.

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

        @howardhh just a thoughts based on your buy_bracket order:

        • you send main order as limit on close price
        • bt opens it if possible, and
        • than bt closes it at bracket's limitprice on the same close

        You may want to increase your limitprice to get the profit.

        • If my answer helped, hit reputation up arrow at lower right corner of the post.
        • Python Debugging With Pdb
        • New to python and bt - check this out
        H 1 Reply Last reply Reply Quote 1
        • H
          howardhh @ab_trader last edited by

          @ab_trader Ahhh I see. All fixed up. Thanks heaps.

          1 Reply Last reply Reply Quote 0
          • 1 / 1
          • First post
            Last post
          Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors