💬 Forum

RsiquiV3

🏆 League #1897 / 1937

remiotore/ccxt-freqtrade/my-strategies/RsiquiV3.py · ★3 · ⑂2 · first seen 2026-07-16 · repo updated 2026-01-11 · ⬇ 1 download

Basics mode: futures timeframe: 5m interface version: 3
Settings stoploss: -0.05 has minimal roi dca hyperopt hyperopt params: 4
Indicators ATR MACD RSI SMA talib
Concepts dca
15 related strategies ( identical code, similar name)

Each tile is a different kind of check — from an instant code lint to full sandboxed backtests and forward tests on recent data. Not sure what a check actually proves? See the FAQ →

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import numpy
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from pandas import DataFrame
from datetime import datetime
from typing import Optional, Tuple, Union
from freqtrade.persistence import Trade
from freqtrade.strategy.interface import IStrategy
from freqtrade.strategy import (IStrategy, DecimalParameter, IntParameter, CategoricalParameter, BooleanParameter)


class RsiquiV3(IStrategy):
    INTERFACE_VERSION = 3

    can_short = True
    timeframe = '5m'
    stoploss = -0.05
    trailing_stop = False
    max_open_trades = 10

    minimal_roi = {
      '0': 0.21000000000000002,
      '10': 0.042,
      '70': 0.028,
      '152': 0
    }

    rsi_entry_long  = IntParameter(0,  50,  default=50, space='buy',  optimize=True)
    rsi_entry_short = IntParameter(50, 100, default=50, space='buy',  optimize=True)
    rsi_exit_long   = IntParameter(50, 100, default=95, space='sell', optimize=True)
    rsi_exit_short  = IntParameter(0,  50,  default=43, space='sell', optimize=True)

    @property
    def plot_config(self):
        plot_config = {}

        plot_config['main_plot'] = {
        }
        plot_config['subplots'] = {
            'Misc': {
                'rsi': {},
                'rsi_gra' : {},
            },
        }

        return plot_config

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        dataframe['rsi_gra'] = numpy.gradient(dataframe['rsi'], 60)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['rsi'] < self.rsi_entry_long.value) &
                qtpylib.crossed_above(dataframe['rsi_gra'], 0)
            ),
        'enter_long'] = 1

        dataframe.loc[
            (
                (dataframe['rsi'] > self.rsi_entry_short.value) &
                qtpylib.crossed_below(dataframe['rsi_gra'], 0)
            ),
        'enter_short'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['rsi'] > self.rsi_exit_long.value) &
                qtpylib.crossed_below(dataframe['rsi_gra'], 0)
            ),
        'exit_long'] = 1

        dataframe.loc[
            (
                (dataframe['rsi'] < self.rsi_exit_short.value) &
                qtpylib.crossed_above(dataframe['rsi_gra'], 0)
            ),
        'exit_short'] = 1

        return dataframe

    def adjust_trade_position(self, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, min_stake: Optional[float], max_stake: float, current_entry_rate: float, current_exit_rate: float, current_entry_profit: float, current_exit_profit: float, **kwargs) -> Optional[float]:
        filled_entries = trade.select_filled_orders(trade.entry_side)
        count_of_entries = trade.nr_of_successful_entries
        
        if current_profit > 0.25 and trade.nr_of_successful_exits == 0:
            return -(trade.stake_amount / 4)
        if current_profit > 0.40 and trade.nr_of_successful_exits == 1:
            return -(trade.stake_amount / 3)
        
        if (current_profit > -0.15 and count_of_entries == 1) or \
        (current_profit > -0.3 and count_of_entries == 2) or \
        (current_profit > -0.6 and count_of_entries == 3):
            return None
        
        try:
            stake_amount = filled_entries[0].cost if filled_entries else None
            return stake_amount
        except Exception as exception:
            return None


    def leverage(self, pair: str, current_time: datetime, current_rate: float, proposed_leverage: float, max_leverage: float, side: str, **kwargs) -> float:
        window_size = 50
        base_leverage = 100

        dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
        historical_close_prices = dataframe["close"].tail(window_size)
        historical_high_prices = dataframe["high"].tail(window_size)
        historical_low_prices = dataframe["low"].tail(window_size)

        rsi_values = ta.RSI(historical_close_prices, timeperiod=14)
        atr_values = ta.ATR(historical_high_prices, historical_low_prices, historical_close_prices, timeperiod=14)
        macd_line, signal_line, _ = ta.MACD(historical_close_prices, fastperiod=12, slowperiod=26, signalperiod=9)
        sma_values = ta.SMA(historical_close_prices, timeperiod=20)

        current_rsi = rsi_values[-1] if len(rsi_values) > 0 else 50.0
        current_atr = atr_values[-1] if len(atr_values) > 0 else 0.0
        current_macd = (macd_line[-1] - signal_line[-1]) if len(macd_line) > 0 and len(signal_line) > 0 else 0.0
        current_sma = sma_values[-1] if len(sma_values) > 0 else 0.0

        dynamic_rsi_low = numpy.nanmin(rsi_values) if len(rsi_values) > 0 and not numpy.isnan(numpy.nanmin(rsi_values)) else 30.0
        dynamic_rsi_high = numpy.nanmax(rsi_values) if len(rsi_values) > 0 and not numpy.isnan(numpy.nanmax(rsi_values)) else 70.0

        leverage_factors = {
            'long': {'increase': 1.5, 'decrease': 0.5},
            'short': {'increase': 1.5, 'decrease': 0.5},
        }

        if side == "long":
            base_leverage = base_leverage * leverage_factors['long']['increase'] if current_rsi < dynamic_rsi_low else base_leverage
            base_leverage = base_leverage * leverage_factors['long']['decrease'] if current_rsi > dynamic_rsi_high else base_leverage
            base_leverage = base_leverage * leverage_factors['long']['increase'] if current_macd > 0 else base_leverage
            base_leverage = base_leverage * leverage_factors['long']['decrease'] if current_rate < current_sma else base_leverage
        elif side == "short":
            base_leverage = base_leverage * leverage_factors['short']['increase'] if current_rsi > dynamic_rsi_high else base_leverage 
            base_leverage = base_leverage * leverage_factors['short']['decrease'] if current_rsi < dynamic_rsi_low else base_leverage
            base_leverage = base_leverage * leverage_factors['short']['increase'] if current_macd < 0 else base_leverage
            base_leverage = base_leverage * leverage_factors['short']['decrease'] if current_rate > current_sma else base_leverage

        adjusted_leverage = max(min(base_leverage, max_leverage), 1.0)

        return adjusted_leverage