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



  • 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.



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



  • 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()
    
    


  • @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



  • @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.


Log in to reply
 

});