Timeframe
1h
Direction
Long Only
Stoploss
-99.0%
Trailing Stop
No
ROI
0m: 10000.0%
Interface Version
3
Startup Candles
N/A
Indicators
3
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
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
"""
BTCLeaderBreakX — fork of BTCLeaderBreak: tighter Donchian-15 + faster SMA20 exit
Paradigm: breakout
Hypothesis: BTCLeaderBreak hit 0.88 on Donchian-20 breaks + SMA50 exit. The
Donchian-20 catches "established" breakouts but may miss earlier,
higher-edge moves. Tighter Donchian-15 catches breaks 25% earlier;
faster SMA20 exit closes faded breakouts before the SMA50 breach
confirms. Risk: more chop entries, tighter exit may cut winners.
This is a riskier variant testing whether earlier-and-faster
outperforms BTCLeaderBreak's slower-and-stronger configuration.
Parent: BTCLeaderBreak
Created: pending — fill in after first commit
Status: active
Uses MTF: yes
"""
from pandas import DataFrame
import talib.abstract as ta
from freqtrade.strategy import IStrategy, informative
class BTCLeaderBreakX(IStrategy):
INTERFACE_VERSION = 3
timeframe = "1h"
can_short = False
minimal_roi = {"0": 100}
stoploss = -0.99
trailing_stop = False
process_only_new_candles = True
use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False
startup_candle_count: int = 200
@informative("4h", "BTC/USDT")
def populate_indicators_btc_4h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Donchian-10 (peak — established as local optimum at r27, confirmed by r28's regression at 7)
dataframe["dc_high10"] = dataframe["high"].rolling(10).max()
dataframe["atr"] = ta.ATR(dataframe, timeperiod=14)
dataframe["atr_ma20"] = dataframe["atr"].rolling(20).mean()
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Faster local-pair exit reference: SMA20 (was 50 in parent)
dataframe["sma20"] = ta.SMA(dataframe, timeperiod=20)
dataframe["sma50"] = ta.SMA(dataframe, timeperiod=50) # kept for entry guard
dataframe["vol_ma20"] = dataframe["volume"].rolling(20).mean()
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
btc_break = (
dataframe["btc_usdt_close_4h"] > dataframe["btc_usdt_dc_high10_4h"].shift(1)
) & (
dataframe["btc_usdt_close_4h"].shift(1) <= dataframe["btc_usdt_dc_high10_4h"].shift(1)
)
dataframe.loc[
btc_break
& (dataframe["btc_usdt_atr_4h"] > dataframe["btc_usdt_atr_ma20_4h"])
& (dataframe["close"] > dataframe["sma50"]) # entry guard kept on slower SMA
& (dataframe["volume"] > dataframe["vol_ma20"] * 1.5),
"enter_long",
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Restore SMA50 exit to isolate whether it was the entry or the exit that hurt
dataframe.loc[
dataframe["close"] < dataframe["sma50"],
"exit_long",
] = 1
return dataframe