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

Need help with problem with positions closing code.



  • Hi,

    I am trying to code strategy based on SuperTrend indicator where the initial transaction is done with BUY or Sell Order but subsequent transactions are done with stop order used for switching the positions.

    But the code seems to be working with some parameters and fail with other for the same daily data. Below is both indicator code and Strategy Code.

    import backtrader as bt
    import numpy as np
    
    
    class SuperTrend(bt.Indicator):
        lines = ('overunder',)
        plotinfo = dict(subplot=False)
        params = dict(period=7, multiplier=3, ticksize=0.01)
    
        def __init__(self):
            self.addminperiod(self.params.period)
            self.atr = bt.ind.ATR(period=self.params.period)
            #self.l.overunder = ( self.data.high + self.data.low ) / 2
            self.__tick = self.params.ticksize
            decimal = str(self.params.ticksize).split('.')
            if len(decimal) is not 1:
                self.__decimal = len(decimal[1])
            else:
                self.__decimal = 0
            self.__prevClose = 0
            self.__prevFUP = 0
            self.__prevFDN = 0
            self.__prevSuperTrend = 0
            self.__prevHL = 0
            
        def next(self):
            HL =  ( self.datas[0].high.get(size=1).tolist()[0] + self.datas[0].low.get(size=1).tolist()[0] ) / 2
            Close = self.datas[0].close.get(size=1).tolist()[0]
            FUP = 0.00
            FDN = 0.00
            SuperTrend = Close
            mul = self.params.multiplier
            atr = np.around(self.atr[0],self.__decimal)
            
            if atr is not None:
                UPPER = HL+(mul*np.around(atr,self.__decimal))
                LOWER = HL-(mul*np.around(atr,self.__decimal))
                if( UPPER < self.__prevFUP or self.__prevClose > self.__prevFUP ):
                    FUP = self.roundSP(np.around(UPPER,self.__decimal))
                else:
                    FUP = self.__prevFUP
                    
                if( LOWER > self.__prevFDN or self.__prevClose < self.__prevFDN ):
                    FDN = self.roundSP(np.around(LOWER,self.__decimal))
                else:
                    FDN = self.__prevFDN
                    
                if( self.__prevSuperTrend == self.__prevFUP and Close <= FUP ):
                    SuperTrend = FUP
                else:
                    if( self.__prevSuperTrend == self.__prevFUP and Close >= FUP ):
                        SuperTrend = FDN
                    else:
                        if( self.__prevSuperTrend == self.__prevFDN and Close >= FDN ):
                            SuperTrend = FDN
                        else:
                            if( self.__prevSuperTrend == self.__prevFDN and Close <= FDN ):
                                SuperTrend = FUP
                    
                self.__prevFUP = FUP
                self.__prevFDN = FDN
                self.__prevSuperTrend = SuperTrend
                    
            
            self.__prevClose = Close
            self.l.overunder[0] = SuperTrend
            
        def roundSP( self, num ):
            return np.around((np.around((num+(self.__tick/2))/self.__tick)*self.__tick)-self.__tick,self.__decimal)
    
    # -*- coding: utf-8 -*-
    """
    Created on Sun Apr  1 04:58:49 2018
    
    @author: Vithal Patil
    """
    
    from datetime import datetime
    import backtrader as bt
    import backtrader.analyzers as btanalyzers
    import backtrader.strategies as btstrats
    import numpy as np
    import btSupertrend
    
    class SuperTrendStrategy(bt.SignalStrategy):
        params = (('pfast', 10), ('pslow', 30),)
        
        def __init__(self):
            self.dataclose = self.datas[0].close
            self.supertrend = btSupertrend.SuperTrend(period=7, multiplier=2, ticksize=1)
            self.trade = None
            self.buystop_order = None
            self.sellstop_order = None
            self.qty = 1
            
        def next(self):
            if self.supertrend[0] < self.dataclose:
                if self.trade == None:
                    self.buy()
                    #self.log('LONG %s ' % ( self.trade ))
                elif self.trade == 'buy_stop':
                    if self.buystop_order:
                        self.cancel(self.buystop_order)
                    self.buystop_order = self.sell(exectype=bt.Order.Stop, price=self.supertrend[0], size=self.qty) 
                    #self.log('SHORT STOP %s ' % ( self.trade ))
            if self.supertrend[0] > self.dataclose:
                if self.trade == None:
                    self.sell()
                    #self.log('SHORT %s ' % ( self.trade ))
                elif self.trade == 'sell_stop':
                    if self.sellstop_order:
                        self.cancel(self.sellstop_order)
                    self.sellstop_order = self.buy(exectype=bt.Order.Stop, price=self.supertrend[0], size=self.qty) 
                    #self.log('SHORT STOP %s ' % ( self.trade ))
                    
        def notify_order(self, order):
            if not order.status == order.Completed:
                #self.log('LONG @ %s and qty %s' % ( order.executed.price,order.executed.size ))
                return  # discard any other notification
            elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                self.log('Order Canceled/Margin/Rejected')
            else:
                if order.isbuy():
                    if self.trade == None or self.trade == 'buy_hit':
                        if self.supertrend[0] < self.dataclose:
                            self.trade = 'buy_stop'
                            self.qty = 2
                            self.log('FRESH LONG STARTED, @ %s and qty %s  Trade %s  varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
                        if self.supertrend[0] > self.dataclose:
                            self.sell(size=self.qty)
                            self.trade = 'sell_hit'
                            self.log('BUY STOP HIT, @ %s and qty %s Trade %s varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
                    if self.trade == 'sell_stop':
                        if self.supertrend[0] > self.dataclose:
                            self.sell(size=self.qty)
                            self.trade = 'sell_hit'
                            self.log('BUY STOP HIT, @ %s and qty %s Trade %s varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
                        if self.supertrend[0] < self.dataclose:
                            self.trade = 'buy_stop'
                            self.log('LONG SWITCH, @ %s and qty %s  Trade %s  varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
                if order.issell():
                    if self.trade == None or self.trade == 'sell_hit':
                        if self.supertrend[0] > self.dataclose:
                            self.qty = 2
                            self.trade = 'sell_stop'
                            self.log('FRESH SHORT STARTED, @ %s and qty %s Trade %s varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
                        if self.supertrend[0] < self.dataclose:
                            self.buy(size=self.qty)
                            self.trade = 'buy_hit'
                            self.log('SELL STOP HIT, @ %s and qty %s Trade %s varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
                    if self.trade == 'buy_stop':
                        if self.supertrend[0] < self.dataclose:
                            self.buy(size=self.qty)
                            self.trade = 'buy_hit'
                            self.log('SELL STOP HIT, @ %s and qty %s Trade %s varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
                        if self.supertrend[0] > self.dataclose:
                            self.trade = 'sell_stop'
                            self.log('SHORT SWITCH, @ %s and qty %s Trade %s varTrade %s' % ( order.executed.price, order.executed.size, self.position.size, self.trade ))
    
                            
    
                    
                    
            #self.log('STATUS %s' % ( self.position.size ))
                
        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))
    
    cerebro = bt.Cerebro()
    data = bt.feeds.GenericCSVData(
        dataname='GOLDPETAL.csv',
        fromdate=datetime(2012, 10, 29),
        todate=datetime(2018, 4, 20),
        nullvalue=0.0,
        dtformat=('%Y-%m-%d'),
        tmformat=('%H:%M:%S'),
        datetime=0,
        time=1,
        high=3,
        low=4,
        open=2,
        close=5,
        volume=6,
        openinterest=-1,
        decimals=0,
        compression=1,
        timeframe=bt.TimeFrame.Days
    )
    cerebro.adddata(data)
    
    cerebro.addstrategy(SuperTrendStrategy)
    
    cerebro.broker.setcommission(mult=1)
    cerebro.addanalyzer(btanalyzers.AnnualReturn, _name='annualreturns')
    cerebro.addanalyzer(btanalyzers.DrawDown, _name='drawdown')
    cerebro.addanalyzer(btanalyzers.Returns, _name='positionvalue')
    cerebro.addanalyzer(btanalyzers.SQN, _name='sqn')
    cerebro.addanalyzer(btanalyzers.TradeAnalyzer, _name='trades')
    thestrats = cerebro.run()
    thestrat = thestrats[0]
    
    ar = thestrat.analyzers.annualreturns.get_analysis()
    print('\n\nAnnual Returns:\n')
    for key, value in ar.items():
        print("%s - %s" % (key, value))
        
    draw = thestrat.analyzers.drawdown.get_analysis()
    print('\n\nDrawDown:\n')
    for key, value in draw.items():
        print("%s - %s" % (key, value))
        
    returns = thestrat.analyzers.positionvalue.get_analysis()
    print('\n\nReturns:\n')
    for key, value in returns.items():
        print("%s - %s" % (key, value))
        
    sqn = thestrat.analyzers.sqn.get_analysis()
    print('\n\nSQN:\n')
    for key, value in sqn.items():
        print("%s - %s" % (key, value))
        
    cerebro.plot(iplot=False,style='bar',volume=True)
    

    Also below the screenshot for the reference with SuperTrend with params as 7 -- 3 and 7 -- 2 respectively.

    1_1522837843068_SuperTrend 7 and 3.png

    0_1522837843068_SuperTrend 7 and 2.png .


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.