For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
Multiple filled orders despite "if not position" condition
-
Hello, trying to backtest a simple RSI strategy.
It sends a buy_bracket if current position==0 and rsi indicator crossup oversold thersold and close the position when the rsi crossdown the opposite threshold.
The opposite for selling; always only if current position==0.What I cannot understand it is that sometimes multiple unwanted entries happen. I added some "check print" ad notify_order status in order to better understand but I gave up.
Here the logic:
import backtrader as bt import datetime class rsi_strategy(bt.Strategy): params = ( ('backtest', False), ('printLog', True), ('rsi_period', 19), ('rsi_overSold', 21), ('rsi_overBought', 77), ('stopLoss_perc', 7), ('takeProfit_perc', 20) ) def __init__(self): # self.live_bars = False self.rsi_ind = bt.indicators.RSI(self.data.close, period=self.p.rsi_period, plot=True, plotname='RSI', subplot=True) # Buy Signals self.CrossedOS = bt.indicators.CrossUp(self.rsi_ind, self.p.rsi_overSold, plotname='x ↑ OS') # Sell Signals self.CrossedOB = bt.indicators.CrossDown(self.rsi_ind, self.p.rsi_overBought, plotname='x ↓ OB') def next(self): self.closePrice = self.data.close[0] self.Bar_time = self.data.datetime.time() self.Bar_date = self.data.datetime.date() self.order_size = int((self.broker.cash / self.closePrice / 4)) self.highside_offset = round(self.closePrice * self.p.takeProfit_perc / 100, 2) self.lowside_offset = round(self.closePrice * self.p.stopLoss_perc / 100, 2) self.current_position = self.getposition().size print(len(self)) print('BarDataTime >>', self.Bar_date, self.Bar_time, ' / Equity >>', int(self.broker.getvalue()), ' / Current Size >>', self.current_position) print('close >>', self.closePrice, ' / RSI >>', self.rsi_ind[0].__round__(1)) print('-------------') # # # If flat and rsi Cross-up Over-Sold level then buy_bracket if self.current_position == 0: if self.broker.getvalue() > 9500 and self.CrossedOS: print('Buy Condition met, current position size>>', self.current_position) # control string self.buy_bracket(size=self.order_size, stopprice=self.closePrice - self.lowside_offset, limitprice=self.closePrice + self.highside_offset, exectype=bt.Order.Limit) elif self.current_position < 0 and self.CrossedOS: print('Close-Sell Condition met, current position size>>', self.current_position) # control string self.close() # If flat and rsi Cross-Down Over-Bought level then buy_bracket if self.current_position == 0: if self.broker.getvalue() > 9500 and self.CrossedOB: print('Sell Condition met, current position size>>', self.current_position) # control string self.sell_bracket(size=self.order_size, stopprice=self.closePrice + self.lowside_offset, limitprice=self.closePrice - self.highside_offset, exectype=bt.Order.Limit) elif self.current_position > 0 and self.CrossedOB: print('Close-Buy Condition met, current position size>>', self.current_position) # control string self.close() def notify_order(self, order): if order.status in [order.Submitted]: print('Order Submitted') if order.status in [order.Accepted]: print('Order Accepted') if order.status in [order.Completed]: print('Order Completed')
the plot:
and some of the terminal prints for "standard behaviour:
close >> 1.334 / RSI >> 20.5 ------------- 62879 BarDataTime >> 2022-06-13 16:24:00 / Equity >> 10991 / Current Size >> 0 close >> 1.33425 / RSI >> 21.3 ------------- Buy Condition met, current position size>> 0 Order Submitted Order Submitted Order Submitted Order Accepted Order Accepted Order Accepted Order Completed 62880 BarDataTime >> 2022-06-13 16:27:00 / Equity >> 10987 / Current Size >> 2059 close >> 1.3325 / RSI >> 19.8 ------------- 62881 BarDataTime >> 2022-06-13 16:30:00 / Equity >> 10992 / Current Size >> 2059 close >> 1.33475 / RSI >> 26.9 ------------- 62882 BarDataTime >> 2022-06-13 16:33:00 / Equity >> 10998 / Current Size >> 2059
and of the strange behaviour:
62921 BarDataTime >> 2022-06-14 10:00:00 / Equity >> 10986 / Current Size >> 2059 close >> 1.332 / RSI >> 41.4 ------------- 62922 BarDataTime >> 2022-06-14 10:03:00 / Equity >> 10979 / Current Size >> 2059 close >> 1.32875 / RSI >> 38.2 ------------- Order Completed 62923 BarDataTime >> 2022-06-14 10:06:00 / Equity >> 10971 / Current Size >> 3684 close >> 1.3255 / RSI >> 35.3 ------------- 62924 BarDataTime >> 2022-06-14 10:09:00 / Equity >> 10971 / Current Size >> 3684 close >> 1.3255 / RSI >> 35.3 ------------- 62925 BarDataTime >> 2022-06-14 10:12:00 / Equity >> 10966 / Current Size >> 3684
I really hope someone has already faced the problem and be kind to give explanation.
Thanks in advance
Gianluca