StopLoss
-
Hi All,
I am trying to code a simple trailing stop loss strategy, but I just cant seem to get the hang of it after reading most of the blog posts on the topic and the docs. Feels like a silly thing to miss but maybe somebody can help. Appreciate the assistance.
'''
class CustomRsi(bt.Indicator):lines = ('signal', 'buysig', 'sellsig', ) params = (('period', 15), ('upperband', 80), ('lowerband', 33), ) def __init__(self): self.lines.signal = bt.indicators.RSI_SMA(period=self.p.period) self.lines.buysig = bt.ind.CrossUp(self.lines.signal, self.p.lowerband) self.lines.sellsig = bt.ind.CrossDown(self.signal, self.p.upperband)
class StopTrading(bt.Strategy):
params = ( ('lowerband', 30), ('upperband', 70), ) def print_signal(self): self.log("open {:.2f}\tclose {:.2f} \thigh {:.2f} rsi {:.2f} atr {:.2f}" .format(self.data.open[0], self.data.close[0], self.data.high[0], self.rsi[0], self.atr[0] ) ) def log(self, txt, dt=None): dt = dt or self.datas[0].datetime.date(0) print(dt.isoformat(), txt) def __init__(self): self.dataclose = self.data.close self.atr = bt.ind.ATR() self.rsi = bt.ind.RSI_SMA(period=15) self.crsi = CustomRsi() # create instance crsi self.buy_signal = self.crsi.buysig # access attributes of instance created self.sell_signal = self.crsi.sellsig # access attributes of instance created 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(f'Buy executed for long position {order.executed.price}') elif order.issell(): self.log(f'Close executed for long position {order.executed.price}') self.order = None def notify_trade(self, trade): if trade.isopen: return else: # Trade is closed, log profit / loss, barlen: amount of bars trade was open self.log(f'Profit {trade.pnl} Trade Length: {trade.barlen}') def next(self): self.print_signal() if self.order: return if not self.position: if self.buy_signal: self.log('Going long@{:.2f}'.format(self.dataclose[0])) self.order=self.buy() elif self.position: self.order=self.sell(exectype=bt.Order.StopTrail, trailamount=300)
'''
-
@gerry 
-
@gerry Did you catch this article?
-
@run-out I have, thanks. I am getting confused between this article and these two, and how to properly use them:
https://www.backtrader.com/blog/posts/2017-03-22-stoptrail/stoptrail/https://www.backtrader.com/docu/order-creation-execution/bracket/bracket/
Is it necessary to use the stoporder in the notify class or is it actually possible to do it under the next method?
-
@gerry You can do it both ways. Using notify_order you are setting up the stop trail after being notified of the first order completing. If you use Bracket it does that job for you.
-
@run-out Thank you very much for the reply, appreciate the help. On the bracket order, I tried using the below code, but there seems to be an error, where am I going wrong?
'''
class CustomRsi(bt.Indicator):lines = ('signal', 'buysig', 'sellsig', ) params = (('period', 15), ('upperband', 80), ('lowerband', 33), ) def __init__(self): self.lines.signal = bt.indicators.RSI_SMA(period=self.p.period) self.lines.buysig = bt.ind.CrossUp(self.lines.signal, self.p.lowerband) self.lines.sellsig = bt.ind.CrossDown(self.signal, self.p.upperband)
class StopTrading(bt.Strategy):
params = ( ('lowerband', 30), ('upperband', 70), ) def print_signal(self): self.log("open {:.2f}\tclose {:.2f} \thigh {:.2f} rsi {:.2f} atr {:.2f}" .format(self.data.open[0], self.data.close[0], self.data.high[0], self.rsi[0], self.atr[0] ) ) def log(self, txt, dt=None): dt = dt or self.datas[0].datetime.date(0) print(dt.isoformat(), txt) def __init__(self): self.dataclose = self.data.close self.atr = bt.ind.ATR() self.rsi = bt.ind.RSI_SMA(period=15) self.crsi = CustomRsi() # create instance crsi self.buy_signal = self.crsi.buysig # access attributes of instance created self.sell_signal = self.crsi.sellsig # access attributes of instance created 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(f'Buy executed for long position {order.executed.price}') elif order.issell(): self.log(f'Close executed for long position {order.executed.price}') self.order = None def notify_trade(self, trade): if trade.isopen: return else: # Trade is closed, log profit / loss, barlen: amount of bars trade was open self.log(f'Profit {trade.pnl} Trade Length: {trade.barlen}') def next(self): self.print_signal() if self.order: return if not self.position: if self.buy_signal: self.order=self.buy_bracket(exectype=bt.Order.StopTrail, trailamount=300) self.log('Going long@{:.2f}, stoptrail {:.2f}'.format(self.dataclose[0], bt.Order.StopTrail))
'''