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/

    Help - Buy signal recognition and trade creation vs execution?

    General Code/Help
    2
    4
    56
    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.
    • J
      j63009567 last edited by

      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 matplotlib.pyplot as plt
      filepath = r'C:\Users\lenovo\Desktop\Scripts\Data\varta20152021.csv'
      
      # Import the backtrader platform
      import backtrader as bt
      cerebro = bt.Cerebro(stdstats=False, cheat_on_open = True)
      # cerebro.addobserver(bt.observers.DrawDown)
      # Create a Stratey
      class SmaStrategy(bt.Strategy):
          params = (
              ('maperiod', 10),
          )
      
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              dt = dt or self.datas[0].datetime.date(0)
              print('%s, %s' % (dt.isoformat(), txt))
      
          def __init__(self):
              # Keep a reference to the "close" line in the data[0] dataseries
              self.dataclose = self.datas[0].close
      
              # To keep track of pending orders and buy price/commission
              self.order = None
              self.buyprice = None
              self.buycomm = None
      
              # Add a MovingAverageSimple indicator
              self.sma = bt.indicators.SimpleMovingAverage(
                  self.datas[0], period=self.params.maperiod)
      
              # Indicators for the plotting show
              bt.indicators.ExponentialMovingAverage(self.datas[0], period=25)
              bt.indicators.WeightedMovingAverage(self.datas[0], period=25,
                                                  subplot=True)
              bt.indicators.StochasticSlow(self.datas[0])
              bt.indicators.MACDHisto(self.datas[0])
              rsi = bt.indicators.RSI(self.datas[0])
              bt.indicators.SmoothedMovingAverage(rsi, period=10)
              bt.indicators.ATR(self.datas[0], plot=False)
      
          def notify_order(self, order):
              if order.status in [order.Submitted, order.Accepted]:
                  # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                  return
      
              # Check if an order has been completed
              # Attention: broker could reject order if not enough cash
              if order.status in [order.Completed]:
                  if order.isbuy():
                      self.log(
                          'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                          (order.executed.price,
                           order.executed.value,
                           order.executed.comm))
      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
                  else:  # Sell
                      self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                               (order.executed.price,
                                order.executed.value,
                                order.executed.comm))
      
                  self.bar_executed = len(self)
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log('Order Canceled/Margin/Rejected')
      
              # Write down: no pending order
              self.order = None
      
          def notify_trade(self, trade):
              if not trade.isclosed:
                  return
      
              self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                       (trade.pnl, trade.pnlcomm))
      
          def next(self):
              # Simply log the closing price of the series from the reference
              self.log('Close, %.2f' % self.dataclose[0])
      
              # Check if an order is pending ... if yes, we cannot send a 2nd one
              if self.order:
                  return
      
              # Check if we are in the market
              if not self.position:
      
                  # Not yet ... we MIGHT BUY if ...
                  if self.dataclose[0] > self.sma[0]:
      
                      # BUY, BUY, BUY!!! (with all possible default parameters)
                      self.log('BUY CREATE, %.2f' % self.dataclose[0])
      
                      # Keep track of the created order to avoid a 2nd order
                      self.order = self.buy(exectype=bt.Order.StopTrail, trailpercent=0.007)
      
              else:
      
                  if self.dataclose[0] < (self.sma[0]):
                      # SELL, SELL, SELL!!! (with all possible default parameters)
                      self.log('SELL CREATE, %.2f' % self.dataclose[0])
      
                      # Keep track of the created order to avoid a 2nd order
                      self.order = self.sell()                
      
      
      
      if __name__ == '__main__':
          # Create a cerebro entity
          cerebro = bt.Cerebro()
      
          # Add a strategy
          cerebro.addstrategy(SmaStrategy)
          cerebro.addanalyzer(bt.analyzers.SharpeRatio)
          cerebro.addanalyzer(bt.analyzers.DrawDown)
          cerebro.addanalyzer(bt.analyzers.TradeAnalyzer)
          cerebro.addanalyzer(bt.analyzers.Returns) 
          cerebro.addanalyzer(bt.analyzers.PyFolio)
          cerebro.addanalyzer(bt.analyzers.Transactions)
          cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
      
      
          
          # Datas are in a subfolder of the samples. Need to find where the script is
          # because it could have been called from anywhere
          modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
          datapath = os.path.join(modpath, filepath)
      
          # Create a Data Feed
          data = bt.feeds.YahooFinanceCSVData(
              dataname=datapath,
              # Do not pass values before this date
              fromdate=datetime.datetime(2020,6, 30),
              # Do not pass values before this date
              todate=datetime.datetime(2021, 6, 30),
              # Do not pass values after this date
              reverse=False)
      
          # Add the Data Feed to Cerebro
          cerebro.adddata(data)
      
          # Set our desired cash start
          cerebro.broker.setcash(1000000.0)
      
          # Add a FixedSize sizer according to the stake
          cerebro.addsizer(bt.sizers.FixedSize, stake=6000)
      
          # Set the commission
          cerebro.broker.setcommission(commission=0.0002)
      
          # Print out the starting conditions
          print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
          
          # Run over everything
          res = cerebro.run()[0]
          
          
          print("\n")
          sharpe_data = res.analyzers.sharperatio.get_analysis()
          print("=== Sharpe Ratio ===")
          print("Sharpe: %s" % sharpe_data['sharperatio'])
      
      #     print("Draw Down: ", res.analyzers.drawdown.get_analysis())
          draw_down_data = res.analyzers.drawdown.get_analysis()
          print("========== Draw Down ==========")
          print("max drawdown: %s %%" % draw_down_data['max']['drawdown'])
          print("max money drawdown: %s" % draw_down_data['max']['moneydown'])
      
                
      #     print("Trade Analyzer: ", res.analyzers.tradeanalyzer.get_analysis())
          trading_data = res.analyzers.tradeanalyzer.get_analysis()
          print("========== Trading Analysis ==========")
          print("Winning Trades")
          print("win ratio: %s" % (trading_data['won']['total'] / float(trading_data['won']['total'] + trading_data['lost']['total'])))
          print("win_hits: %s" % trading_data['won']['total'])
          print("win_pnl --> total: %s, average: %s, max: %s" %
                (trading_data['won']['pnl']['total'],
                trading_data['won']['pnl']['average'],
                trading_data['won']['pnl']['max'])
               )
          print("Losing Trades")
          print("lost_hits:%s" % trading_data['lost']['total'])
          print("lost_pnl --> total: %s, average: %s, max: %s" %
                (trading_data['lost']['pnl']['total'],
                trading_data['lost']['pnl']['average'],
                trading_data['lost']['pnl']['max'])
               )
          print("Long Trades")
          print("long_hits: %s" % trading_data['long']['total'])
          print("long_pnl --> total: %s, average: %s" %
               (trading_data['long']['pnl']['total'],
                trading_data['long']['pnl']['average'])
               )
          print("Short Trades")
          print("short_hits: %s" % trading_data['short']['total'])
          print("short_pnl --> total: %s, average: %s" %
               (trading_data['short']['pnl']['total'],
                trading_data['short']['pnl']['average'])
               )
              
              
          transactions_data = res.analyzers.tradeanalyzer.get_analysis()
          print("========== SQN Analysis ==========")
          print(dict(res.analyzers.sqn.get_analysis())['sqn'])
          
          
          print('\n')
          
          # Print out the final result
          print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
         
          # Plot the result
          cerebro.plot(style='candle')
      

      Testing strategy using VAR1.DE daily data from yahoo finance.

      1. Why is the buy creation and execution distanced away by more than 1 day? As I see this happen maybe a couple of times.

      2. Why didn't the signal detect a buy order at the start of the data? As you can see, the first buy order is on Aug 2020 but in the chart you can see that before the first buy order, there is another crossover where the close is above the sma10.

      Please let me know your thoughts, thanks a lot! Would really appreciate the help especially on the coding part, as I most likely typed something wrong somewhere.. though this is taken from the quickstarter guide. The cheat is not incorporated yet.

      J 1 Reply Last reply Reply Quote 0
      • J
        j63009567 @j63009567 last edited by

        @j63009567 said in Help - Buy signal recognition and trade creation vs execution?:

        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 matplotlib.pyplot as plt
        filepath = r'C:\Users\lenovo\Desktop\Scripts\Data\varta20152021.csv'
        
        # Import the backtrader platform
        import backtrader as bt
        cerebro = bt.Cerebro(stdstats=False, cheat_on_open = True)
        # cerebro.addobserver(bt.observers.DrawDown)
        # Create a Stratey
        class SmaStrategy(bt.Strategy):
            params = (
                ('maperiod', 10),
            )
        
            def log(self, txt, dt=None):
                ''' Logging function fot this strategy'''
                dt = dt or self.datas[0].datetime.date(0)
                print('%s, %s' % (dt.isoformat(), txt))
        
            def __init__(self):
                # Keep a reference to the "close" line in the data[0] dataseries
                self.dataclose = self.datas[0].close
        
                # To keep track of pending orders and buy price/commission
                self.order = None
                self.buyprice = None
                self.buycomm = None
        
                # Add a MovingAverageSimple indicator
                self.sma = bt.indicators.SimpleMovingAverage(
                    self.datas[0], period=self.params.maperiod)
        
                # Indicators for the plotting show
                bt.indicators.ExponentialMovingAverage(self.datas[0], period=25)
                bt.indicators.WeightedMovingAverage(self.datas[0], period=25,
                                                    subplot=True)
                bt.indicators.StochasticSlow(self.datas[0])
                bt.indicators.MACDHisto(self.datas[0])
                rsi = bt.indicators.RSI(self.datas[0])
                bt.indicators.SmoothedMovingAverage(rsi, period=10)
                bt.indicators.ATR(self.datas[0], plot=False)
        
            def notify_order(self, order):
                if order.status in [order.Submitted, order.Accepted]:
                    # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                    return
        
                # Check if an order has been completed
                # Attention: broker could reject order if not enough cash
                if order.status in [order.Completed]:
                    if order.isbuy():
                        self.log(
                            'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                            (order.executed.price,
                             order.executed.value,
                             order.executed.comm))
        
                        self.buyprice = order.executed.price
                        self.buycomm = order.executed.comm
                    else:  # Sell
                        self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                                 (order.executed.price,
                                  order.executed.value,
                                  order.executed.comm))
        
                    self.bar_executed = len(self)
        
                elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                    self.log('Order Canceled/Margin/Rejected')
        
                # Write down: no pending order
                self.order = None
        
            def notify_trade(self, trade):
                if not trade.isclosed:
                    return
        
                self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                         (trade.pnl, trade.pnlcomm))
        
            def next(self):
                # Simply log the closing price of the series from the reference
                self.log('Close, %.2f' % self.dataclose[0])
        
                # Check if an order is pending ... if yes, we cannot send a 2nd one
                if self.order:
                    return
        
                # Check if we are in the market
                if not self.position:
        
                    # Not yet ... we MIGHT BUY if ...
                    if self.dataclose[0] > self.sma[0]:
        
                        # BUY, BUY, BUY!!! (with all possible default parameters)
                        self.log('BUY CREATE, %.2f' % self.dataclose[0])
        
                        # Keep track of the created order to avoid a 2nd order
                        self.order = self.buy(exectype=bt.Order.StopTrail, trailpercent=0.007)
        
                else:
        
                    if self.dataclose[0] < (self.sma[0]):
                        # SELL, SELL, SELL!!! (with all possible default parameters)
                        self.log('SELL CREATE, %.2f' % self.dataclose[0])
        
                        # Keep track of the created order to avoid a 2nd order
                        self.order = self.sell()                
        
        
        
        if __name__ == '__main__':
            # Create a cerebro entity
            cerebro = bt.Cerebro()
        
            # Add a strategy
            cerebro.addstrategy(SmaStrategy)
            cerebro.addanalyzer(bt.analyzers.SharpeRatio)
            cerebro.addanalyzer(bt.analyzers.DrawDown)
            cerebro.addanalyzer(bt.analyzers.TradeAnalyzer)
            cerebro.addanalyzer(bt.analyzers.Returns) 
            cerebro.addanalyzer(bt.analyzers.PyFolio)
            cerebro.addanalyzer(bt.analyzers.Transactions)
            cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
        
        
            
            # Datas are in a subfolder of the samples. Need to find where the script is
            # because it could have been called from anywhere
            modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
            datapath = os.path.join(modpath, filepath)
        
            # Create a Data Feed
            data = bt.feeds.YahooFinanceCSVData(
                dataname=datapath,
                # Do not pass values before this date
                fromdate=datetime.datetime(2020,6, 30),
                # Do not pass values before this date
                todate=datetime.datetime(2021, 6, 30),
                # Do not pass values after this date
                reverse=False)
        
            # Add the Data Feed to Cerebro
            cerebro.adddata(data)
        
            # Set our desired cash start
            cerebro.broker.setcash(1000000.0)
        
            # Add a FixedSize sizer according to the stake
            cerebro.addsizer(bt.sizers.FixedSize, stake=6000)
        
            # Set the commission
            cerebro.broker.setcommission(commission=0.0002)
        
            # Print out the starting conditions
            print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
            
            # Run over everything
            res = cerebro.run()[0]
            
            
            print("\n")
            sharpe_data = res.analyzers.sharperatio.get_analysis()
            print("=== Sharpe Ratio ===")
            print("Sharpe: %s" % sharpe_data['sharperatio'])
        
        #     print("Draw Down: ", res.analyzers.drawdown.get_analysis())
            draw_down_data = res.analyzers.drawdown.get_analysis()
            print("========== Draw Down ==========")
            print("max drawdown: %s %%" % draw_down_data['max']['drawdown'])
            print("max money drawdown: %s" % draw_down_data['max']['moneydown'])
        
                  
        #     print("Trade Analyzer: ", res.analyzers.tradeanalyzer.get_analysis())
            trading_data = res.analyzers.tradeanalyzer.get_analysis()
            print("========== Trading Analysis ==========")
            print("Winning Trades")
            print("win ratio: %s" % (trading_data['won']['total'] / float(trading_data['won']['total'] + trading_data['lost']['total'])))
            print("win_hits: %s" % trading_data['won']['total'])
            print("win_pnl --> total: %s, average: %s, max: %s" %
                  (trading_data['won']['pnl']['total'],
                  trading_data['won']['pnl']['average'],
                  trading_data['won']['pnl']['max'])
                 )
            print("Losing Trades")
            print("lost_hits:%s" % trading_data['lost']['total'])
            print("lost_pnl --> total: %s, average: %s, max: %s" %
                  (trading_data['lost']['pnl']['total'],
                  trading_data['lost']['pnl']['average'],
                  trading_data['lost']['pnl']['max'])
                 )
            print("Long Trades")
            print("long_hits: %s" % trading_data['long']['total'])
            print("long_pnl --> total: %s, average: %s" %
                 (trading_data['long']['pnl']['total'],
                  trading_data['long']['pnl']['average'])
                 )
            print("Short Trades")
            print("short_hits: %s" % trading_data['short']['total'])
            print("short_pnl --> total: %s, average: %s" %
                 (trading_data['short']['pnl']['total'],
                  trading_data['short']['pnl']['average'])
                 )
                
                
            transactions_data = res.analyzers.tradeanalyzer.get_analysis()
            print("========== SQN Analysis ==========")
            print(dict(res.analyzers.sqn.get_analysis())['sqn'])
            
            
            print('\n')
            
            # Print out the final result
            print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
           
            # Plot the result
            cerebro.plot(style='candle')
        

        Testing strategy using VAR1.DE daily data from yahoo finance.

        1. Why is the buy creation and execution distanced away by more than 1 day? As I see this happen maybe a couple of times.

        2. Why didn't the signal detect a buy order at the start of the data? As you can see, the first buy order is on Aug 2020 but in the chart you can see that before the first buy order, there is another crossover where the close is above the sma10.

        Please let me know your thoughts, thanks a lot! Would really appreciate the help especially on the coding part, as I most likely typed something wrong somewhere.. though this is taken from the quickstarter guide. The cheat is not incorporated yet.

        Capture.PNG ![alt text](Capture.PNG image url)

        As you can see the create and execute is randomly distanced by a day. Please help me!

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

          @j63009567 The answer is because you are using a stop trail order:

          # Keep track of the created order to avoid a 2nd order
                          self.order = self.buy(exectype=bt.Order.StopTrail, trailpercent=0.007)
          

          You can read more about how they operate here in the docs

          RunBacktest.com

          J 1 Reply Last reply Reply Quote 1
          • J
            j63009567 @run-out last edited by

            @run-out

            I thought the trailing stop loss would automatically execute?

            I think there is something error with my code, as the trailing stop loss doesn't seem to be hitting

            I added a bracket order, and the limit price is not executing despite the price reaching that target on the graph, as we have a position already?

            A sell is only detected when close < sma

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