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

Entering and taking profit on the same bar



  • for simple MA crossover strategy, when an order is created, if the next bar triggers the entry but simultaneously hits the target, it will only execute the entry and then exit the bar after that on the open. I can't figure it out. I've been trying different order types but I haven't been able to change the behavior. I've experimented with cheat on open but that didn't get me anywhere

    class Order_testing(bt.Strategy):
    
        params = dict(
            pfast=10,  # period for the fast moving average
            pslow=30   # period for the slow moving average
        )
    
        
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = dt or self.datas[0].datetime.datetime(0)
            print('%s, %s' % (dt.strftime("%Y-%m-%d %H:%M"), txt))
    
        def __init__(self):
            
            sma1 = bt.ind.SMA(period=self.p.pfast)  # fast moving average
            sma2 = bt.ind.SMA(period=self.p.pslow)  # slow moving average
            self.crossover = bt.ind.CrossOver(sma1, sma2)  # crossover signal
    
            # To keep track of pending orders and buy price/commission
            self.order = None
            self.buyprice = None
            self.buycomm = None
    
        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: %.5f, Cost: %.f, 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: %.5f, Cost: %.f, 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')
    
            self.order = None
    
        def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            self.log('OPERATION PROFIT, GROSS %.5f, NET %.5f' %
                     (trade.pnl, trade.pnlcomm))
    
        def next(self):
    
            # Check if an order is pending ... if yes, we cannot send a 2nd one
            if self.order:
                if self.order.status == 2 and len(self) == self.bar_order_submitted + 1:
                    self.broker.cancel(self.order)
                    self.log("order was cancelled")
    
    
            # Check if we are in the market
            if not self.position:
    
                # Not yet ... we MIGHT BUY if ...
                if self.crossover > 0:  # if fast crosses slow to the upside
    
                    self.order = self.buy(exectype=bt.Order.StopLimit, price=self.data.high[0], transmit=False)
                    self.StopLoss = self.sell(price=self.data.low[0],exectype=bt.Order.Stop, 
                                            transmit=False, size=self.order.size,parent=self.order)
                    self.target = self.sell(price=(self.data.high[0]-self.data.low[0])*1.1+self.data.high[0], exectype=bt.Order.Limit, 
                                            transmit=True, size=self.order.size,  parent=self.order)
    
                    self.bar_order_submitted = len(self)
                    
    
                    self.log('BUY CREATE, %.5f' % self.order.price)
    
                    self.log('SL: %.5f, T: %.5f' %(self.StopLoss.price,self.target.price))
                              
    
    if __name__ == '__main__':
    
        cerebro = bt.Cerebro()
    
        # Add a strategy
        cerebro.addstrategy(Order_testing)
        
        # Create a Data Feed
        data = bt.feeds.PandasData(dataname=df2020)
        one_minute = cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=1)
          
        
        # Print out the starting conditions
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
        
        cerebro.run()
        
        # Print out the final result
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    

    log for reference. it should both execute the buy and sell order at 06:29

    2020-08-12 06:28, BUY CREATE, 1.17185
    2020-08-12 06:28, SL: 1.17171, T: 1.17200
    2020-08-12 06:29, BUY EXECUTED, Price: 1.17185, Cost: 1, Comm 0.00
    2020-08-12 06:30, SELL EXECUTED, Price: 1.17203, Cost: 1, Comm 0.00
    2020-08-12 06:30, Order Canceled/Margin/Rejected
    2020-08-12 06:30, OPERATION PROFIT, GROSS 0.00018, NET 0.00018
    


  • I am not really sure with this. Maybe the quicknotify param could help you with that problem.



  • @dasch much appreciate the quick response. I've tried it but it doesn't work. I haven't found any posts on the forum where it was mentioned either unfortunately.



  • could you post the data file to play with that problem a bit?



  • I would but I can't see how to add an attachment? if not possible, I'll add it to dropbox and then send it that way



  • you can send it directly to my email, which is available in my profile



  • @Jens-Halsberghe said in Entering and taking profit on the same bar:

    if the next bar triggers the entry but simultaneously hits the target, it will only execute the entry and then exit the bar after that on the open.

    This is default behaviour since it is impossible to know for sure what order the triggers for enter and sale happen when using just one bar of data. Perhaps the enter price happens just before the close but the stop price happens near the open. It's problematic. If you wish to have greater granularity you may wish to consider using a smaller time frame, or perhaps replay.



  • @run-out you are right. we went through this yesterday via email. The result was like you explained. The child order gets activated after the parent order gets executed and will be checked in next cycle.

    One way to manually allow executing on the same bar is to activate the child order by hand.

    after the order was created:

    self.target.activate()
    

    Which is not that good idea, since then you don't know, if the parent order was executed, too.



  • I agree and I understand the logic. I can't replay but also, it's useful to use target.activate() and it can be used to do only in certain scenarios where it looks most likely the target would have been hit. for example if the price never even reached the stoploss but got to the entry and then the target, it's perfectly fine to use it. in case of a big outside bar which would hit all three entry, target and stoploss there would be doubt but it's more an exceptional case.

    thanks again for your help Dasch


Log in to reply
 

});