For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

How to execute(buy or sell) create and complete operations at one time?



  • For instance,
    2018-02-20, BUY CREATE AAPL, price = 171.85
    2018-02-21, BUY COMPLETE, 178.13
    171.85 and 178.13 are the close price of each day.
    It is daily trading. Complete operation is performed the next day, in 2018-02-21.
    I want to create and complete the operation in 2018-02-20.
    I mean that the action was created and completed at a price of 171.85.
    Is it possible to perform such an operation?
    In short, I want to buy and sell shares in the market the same day when a signal comes to me, and not the next day as in the document

    import datetime  # For datetime objects
    import os  # To manage paths
    import sys  # To find out the script name (in argv[0])
    
    # Import the backtrader platform
    import backtrader as bt
    import scipy.stats
    
        
    # Create a Stratey
    class TestStrategy(bt.Strategy):
    
        lines = ('correlation',)
        params = dict(
            period20=20,
            period10=10,
            stake=10,
            qty1=0,
            qty2=0,
            status=0,
            portfolio_value=10000,
        )
    
        
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
    
        
        def notify_order(self, order):
            if order.status in [bt.Order.Submitted, bt.Order.Accepted]:
                return  # Await further notifications
    
            if order.status == order.Completed:
                if order.isbuy():
                    buytxt = 'BUY COMPLETE, %.2f' % order.executed.price
                    self.log(buytxt)
                else:
                    selltxt = 'SELL COMPLETE, %.2f' % order.executed.price
                    self.log(selltxt)
                
            elif order.status in [order.Expired, order.Canceled, order.Margin]:
                self.log('%s ,' % order.Status[order.status])
                pass  # Simply log
    
            # Allow new orders
            self.orderid = None
        
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            
            self.orderid = None
            self.qty1 = self.p.qty1
            self.qty2 = self.p.qty2
            self.status = self.p.status
            self.portfolio_value = self.p.portfolio_value
            self.profit_fix = 30
            self.profit = 0 
            self.cash_aapl = 0
            self.cash_msft = 0
            self.init_close1 = 0
            self.init_close2 = 0
            
            
        def next(self):
            if self.orderid:
                return
            print('*'*20)
            print('Status is ', self.status)
    
            c10, p = scipy.stats.pearsonr(self.data0.get(size=self.p.period10),
                                         self.data1.get(size=self.p.period10))
    
            c20, p = scipy.stats.pearsonr(self.data0.get(size=self.p.period20),
                                         self.data1.get(size=self.p.period20))
            c10, c20 = round(c10, 2), round(c20, 2)
            self.log('Close, {}'.format(self.datas[0].close[0]))
            self.log('Close, {}'.format(self.datas[1].close[0]))    
            print('corr10: {}, corr20: {}'.format(c10, c20))
            # Step 2: Check conditions for LONG & place the order
            # Checking the condition for LONG
    
            
            if self.status == 1:
                self.cash_aapl = round((self.data0.close[0] - self.init_close1)*self.qty1,2)
                self.cash_msft = round((self.init_close2 - self.data1.close[0])*self.qty2,2)
                self.profit = round((self.cash_aapl + self.cash_msft),2)
                
                print('Profit stock1: {}'.format(self.cash_aapl))
                print('Profit stock2: {}'.format(self.cash_msft))
                print('Total profit: {}'.format(self.profit))
                   
            
            if (c10 > 0.7 and c20 > 0.7) and (self.status != 1):
    
                # Calculating the number of shares for each stock
                value = 0.45 * self.portfolio_value  # Divide the cash equally
                x = int(value / (self.data0.close))  # Find the number of shares for Stock1
                y = int(value / (self.data1.close))  # Find the number of shares for Stock2
    
                
                print('portfolio_value: {}'.format(self.portfolio_value))
                
                # Place the order
                self.log('BUY CREATE %s, price = %.2f, qty = %d' % ("AAPL", self.data0.close[0], x))
                self.buy(data=self.data0, size=(x))  
    
                self.log('SELL CREATE %s, price = %.2f, qty = %d' % ("MSFT", self.data1.close[0], y))
                self.sell(data=self.data1, size=(y))  
    
                
                self.qty1 = x  # The new open position quantity for Stock1 is x shares
                self.qty2 = y  # The new open position quantity for Stock2 is y shares
                self.init_close1 = self.data0.close[0]
                self.init_close2 = self.data1.close[0]
                self.status = 1  # The current status is "long the spread"
                
            elif (self.profit > self.profit_fix) and self.status == 1:
                print('profit: {}, profit_fix: {}'.format(self.profit, self.profit_fix))
                # Placing the order
                self.log('SELL CREATE %s, price = %.2f, qty = %d' % ("AAPL", self.data0.close[0], self.qty1))
                self.sell(data=self.data0, size=(self.qty1))  
                
                self.log('BUY CREATE %s, price = %.2f, qty = %d' % ("MSFT", self.data1.close[0], self.qty2))
                self.buy(data=self.data1, size=(self.qty2))  
    
                # Updating the counters with new value
                self.portfolio_value+=self.profit
                self.qty1, self.qty2 = 0, 0
                
                self.cash_aapl, self.cash_msft, self.profit = 0, 0, 0
                
                self.status = 0 
    
        def stop(self):
            print('==================================================')
            print('Starting Value - %.2f' % self.broker.startingcash)
            print('Ending   Value - %.2f' % self.broker.getvalue())
            print('==================================================')
            
            
    if __name__ == '__main__':
        # Create a cerebro entity
        cerebro = bt.Cerebro()
    
        # Add a strategy
        cerebro.addstrategy(TestStrategy)
        
        
        def read_data(file_name):    
            datapath = os.path.abspath(os.getcwd() + '/' + file_name)
            return bt.feeds.YahooFinanceCSVData(
                    dataname=datapath,
                    # Do not pass values before this date
                    #fromdate=datetime.datetime(2018, 1, 1),
                    # Do not pass values before this date
                    #todate=datetime.datetime(2019, 1, 1),
                    # Do not pass values after this date
                    reverse=False)
        
        # Create a Data Feed
        data1 = read_data('aapl_1819.csv')
        cerebro.adddata(data1, name='AAPL')
        
        data2 = read_data('msft_1819.csv')
        cerebro.adddata(data2, 'MSFT')
        
        # Set our desired cash start
        cerebro.broker.setcash(100000.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())
    

    Output:

    Status is  0
    2018-02-20, Close, 171.85
    2018-02-20, Close, 92.72
    corr10: 0.9, corr20: 0.73
    portfolio_value: 10000
    2018-02-20, BUY CREATE AAPL, price = 171.85, qty = 26
    2018-02-20, SELL CREATE MSFT, price = 92.72, qty = 48
    2018-02-21, BUY COMPLETE, 178.13
    2018-02-21, SELL COMPLETE, 95.61
    ********************
    Status is  1
    2018-02-21, Close, 171.07
    2018-02-21, Close, 91.49
    corr10: 0.93, corr20: 0.76
    Profit stock1: -20.28
    Profit stock2: 59.04
    Total profit: 38.76
    profit: 38.76, profit_fix: 30
    2018-02-21, SELL CREATE AAPL, price = 171.07, qty = 26
    2018-02-21, BUY CREATE MSFT, price = 91.49, qty = 48
    2018-02-22, SELL COMPLETE, 177.95
    2018-02-22, BUY COMPLETE, 94.96


  • Take a look on cheat-on-close and cheat-on-open modes. This is probably what you are looking for.



  • @ab_trader thanks, but I do not benefit from this because the prices are different and I want to buy a stock that day at the same price

    2018-02-20, BUY CREATE AAPL, price = 171.85, qty = 26
    2018-02-20, BUY COMPLETE, 178.27
    I want to buy and complete stock with a price 171.85, not 178.27



  • @Sasha said in How to execute(buy or sell) create and complete operations at one time?:

    but I do not benefit from this because the prices are different and I want to buy a stock that day at the same price

    With two cheat modes shown above you will be able to issue and execute the order on the same bar. Briefly, cheat-on-close helps to execute your order on the close of the current bar, cheat-on-open helps to issue and execute an order on the open of the bar. I recommend you to read the docs.



  • Thanks a lot
    I need to be careful )



  • @Sasha consider using the replay datafeeds functionality of Backtrader. This allows you to make trading decisions on a lower timeframe while your higher level algorithm still operates on the higher timeframe. For instance, my system looks at indicators to make choices on the 1D candle, but my entries and exits are made on the 1H level. This way I can place a trade 1H before the close of the 1D candle and my trading results will be much more accurate.


Log in to reply
 

});