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/

    Strategy closing instead of reverting to short

    General Code/Help
    4
    14
    89
    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.
    • Eduardo Menges Mattje
      Eduardo Menges Mattje last edited by

      Hello. I programmed a very simple MA crossover strategy, however the short signals are only closing the long positions, not opening new short positions. I used self.sell() for that, and changing it for self.close() will yield the same result. This is the code:

      from datetime import datetime
      
      import backtrader as bt
      
      
      class MACross(bt.Strategy):
          params = dict(
              pfast=10,
              pslow=30
          )
      
          def log(self, text, date=None):
              date = date or self.datas[0].datetime.datetime(0)
              print(f'{date.isoformat()}: {text}')
      
          def __init__(self):
              self.bar_executed = len(self)
              self.order = None
              self.comm = None
      
              ema_short = bt.ind.EMA(period=self.p.pfast)
              ema_long = bt.ind.EMA(period=self.p.pslow)
              self.crossover = bt.ind.CrossOver(ema_short, ema_long)
      
          def notify_order(self, order):
              order.executed.comm = round(order.executed.comm, 2)
              order.executed.price = round(order.executed.price, 2)
              if order.status in [order.Submitted, order.Accepted]:
                  return
              elif order.status in [order.Completed]:
                  if order.isbuy():
                      self.log(f'Entry long, price: {order.executed.price}; commission: {order.executed.comm}')
                  elif order.issell():
                      self.log(f'Entry short, price: {order.executed.price}; commission {order.executed.comm}')
              elif order.status in [order.Margin]:
                  self.log('Order Margin')
              self.order = None
      
          def notify_trade(self, trade):
              trade.pnlcomm = round(trade.pnlcomm, 2)
              if not trade.isclosed:
                  return
              else:
                  self.log(f'Net profit: {trade.pnlcomm}')
      
          def next(self):
              if self.crossover > 0:
                  self.buy()
              if self.crossover < 0:
                  self.sell()
      
      
      if __name__ == "__main__":
          def print_sqn(analyzer):
              sqn = round(analyzer.sqn, 2)
              print(f'SQN: {sqn}')
      
          start_cash = 10000
          commission_percentage = 0.075
          cerebro = bt.Cerebro()
      
          data = bt.feeds.GenericCSVData(
              dataname='BTCUSDT_1h.csv',
              fromdate=datetime(2020, 1, 1),
              # todate=datetime(2020, 5, 8),
              timeframe=bt.TimeFrame.Minutes,
              compression=60,
              dtformat='%Y-%m-%d %H:%M:%S',
              openinterest=None
          )
      
          cerebro.adddata(data)
          cerebro.broker.setcash(start_cash)
          cerebro.addsizer(bt.sizers.PercentSizer, percents=99)
          cerebro.broker.setcommission(commission=(commission_percentage / 100), margin=False)
          cerebro.addstrategy(MACross)
          cerebro.addanalyzer(bt.analyzers.SQN)
      
          strategies = cerebro.run()
          current_strategy = strategies[0]
      
          port_value = round(cerebro.broker.getvalue(), 2)
          pnl = round(port_value - start_cash, 2)
      
          print(f'Final value: ${port_value}')
          print(f'P/L: ${pnl}')
          print_sqn(current_strategy.analyzers.sqn.get_analysis())
          # cerebro.plot(style='candle')
      
      

      What should I do to get short positions?

      1 Reply Last reply Reply Quote 0
      • D
        dasch last edited by

        you may try closing your trades:

        def next(self):
            if self.position:
                # close position on sma cross
                if self.crossover[0] != 0:
                    self.close(self.data_primary)
            else:
                if self.crossover[0] > 0:
                    self.buy()
                elif self.crossover[0] < 0:
                    self.sell()
        
        
        D Eduardo Menges Mattje 2 Replies Last reply Reply Quote 0
        • D
          dasch @dasch last edited by

          @dasch

          @dasch said in Strategy closing instead of reverting to short:

                  self.close(self.data_primary)
          

          change the code above to:

          self.close()
          
          1 Reply Last reply Reply Quote 0
          • Eduardo Menges Mattje
            Eduardo Menges Mattje @dasch last edited by

            @dasch Hello, thanks for your answer, but it still is not reverting to short.
            The result from using your code is:
            Final value: $18389.98
            P/L: $8389.98
            If i use my original code, the result is:
            Final value: $18389.98
            P/L: $8389.98
            If I change the code to

                    if self.crossover[0] > 0:
                        self.buy()
                    if self.crossover[0] < 0:
                        self.close()
            

            The result still will be:
            Final value: $18389.98
            P/L: $8389.98

            This is what is bugging me, self.sell() should revert long positions to short, but it's behaving the same way as self.close().

            1 Reply Last reply Reply Quote 0
            • D
              dasch last edited by

              Sell will not revert to a short position if you have a long position open. It will subtract the position size from the open position. You would either need to close the trade or increase the position size by the open position size.

              Eduardo Menges Mattje 1 Reply Last reply Reply Quote 0
              • D
                dasch last edited by

                When you call close it is doing just a order in the counter direction of the current open position. So if you call close on a long position it will create a sell order with the same size as your open position.

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

                  Target size orders will be good choice to use with the strategy which reverses positions and stay always in the market. Just use size 1 for long, size -1 for short.

                  Eduardo Menges Mattje 1 Reply Last reply Reply Quote 2
                  • Eduardo Menges Mattje
                    Eduardo Menges Mattje @dasch last edited by

                    @dasch ok, but then if I use

                            if self.position:
                                if self.crossover[0] != 0:
                                    self.close()
                            else:
                                if self.crossover[0] > 0:
                                    self.buy()
                                if self.crossover[0] < 0:
                                    self.sell()
                    

                    Shouldn't it close the current position and then open a short?

                    @ab_trader target orders? What are these?

                    vladisld 1 Reply Last reply Reply Quote 0
                    • vladisld
                      vladisld @Eduardo Menges Mattje last edited by

                      @Eduardo-Menges-Mattje said in Strategy closing instead of reverting to short:

                      target orders? What are these?

                      I believe it is documented here:
                      https://www.backtrader.com/docu/order_target/order_target/

                      1 Reply Last reply Reply Quote 2
                      • Eduardo Menges Mattje
                        Eduardo Menges Mattje @ab_trader last edited by

                        @ab_trader using

                                if self.crossover > 0:
                                    self.order_target_size(target=1)
                                if self.crossover < 0:
                                    self.order_target_size(target=-1)
                        

                        Worked, it reverts the positions. But how can I use the sizer instead of 1?

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

                          @Eduardo-Menges-Mattje said in Strategy closing instead of reverting to short:

                          But how can I use the sizer instead of 1?

                          Docs
                          You are welcome! :)

                          1 Reply Last reply Reply Quote 0
                          • Eduardo Menges Mattje
                            Eduardo Menges Mattje last edited by

                            Yes, thank you, I know how to read. The issue is that if I use

                                    if self.crossover > 0:
                                        self.order_target_size(target=self.getsizing())
                                    elif self.crossover < 0:
                                        self.order_target_size(target=-self.getsizing())
                            

                            Trades are only exited when they generate a profit, as you can see on the graph, which still has a short position opened.
                            alt text
                            The same thing happens if I use isbuy=False.
                            If the sizer is a FixedReverser, I don't even need to use the target orders, I can just use a self.buy or a self.close, but what I really want to use is a percent sizer that reverts the position, something that seems to be missing from Backtrader.

                            D 1 Reply Last reply Reply Quote 0
                            • D
                              dasch @Eduardo Menges Mattje last edited by

                              @Eduardo-Menges-Mattje said in Strategy closing instead of reverting to short:

                              Yes, thank you, I know how to read. The issue is that if I use

                              maybe check out https://backtrader.com/docu/sizers/sizers/#sizer-development

                              where there is this:

                              Another example: A position rerverser

                              Cheers

                              1 Reply Last reply Reply Quote 2
                              • Eduardo Menges Mattje
                                Eduardo Menges Mattje last edited by

                                Made a PercentReverter sizer which does what I wanted. In case anyone else needs it:

                                class PercentReverter(bt.Sizer):
                                    params = (
                                        ('percents', 20),
                                    )
                                
                                    def _getsizing(self, comminfo, cash, data, isbuy):
                                        position = self.broker.getposition(data)
                                        if not position:
                                            size = cash / data.close[0] * (self.params.percents / 100)
                                        else:
                                            size = abs(position.size) + (position.size + cash / data.close[0]) * (self.params.percents / 100)
                                        return size
                                
                                1 Reply Last reply Reply Quote 2
                                • 1 / 1
                                • First post
                                  Last post
                                Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                                $(document).ready(function () { app.coldLoad(); }); }