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.
.