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/

    Final SELL order not created in Quickstart Examples

    General Discussion
    4
    5
    166
    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.
    • Y
      Yulem last edited by

      I'm learning Backtrader by following the examples in Quickstart Guide.
      The only modifications I've made to the examples are in the data feed and broker.setcash (increased to cover orders). The problem is that in all the examples up through "Customizing the Strategy: Parameters " everything works as I expect and matches the example outputs (except for values since I'm using a different data set).
      When I test the "Adding an indicator" code it generates a BUY order but no SELL order is generated upon exit leaving me with an open position. I believe the logic is to generate a SELL using the final day's CLOSE value which makes sense and is what I saw in the previous examples. What am I missing???
      Below are the changes to the data feed that I made.

          # 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, 'data/Sector ETFs/VTI.csv')
      
          # Create a Data Feed
          data = bt.feeds.GenericCSVData(
              dataname=datapath,
              # Do not pass values before this date
              fromdate=datetime.datetime(2019, 1, 1),
              # Do not pass values before this date
              todate=datetime.datetime(2020, 8, 31),
              # Do not pass values after this date
              reverse=False,
              #Fix DateTime format
              dtformat= '%Y-%m-%d',
              close = 6)```
      code_text
      

      Thanks for your help in advance.

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

        It is helpful if you include all of the code, the output you are getting, and where you think that output is wrong. Thanks

        RunBacktest.com

        1 Reply Last reply Reply Quote 0
        • Y
          Yulem last edited by

          Sorry, the code is what is reproduced in the Quickstart examples, exactly, except for the code I included.
          Here's the output:

          
          .
          .
          .
          2020-06-23, Close, 157.42
          2020-06-23, BUY CREATE, 157.42
          2020-06-24, BUY EXECUTED, Price: 157.91, Cost: 1579.10, Comm 0.00
          2020-06-24, Close, 153.15
          2020-06-24, SELL CREATE, 153.15
          2020-06-25, SELL EXECUTED, Price: 155.77, Cost: 1579.10, Comm 0.00
          2020-06-25, OPERATION PROFIT, GROSS -21.40, NET -21.40
          2020-06-25, Close, 155.00
          2020-06-26, Close, 151.40
          2020-06-29, Close, 153.62
          2020-06-30, Close, 155.89
          2020-06-30, BUY CREATE, 155.89
          2020-07-01, BUY EXECUTED, Price: 158.04, Cost: 1580.40, Comm 0.00
          2020-07-01, Close, 156.80
          2020-07-02, Close, 157.42
          .
          .
          .
          
          2020-08-25, Close, 173.74
          2020-08-26, Close, 175.31
          2020-08-27, Close, 175.73
          2020-08-28, Close, 176.95
          Final Portfolio Value: 100528.34
          

          Here's the Quickstart example:

          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 the backtrader platform
          import backtrader as bt
          
          
          # Create a Stratey
          class TestStrategy(bt.Strategy):
              params = (
                  ('maperiod', 15),
              )
          
              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()
          
                  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(TestStrategy)
          
              # 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, 'data/Sector ETFs/VTI.csv')
          
              # Create a Data Feed
              data = bt.feeds.GenericCSVData(
                  dataname=datapath,
                  # Do not pass values before this date
                  fromdate=datetime.datetime(2019, 1, 1),
                  # Do not pass values before this date
                  todate=datetime.datetime(2020, 8, 31),
                  # Do not pass values after this date
                  reverse=False,
                  #Fix DateTime format
                  dtformat= '%Y-%m-%d',
                  close = 6)
          
              # Add the Data Feed to Cerebro
              cerebro.adddata(data)
          
              # Set our desired cash start
              cerebro.broker.setcash(100000.0)
          
              # Add a FixedSize sizer according to the stake
              cerebro.addsizer(bt.sizers.FixedSize, stake=10)
          
              # Set the commission
              cerebro.broker.setcommission(commission=0.0)
          
              # Print out the starting conditions
              print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
          
              # Run over everything
              cerebro.run()
          
              # Print out the final result
              print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
          
              # Plot the result
              cerebro.plot()
          
          
          1 Reply Last reply Reply Quote 0
          • hghhgghdf dfdf
            hghhgghdf dfdf last edited by

            @Yulem said in Final SELL order not created in Quickstart Examples:

            but no SELL order is generated upon exit leaving me with an open position. I believe the logic is to generate a SELL using the final day's CLOSE value which makes sense and is what I saw in the previous examples.

            There is no problem with your code. Whether you still have a position open or closed at the end of a backtest is inconsequential. If you want to generate a sell specifically using the final day's close value, you can do so in the strategy's stop method

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

              @Yulem said in Final SELL order not created in Quickstart Examples:

              I believe the logic is to generate a SELL using the final day's CLOSE value which makes sense and is what I saw in the previous examples. What am I missing???

              In the Quickstart guide examples there is no logic to close the position at the end of the backtest.

              @hghhgghdf-dfdf said in Final SELL order not created in Quickstart Examples:

              If you want to generate a sell specifically using the final day's close value, you can do so in the strategy's stop method

              I didn't try this by myself, but based on the bt workflow I doubt that this will work, since stop is called after all the bars are gone and it should be no price to execute the order.

              • 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
              1 Reply Last reply Reply Quote 2
              • 1 / 1
              • First post
                Last post
              Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors