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

RSI: moving thresholds signals

  • Hi everyone,

    I am fairly new to Python and Backtrader. I am testing out a simple RSI cross over strategy. Instead of having two hard-plugged thresholds for buy and sell signals, I’d like those thresholds to be moving across time series. For example, a buy signal would be triggered when current RSI is equal to the 10% minimum / lowest RSI over the last 24 hours, conversely a sell signal would be triggered when current RSI reaches the 90% highest RSI over the same period of time.

    As you can see on the code below, I haven’t been successful figuring out what to code in order to get those moving thresholds (10% lowest and 90% highest thresholds) that would trigger a trade signal.

    Any assistance or feedback would be greatly appreciated.

    class TestStrategy(bt.Strategy):

    params = (
        ('period',195),('threshold_Buy', 50),('threshold_Sell', 56),
        ) #tresholds here are hard plugged, the intent would be to have them as a percentage (for example 10% buy signal and 90% sell signal)
    def log(self, txt, dt=None):
        dt = dt or self.datas[0]
        print('%s, %s' % (dt.isoformat(), txt))
    def __init__(self):
        self.dataclose = self.datas[0].close
        self.order = None
        self.buyprice = None
        self.buycomm = None
        self.rsi = bt.indicators.RelativeStrengthIndex(self.datas[0], period=self.params.period) # simple RSI, period here has already been optimized for this particular stock
        self.smaRSI = bt.indicators.SimpleMovingAverage(self.rsi, period=288) #period here represents 24 hours cut into 5 minutes timeframe periods
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
        if order.status in [order.Completed]:
            if order.isbuy():
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
            self.bar_executed = len(self)
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            '''self.log('Order Canceled/Margin/Rejected')'''
        self.order = None
    def notify_trade(self, trade):
        if not trade.isclosed:
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
    def next(self):
        if self.order:
        if not self.position:
            print('rsi', self.rsi[0], 'smaRSI', self.smaRSI[0])
            if self.rsi[0] < self.params.threshold_Buy:
                self.order =
            if self.rsi[0] > self.params.threshold_Sell:
                self.order = self.sell()

  • I would start from this script (didn't test):

    class TestStrategy(bt.Strategy):
        params = (('period',195), ('threshold_Buy', 10), ('threshold_Sell', 90),)
        def __init__(self):
            self.rsi = bt.indicators.RelativeStrengthIndex(period=self.p.period)
            self.rsiHHV = bt.indicators.Highest(self.rsi, period=288)
            self.rsiLLV = bt.indicators.Lowest(self.rsi, period=288)
            self.buysig = (self.rsi >= self.p.threshold_Buy * self.rsiHHV)
            self.sellsig = (self.rsi <= self.p.threshold_Sell * self.rsiLLV)

  • Great thanks, exactly what I needed.

    I just changed the buy / sell signals as per the below:

            if self.rsi[0] <= (np.percentile([self.rsiLLV[0], self.rsiHHV[0]], self.p.threshold_Buy)):
                self.order =
            if self.rsi[0] >= (np.percentile([self.rsiLLV[0], self.rsiHHV[0]], self.p.threshold_Sell)):
                self.order = self.sell()

    Many thanks again

Log in to reply