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

stop trail order executed but position not change



  • In my strategy, a stop trail order has been executed, but the position has not changed and the trade has not been closed.
    Then another sell order executed, the trade close.
    Is there anyone who can help me solve this problem?

    2015-03-18, BUY EXECUTED, Price: 2.55, Cost: 2550.00, Comm 0.00
    2015-03-24, SELL EXECUTED, Price: 2.62, Cost: 2.55, Comm 0.00
    2015-05-18, SELL EXECUTED, Price: 2.98, Cost: 2550.43, Comm 0.00
    2015-05-18, OPERATION PROFIT, GROSS 429.64, NET 429.64
    
       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):
           
           if not self.position: # no position
               
               if self.datas[0].close > self.upband:
                   self.order = self.buy()            
                   self.sl_order = self.sell(size=1, exectype=bt.Order.StopTrail, trailpercent=0.02)
               if self.datas[0].close < self.downband:
                   self.order = self.sell()
                   self.sl_order = self.buy(size=1, exectype=bt.Order.StopTrail, trailpercent=0.02)
           
           else: # have position
               
               if self.position.size > 0 and self.datas[0].close < self.ema:
                   self.order = self.sell()
                   
               elif self.position.size < 0 and self.datas[0].close > self.ema:
                   self.order = self.buy()
    

  • administrators

    @sanmao said in stop trail order executed but position not change:

    2015-03-18, BUY EXECUTED, Price: 2.55, Cost: 2550.00, Comm 0.00
    2015-03-24, SELL EXECUTED, Price: 2.62, Cost: 2.55, Comm 0.00
    2015-05-18, SELL EXECUTED, Price: 2.98, Cost: 2550.43, Comm 0.00
    

    The 1st sell ist obviously not closing the position opened by the buy.

    • Buy Cost: 2550
    • Sell 1 Cost: 2.55
    • Sell 2 Cost: 2550.43 (this one obviously is closing the trade)

    Given the lack of other information, not much more can be said.



  • @backtrader Sorry, I set the wrong order size in stop_loss_order. I have fixed it. But there comes another problem.
    Sometimes, my order executed twice in one bar, like these.

    2015-07-28, SELL EXECUTED, Price: 2.44, Cost: 2444.00, Comm 0.00
    2015-07-28, SELL EXECUTED, Price: 2.44, Cost: 2444.00, Comm 0.00
    2015-07-30, BUY EXECUTED, Price: 2.54, Cost: 2444.00, Comm 0.00
    2015-07-30, BUY EXECUTED, Price: 2.54, Cost: 2444.00, Comm 0.00
    2015-07-30, OPERATION PROFIT, GROSS -195.52, NET -195.52
    
    2016-07-04, BUY EXECUTED, Price: 2.18, Cost: 2181.50, Comm 0.00
    2016-07-04, BUY EXECUTED, Price: 2.16, Cost: 2156.54, Comm 0.00
    2016-08-02, SELL EXECUTED, Price: 2.19, Cost: 2169.02, Comm 0.00
    2016-08-03, SELL EXECUTED, Price: 2.19, Cost: 2169.02, Comm 0.00
    2016-08-03, OPERATION PROFIT, GROSS 40.95, NET 40.95
    

    Below is my strategy.

    class KeltnerChannelStrategy(bt.Strategy):
        params = (
                ('emaperiod', 20),
                ('atrperiod', 45),
                ('multipleAtr', 1.5),
                ('stop_loss', 0.04)
                )
        
        def log(self, txt, dt=None):
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
        
        def __init__(self):
            self.ema = bt.indicators.ExponentialMovingAverage(self.datas[0], period=self.params.emaperiod)
            self.atr = bt.indicators.AverageTrueRange(self.datas[0], period=self.params.atrperiod)
            self.upband = self.ema + self.params.multipleAtr * self.atr
            self.downband = self.ema - self.params.multipleAtr * self.atr
            
            # plot indicators
            bt.LinePlotterIndicator(self.upband, name='upband', subplot=False)
            bt.LinePlotterIndicator(self.downband, name='downband', subplot=False)
            
            self.order = None
            
            
        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                return
            
            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)                    
                    )
                    
                    if self.position.size > 0:                
                        stop_price = order.executed.price * (1.0 - self.params.stop_loss)
                        self.sell(exectype=bt.Order.Stop, price=stop_price)
                    
                elif order.issell():
                    self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                                             (order.executed.price,
                                              order.executed.value,
                                              order.executed.comm)
                    )
                    
                    if self.position.size < 0:
                        stop_price = order.executed.price * (1.0 + self.params.stop_loss)
                        self.buy(exectype=bt.Order.Stop, price=stop_price)                
                
            elif order.status in [order.Margin, order.Rejected]:
                pass
            elif order.status in [order.Canceled]:
                self.log('Order Canceled !')
                
        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):
            if not self.position:
                if self.datas[0].close > self.upband:
                    self.buy()            
                if self.datas[0].close < self.downband:
                    self.sell()
            else:
                if self.position.size > 0 and self.datas[0].close < self.ema:
                    self.sell()
                elif self.position.size < 0 and self.datas[0].close > self.ema:
                    self.buy()
                
    
    cerebro = bt.Cerebro(tradehistory=True)
    cerebro.addstrategy(KeltnerChannelStrategy)
    
    dataname = pd.read_csv(r'E:\backtrader_study\dfqc.csv', index_col=0, parse_dates=True)
    dataname['openinterest'] = 0
    
    data = bt.feeds.PandasData(dataname=dataname,
                               fromdate=datetime.datetime(2015,1,1),
                               todate=datetime.datetime(2016,12,31))
    
    cerebro.adddata(data)
    cerebro.broker.setcash(10000.0)
    cerebro.broker.set_shortcash(False)
    cerebro.addsizer(bt.sizers.FixedSize, stake=1000)
    cerebro.broker.setcommission(commission=0.000)
    
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    result = cerebro.run()
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    cerebro.plot()
    

  • administrators

    @sanmao said in stop trail order executed but position not change:

    Sometimes, my order executed twice in one bar, like these.

    No. If you printed meaningful information like the order reference you will most likely see that you are creating more than one order.

    You'd probably find the errors before if your first instinct was not to blame the framework ... (it may not be perfect, but things like closing at trade have been stable for a very long time)