15 related strategies (⧉ identical code, ≈ similar name)
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 | """Multi-Indicator Confirmation Strategy. Developed 2023, updated 2025.""" import logging import pandas_ta as ta from pandas import DataFrame from freqtrade.strategy import IntParameter, IStrategy logger = logging.getLogger(__name__) class CombinedSignalStrategy(IStrategy): INTERFACE_VERSION = 3 timeframe = "4h" can_short = False startup_candle_count: int = 100 minimal_roi = {"0": 0.10, "120": 0.06, "240": 0.03} stoploss = -0.06 trailing_stop = True trailing_stop_positive = 0.02 trailing_stop_positive_offset = 0.04 trailing_only_offset_is_reached = True rsi_threshold = IntParameter(25, 45, default=35, space="buy", optimize=True) min_signals = IntParameter(2, 5, default=3, space="buy", optimize=True) ema_period = IntParameter(40, 100, default=50, space="buy", optimize=True) def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe["rsi"] = ta.rsi(dataframe["close"], length=14) macd = ta.macd(dataframe["close"], fast=12, slow=26, signal=9) dataframe["macd"] = macd["MACD_12_26_9"] dataframe["macd_signal_line"] = macd["MACDs_12_26_9"] dataframe["macd_hist"] = macd["MACDh_12_26_9"] dataframe["ema_trend"] = ta.ema(dataframe["close"], length=self.ema_period.value) bb = ta.bbands(dataframe["close"], length=20, std=2.0) dataframe["bb_lower"] = bb["BBL_20_2.0"] dataframe["bb_upper"] = bb["BBU_20_2.0"] srsi = ta.stochrsi(dataframe["close"], length=14) dataframe["stochrsi_k"] = srsi["STOCHRSIk_14_14_3_3"] dataframe["stochrsi_d"] = srsi["STOCHRSId_14_14_3_3"] dataframe["volume_sma"] = dataframe["volume"].rolling(window=20).mean() dataframe["s_rsi"] = (dataframe["rsi"] < self.rsi_threshold.value).astype(int) dataframe["s_macd"] = ( (dataframe["macd"] > dataframe["macd_signal_line"]) & (dataframe["macd_hist"] > 0) ).astype(int) dataframe["s_ema"] = (dataframe["close"] > dataframe["ema_trend"]).astype(int) dataframe["s_stochrsi"] = ( (dataframe["stochrsi_k"] > dataframe["stochrsi_d"]) & (dataframe["stochrsi_k"] < 50) ).astype(int) dataframe["s_volume"] = (dataframe["volume"] > dataframe["volume_sma"]).astype(int) dataframe["signal_count"] = ( dataframe["s_rsi"] + dataframe["s_macd"] + dataframe["s_ema"] + dataframe["s_stochrsi"] + dataframe["s_volume"] ) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[dataframe["signal_count"] >= self.min_signals.value, "enter_long"] = 1 return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[dataframe["signal_count"] <= 1, "exit_long"] = 1 return dataframe |
Strategy League — fixed backtest that feeds the ranking
Export report Freqtrade logsRun finished · took 26.1s
ℹ️ This strategy uses a trailing stop — freqtrade only
re-checks these once per 4h candle by default, not against the price movement within it.
For a more accurate read, re-run this backtest locally with --timeframe-detail 1m
(or 5m — freqtrade's own docs use 5m detail for an hourly strategy as a lighter
alternative). Freqle doesn't do this for every check here: multiplying every
League/sweep backtest by a finer detail timeframe is more compute than the sandbox can sustain
across every indexed strategy. why this matters →
- profit isn't statistically significant (p=1.00) — hard to tell apart from luck
- only 0% of resampled runs were profitable
- profitable in only 29% of rolling 3-month windows
- did not beat simply holding the market
- very deep drawdown (-93%)
Resampling the trade sequence 2,000× shows the spread of results this edge could plausibly produce — separating a dependable strategy from one that got lucky once.
Loading charts…
Monthly breakdown
| Month | Regime | Trades | Profit % | Avg % | Win | Loss | Win % | DD % | Avg dur |
|---|---|---|---|---|---|---|---|---|---|
| Sep 2021 | bearish trending high vol | 71 | -8.08 | -1.14 | 36 | 35 | 50.7 | -93.24 | 4h 44m |
| Aug 2021 | bullish trending high vol | 120 | -2.60 | -0.22 | 62 | 58 | 51.7 | -88.73 | 7h 30m |
| Jul 2021 | bearish trending high vol | 72 | +0.88 | 0.12 | 43 | 29 | 59.7 | -88.68 | 9h 07m |
| Jun 2021 | bearish trending high vol | 250 | -36.78 | -1.47 | 120 | 130 | 48.0 | -87.64 | 4h 55m |
| May 2021 | bearish trending high vol | 584 | -44.75 | -0.77 | 299 | 285 | 51.2 | -69.0 | 3h 27m |
| Apr 2021 | bearish choppy high vol | 705 | -13.29 | -0.19 | 408 | 297 | 57.9 | -35.13 | 5h 27m |
| Mar 2021 | bullish choppy high vol | 544 | -4.22 | -0.08 | 313 | 231 | 57.5 | -28.5 | 8h 00m |
| Feb 2021 | bullish trending high vol | 726 | +31.88 | 0.44 | 468 | 258 | 64.5 | -26.68 | 3h 58m |
| Jan 2021 | bullish trending high vol | 938 | -13.39 | -0.14 | 547 | 391 | 58.3 | -26.45 | 3h 22m |
Trade charts — best 2 and worst 2 performing pairs (full OHLC candles are expensive to render for every pair)
Backtests — over a market period
Backtest this strategy over a chosen crypto-cycle period. These don't affect the League ranking, and need that period's candle data downloaded.
Log in or sign up to run backtests.
| Period | Range | Total % | Win % | Max DD | Trades | |
|---|---|---|---|---|---|---|
| 2020 · DeFi Summer & Pre-Halving Rally | 20200101-20210101 | not run | ||||
| 2021 · Institutional Bull Market | 20210101-20220101 | not run | ||||
| 2022 · Post-Bull Crash & Macro Tightening | 20220101-20230101 | not run | ||||
| 2023–2024 · Recovery & ETF Anticipation | 20230101-20250101 | not run | ||||
| 2025–2026 · Current Cycle | 20250101-20260101 | not run | ||||
Walk forward
Out-of-sample backtest on recent data · 33 pairs · 20260101-20260701.
Backtest trust check
no lookahead-bias patterns detected
ran by Ron · took s
Lookahead analysis
freqtrade lookahead-analysis: detects strategies peeking at future candles.