Freqtrade Strategy

BbandRsi

1h candlesMean reversionSpot, long only

Tested 1 Jun 2023 – 30 May 2025
Rank 11 of 27 by return

BbandRsi turned $1,000 into $1,079 (+7.9%) over 729 days, while holding Bitcoin returned +288.1% and an equal mix of the ten coins +194.8%. Its worst drawdown was 32.7%, a substantial dip to sit through. It won 64% of trades for a profit factor of 1.03.

BbandRsi account balance compared with holding Bitcoin$0$1,000$2,000$3,000$4,000JulOctJan 2024AprJulOctJan 2025AprBbandRsi $1,079BTC hold $3,880
Account balance from $1,000 (closed trades, daily). Dashed line: $1,000 held in BTC over the same days.
Total return+7.9%$1,079 final balance
Max drawdown32.7%31 Mar 2024 to 9 Apr 2025
Win rate63.7%251 wins / 143 losses
Profit factor1.03Gross wins ÷ gross losses
Trades3940.5 per day
Average trade+0.10%after fees
Average hold4d 21hwinners 3d 6h, losers 7d 16h
Annualised (CAGR)+3.9%Sharpe 0.12 · Sortino 0.12

How BbandRsi trades

BbandRsi buys oversold dips: RSI below 30 and price below the lower Bollinger Band on the 1-hour chart. It sells once RSI climbs above 70, or when the 10% take-profit is reached.

Buying weakness works well in ranging markets and poorly in steady downtrends, where RSI can stay below 30 for days. The 25% stoploss leaves a lot of room for a bad trade to grow.

Rules at a glance

Indicators
RSI 14, Bollinger Bands 20/2
Take-profit (minimal ROI)
10% from entry
Stoploss
−25%
Trailing stop
Off
Exit signal
Used

Results by month

Profit or loss in USDT for trades closed in each month.

JFMAMJJASOND2023-112+62-106+5-22+130+1552024-7+105+163-173+62+16+86-157-7+18+98-812025-11-126-24-61+66

Results by coin

PairTradesWin rateProfit (USDT)Avg. hold
BNB/USDT4973.5%+144.134d 18h
SOL/USDT3661.1%+43.934d 14h
ETH/USDT5265.4%+42.774d 13h
BTC/USDT5060.0%+39.784d 20h
ADA/USDT3969.2%+25.024d 20h
XRP/USDT4367.4%+19.205d 8h
LINK/USDT2871.4%+17.674d 4h
DOT/USDT3259.4%−16.285d 17h
AVAX/USDT3148.4%−72.785d 9h
DOGE/USDT3455.9%−164.254d 16h

Why trades closed

Exit reasonTradesWin rateProfit (USDT)
Take-profit (ROI)39100.0%+780.70
Exit signal32665.0%+574.77
Still open at end of test40.0%−17.78
Stoploss250.0%−1,258.51

The code

BbandRsi comes from the community freqtrade-strategies repository (GPL-3.0). These are the parts that decide when it trades; the full file is 64 lines.

Entry rules
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    dataframe.loc[
        (
                (dataframe['rsi'] < 30) &
                (dataframe['close'] < dataframe['bb_lowerband'])

        ),
        'enter_long'] = 1
    return dataframe
Exit rules
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    dataframe.loc[
        (
                (dataframe['rsi'] > 70)

        ),
        'exit_long'] = 1
    return dataframe
Indicators
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)

    # Bollinger bands
    bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
    dataframe['bb_lowerband'] = bollinger['lower']
    dataframe['bb_middleband'] = bollinger['mid']
    dataframe['bb_upperband'] = bollinger['upper']

    return dataframe

Reproduce this test

With freqtrade installed (see our Docker guide), download the data and run the same backtest:

freqtrade download-data --exchange binance --pairs ADA/USDT AVAX/USDT BNB/USDT BTC/USDT DOGE/USDT DOT/USDT ETH/USDT LINK/USDT SOL/USDT XRP/USDT --timeframes 1h --timerange 20230501-20250530
freqtrade backtesting --strategy BbandRsi --timeframe 1h \
  --timerange 20230601-20250530 --dry-run-wallet 1000 --stake-amount 200 --max-open-trades 5 --fee 0.001

Results can differ slightly with a different data source or freqtrade version. See how we test.