Getting executed twice on closing orders
-
I just realized this is probably in the wrong forum, but don't have enough privileges go delete so can an admin move?
Hello. I am getting executed twice on a time triggered close order. Anyone have any thoughts on why this would occur and how to solve this?
def next(self): dt = self.datas[0].datetime.date(0) wkdy = datetime.datetime.weekday(dt) tme = self.datas[0].datetime.time(0) #If not in trade and day is wed and time is 930 and the closing 5m print is up buy 1 lot if not self.position: if wkdy == 2: if tme == datetime.time(9,30,0,0): if (((self.dataclose[0] / self.dataclose[-5])-1)*100) > 0: self.buy(size=1,trailamount=1) #Exit positions at 12:01 open if trail stop not triggered elif self.position: if tme == datetime.time(12, 00, 0, 0): self.close()
and the console output in pycharm
Any thoughts? This is by far the most powerful backtesting engine I have used and love it!
-
Partial code won't for sure help. The likely culprit: you are printing twice. But cannot be ascertained.
-
Sorry, realize it might be helpful for you to have the logging code for a question about logging.
My first reaction to printing twice is thats probably true, but I can't seem where to find where it is printed twice. It looks like maybe the close function is doing twice as many contracts as I have open, but when i put
self.close(size=1)
nothing changes, I still go short 2 contracts when I am trying to close out the 1 long contract I have open. Any other users have this issue?class Strat(bt.Strategy): def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = self.datas[0].datetime.date(0) dt_time = self.datas[0].datetime.time(0) dt_weekday = datetime.datetime.weekday(dt) 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 self.dataopen = self.datas[0].open self.dt = self.datas[0].datetime.date(0) self.dt_time = self.datas[0].datetime.time(0) self.dt_weekday = datetime.datetime.weekday(self.dt) 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 enougth cash if order.status in [order.Completed]: if order.isbuy(): self.log( 'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' % (order.executed.price, order.executed.value, order.executed.comm, bt.num2date(order.executed.dt))) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' % (order.executed.price, order.executed.value, order.executed.comm, bt.num2date(order.executed.dt))) self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') 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)) #####CHANGED IN V4 def next(self): dt = self.datas[0].datetime.date(0) wkdy = datetime.datetime.weekday(dt) tme = self.datas[0].datetime.time(0) if self.position: if tme == datetime.time(12,00,0,0): self.close() elif not self.position: if wkdy == 2: if tme == datetime.time(9,30,0,0): if (((self.dataclose[0] / self.dataclose[-5])-1)*100) > 0: self.buy(size=1)
-
The problem is still that part of the whole still has holes
You may not think that the surrounding parts for your strategy play any role in your whereabouts. But they mostly probably do. Things like how the data feed is loaded.
-
@backtrader Here is the code in its entirety. In the main i feed the data as a pandas dataframe and run don't do much else. I have also included a screenshot of the dataframe that is imported.
Thanks for all your help!
class Strat(bt.Strategy): def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = self.datas[0].datetime.date(0) dt_time = self.datas[0].datetime.time(0) dt_weekday = datetime.datetime.weekday(dt) 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 self.dataopen = self.datas[0].open self.dt = self.datas[0].datetime.date(0) self.dt_time = self.datas[0].datetime.time(0) self.dt_weekday = datetime.datetime.weekday(self.dt) 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 enougth cash if order.status in [order.Completed]: if order.isbuy(): self.log( 'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' % (order.executed.price, order.executed.value, order.executed.comm, bt.num2date(order.executed.dt))) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' % (order.executed.price, order.executed.value, order.executed.comm, bt.num2date(order.executed.dt))) self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') 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)) #####CHANGED IN V4 def next(self): dt = self.datas[0].datetime.date(0) wkdy = datetime.datetime.weekday(dt) tme = self.datas[0].datetime.time(0) if self.position: if tme == datetime.time(12,00,0,0): self.close() elif not self.position: if wkdy == 2: if tme == datetime.time(9,30,0,0): if (((self.dataclose[0] / self.dataclose[-5])-1)*100) > 0: self.buy(size=1) if __name__ == '__main__': #Start the brain cerebro = bt.Cerebro() # Load Strat cerebro.addstrategy(Strat) #Start cash level cerebro.broker.setcash(10000.0) #Set multiplier and commish level cerebro.broker.setcommission(commission=0.79, margin=3000.0, mult=1000.0) #Get dataframe df = pd.DataFrame() df = bck.df() #Add Dataframe from other module data = bt.feeds.PandasData(dataname=df) #Load data to brain cerebro.adddata(data) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) results = cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.plot(style='bar')
-
@Osofuego said in Getting executed twice on closing orders:
#Add Dataframe from other module data = bt.feeds.PandasData(dataname=df)
Your data is clearly
1-minute
based, but you are not telling that to the platform. You are letting the defaults kick-in, i.e.:1-day
.Hence the multiple execution which happens only when the day changes, because the timeframe is daily based. Your
self.position
check happens more than once during the day.See for example
- Community - FAQ
- Community -Intraday time issue/Orders waiting until T+1 (which was due to typo, but it's exactly the same)
-
Re: Getting executed twice on closing orders
Ah, I am an idiot. Thanks for your help I had a datafeed issue. Thx!
Working code below.if __name__ == '__main__': #Start the brain cerebro = bt.Cerebro() # Load Strat cerebro.addstrategy(Strat) #Start cash level cerebro.broker.setcash(10000.0) #Set multiplier and commish level cerebro.broker.setcommission(commission=0.79, margin=3000.0, mult=1000.0) #Get dataframe df = pd.DataFrame() df = bck.df() #Add Dataframe from other module data = bt.feeds.PandasData(dataname=df,timeframe=bt.TimeFrame.Minutes,compression=1) #Load data to brain cerebro.adddata(data) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) results = cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())