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 documentimport 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
andcheat-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 theclose
of the current bar,cheat-on-open
helps to issue and execute an order on theopen
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.