20-bar breakout strategy with 3-bar trailing stoploss. Only one trade is allowed at a time (handled by Freqtrade via max_open_trades = 1).
Timeframe
1h
Direction
Long Only
Stoploss
-100.0%
Trailing Stop
No
ROI
0m: 5.0%
Interface Version
N/A
Startup Candles
N/A
Indicators
0
freqtrade/freqtrade-strategies
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
''' new strat '''
# from freqtrade.strategy import IStrategy
# from pandas import DataFrame
# import numpy as np
# class NewStrategy(IStrategy):
# timeframe = '1h'
# stoploss = -1
# minimal_roi = {"0": 0.05}
# def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['high_20'] = dataframe['high'].rolling(window=20).max()
# dataframe['low_20'] = dataframe['low'].rolling(window=20).min()
# dataframe['low_3'] = dataframe['low'].rolling(window=3).min()
# return dataframe.dropna().copy()
# def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['buy'] = (dataframe['close'] > dataframe['high_20']).astype('bool')
# return dataframe
# def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['exit_long'] = False
# dataframe['exit_short'] = False
# return dataframe
# def custom_stoploss(self, pair: str, trade, current_time, current_rate, current_profit, **kwargs) -> float:
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# idx = dataframe.index.searchsorted(trade.open_date_utc)
# if idx >= len(dataframe) or idx < 0:
# return 1.0 # Trigger exit if index is invalid
# trailing_min = dataframe['low_3'].iloc[idx:].min()
# if current_rate <= trailing_min:
# stoploss_rel = (trailing_min - trade.open_rate) / trade.open_rate
# return max(0.01, abs(stoploss_rel)) # Ensure within valid bounds
# return 1.0
from freqtrade.strategy import IStrategy
from pandas import DataFrame
import numpy as np
from freqtrade.strategy import IStrategy
from pandas import DataFrame
class NewStrategy(IStrategy):
"""
20-bar breakout strategy with 3-bar trailing stoploss.
Only one trade is allowed at a time (handled by Freqtrade via max_open_trades = 1).
"""
# === Configuration ===
timeframe = '30m' # Use '1h' for testing, '30m' for actual outputs
stoploss = -1 # Disable default stoploss; custom stoploss is used
minimal_roi = {"0": 0.5} # Placeholder ROI
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Calculate breakout and trailing indicators
dataframe['high_20'] = dataframe['high'].rolling(window=20).max()
dataframe['low_20'] = dataframe['low'].rolling(window=20).min()
dataframe['low_3'] = dataframe['low'].rolling(window=3).min()
dataframe.dropna(inplace=True)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Entry condition: Close breaks out above *previous* 20-bar high
dataframe['buy'] = (
dataframe['close'] > dataframe['high_20'].shift(1)
).astype('bool')
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Exit logic is handled via custom stoploss
dataframe['exit_long'] = False
dataframe['exit_short'] = False
return dataframe
def custom_stoploss(self, pair: str, trade, current_time, current_rate, current_profit, **kwargs) -> float:
# Use the 3-bar low since the trade was opened as a trailing stop
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# Find index where trade was opened
idx = dataframe.index.searchsorted(trade.open_date_utc)
if idx >= len(dataframe) or idx < 0:
return 1.0 # Exit immediately if data is invalid
# Get trailing minimum 3-bar low after trade entry
trailing_min = dataframe['low_3'].iloc[idx:].min()
# If current price drops below that trailing min, exit the trade
if current_rate <= trailing_min:
stoploss_rel = (trailing_min - trade.open_rate) / trade.open_rate
return max(0.01, abs(stoploss_rel)) # Return positive stop between 0 and 1
return 1.0 # Otherwise, keep trade open