SimpleRSI_Shorts - Shorts-only variant of SimpleRSI.
Timeframe
1d
Direction
Long Only
Stoploss
-99.0%
Trailing Stop
No
ROI
0m: 50000.0%
Interface Version
3
Startup Candles
N/A
Indicators
1
freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
this is an example class, implementing a PSAR based trailing stop loss you are supposed to take the `custom_stoploss()` and `populate_indicators()` parts and adapt it to your own strategy
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these libs ---
from warnings import simplefilter
import numpy as np # noqa
import pandas as pd # noqa
from pandas import DataFrame
from functools import reduce
from typing import Dict, List
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
IStrategy, IntParameter)
from freqtrade.persistence import Trade
from datetime import datetime
# --------------------------------
import talib.abstract as ta
import warnings
warnings.filterwarnings(
'ignore', message='The objective has been evaluated at this point before.')
simplefilter(action="ignore", category=pd.errors.PerformanceWarning)
class SimpleRSI_Shorts(IStrategy):
"""
SimpleRSI_Shorts - Shorts-only variant of SimpleRSI.
Original enters long when RSI crosses above minRSI (default 80) - momentum breakout.
This shorts variant enters short when RSI crosses below (100 - minRSI) = 20 - momentum breakdown.
Same ROI, stoploss, and leverage as longs with only trading logic inverted.
"""
can_short: bool = True
INTERFACE_VERSION = 3
rsiWindow = IntParameter(7, 21, default=14, space="buy", optimize=True)
# Inverted: 100 - 80 = 20 (enter short when RSI drops into oversold)
minRSI = DecimalParameter(1, 99, decimals=0, default=20, space="buy", optimize=True)
use_custom_stoploss: bool = True
process_only_new_candles: bool = True
position_adjustment_enable: bool = False
# Same as longs
minimal_roi = {
"0": 500.0
}
stoploss = -0.99
trailing_stop = False
timeframe = '1d'
startup_candle_count: int = 50
# Max short trades
max_short_trades = 4
order_types = {
'entry': 'market',
'exit': 'market',
'stoploss': 'market',
'stoploss_on_exchange': False
}
order_time_in_force = {
'entry': 'gtc',
'exit': 'gtc'
}
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float:
# Emergency backstop: prevent liquidation at 3x leverage
if current_profit <= -0.20:
return -0.21
return 1
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time: datetime, entry_tag: str,
side: str, **kwargs) -> bool:
# Only allow shorts
if side == "long":
return False
# Enforce max short positions
short_count = sum(1 for t in Trade.get_trades_proxy(is_open=True) if t.is_short)
if short_count >= self.max_short_trades:
return False
return True
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['RSI'] = ta.RSI(dataframe, timeperiod=int(self.rsiWindow.value))
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Inverted: enter short when RSI drops below threshold from above
conditions = []
conditions.append(dataframe['RSI'] <= self.minRSI.value)
conditions.append(dataframe['RSI'].shift(1) > self.minRSI.value)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'enter_short'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
conditions.append(dataframe['RSI'] <= -5) # never exits
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'exit_short'] = 1
return dataframe
def leverage(self, pair: str, current_time: datetime, current_rate: float,
proposed_leverage: float, max_leverage: float, entry_tag: str,
side: str, **kwargs) -> float:
return 3.0
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration": 10080
}
]