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 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 | # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement # flake8: noqa: F401 # isort: skip_file # --- Do not remove these imports --- from freqtrade.strategy import IStrategy from datetime import datetime from pandas import DataFrame import talib.abstract as ta from technical import qtpylib class ZaratustraV24(IStrategy): # Parameters INTERFACE_VERSION = 3 timeframe = '5m' can_short = True use_exit_signal = True exit_profit_only = True # ROI table: minimal_roi = { "0": 0.100, "30": 0.090, "60": 0.040, "127": 0 } # Stoploss: stoploss = -0.2 # Trailing stop: trailing_stop = True trailing_stop_positive = 0.012 trailing_stop_positive_offset = 0.080 trailing_only_offset_is_reached = True # Max Open Trades: max_open_trades = 10 @property def plot_config(self): plot_config = {} plot_config['main_plot'] = { 'EMA' : {} } plot_config['subplots'] = { 'DI': { 'DX' : { 'color': 'yellow' }, 'ADX': { 'color': 'orange' }, 'PDI': { 'color': 'green' }, 'MDI': { 'color': 'red' }, }, } return plot_config def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['EMA'] = ta.EMA(dataframe) dataframe['LRS'] = ta.LINEARREG_SLOPE(dataframe) dataframe['DX'] = ta.DX(dataframe) # ta.SMA( ta.DX(dataframe) * dataframe['volume']) / ta.SMA(dataframe['volume']) dataframe['ADX'] = ta.ADX(dataframe) # ta.SMA( ta.ADX(dataframe) * dataframe['volume']) / ta.SMA(dataframe['volume']) dataframe['PDI'] = ta.PLUS_DI(dataframe) # ta.SMA( ta.PLUS_DI(dataframe) * dataframe['volume']) / ta.SMA(dataframe['volume']) dataframe['MDI'] = ta.MINUS_DI(dataframe) # ta.SMA(ta.MINUS_DI(dataframe) * dataframe['volume']) / ta.SMA(dataframe['volume']) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ ( (qtpylib.crossed_above(dataframe['DX'], dataframe['PDI'])) & (dataframe['PDI'] > dataframe['MDI']) & (dataframe['LRS'] > dataframe['LRS'].shift(1)) ), ['enter_long', 'enter_tag'] ] = (1, 'Long DI enter') dataframe.loc[ ( (qtpylib.crossed_above(dataframe['DX'], dataframe['MDI'])) & (dataframe['MDI'] > dataframe['PDI']) & (dataframe['LRS'] < dataframe['LRS'].shift(1)) ), ['enter_short', 'enter_tag'] ] = (1, 'Short DI enter') return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ ( (qtpylib.crossed_below(dataframe['DX'], dataframe['ADX'])) | (qtpylib.crossed_below(dataframe['DX'], dataframe['PDI'])) | (dataframe['DX'] < dataframe['PDI']) ), ['exit_long', 'exit_tag'] ] = (1, 'Long DI exit') dataframe.loc[ ( (qtpylib.crossed_below(dataframe['DX'], dataframe['ADX'])) | (qtpylib.crossed_below(dataframe['DX'], dataframe['MDI'])) | (dataframe['DX'] < dataframe['MDI']) ), ['exit_short', 'exit_tag'] ] = (1, 'Short DI exit') return dataframe def leverage(self, pair: str, current_time: datetime, current_rate: float, proposed_leverage: float, max_leverage: float, side: str, **kwargs,) -> float: return 10 |
Strategy League — fixed backtest that feeds the ranking
Export report Freqtrade logsRun finished · took 369.0s
ℹ️ This strategy uses a trailing stop — freqtrade only
re-checks these once per 5m candle by default, not against the price movement within it.
For a more accurate read, re-run this backtest locally with --timeframe-detail 1m. 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=0.75) — hard to tell apart from luck
- only 20% of resampled runs were profitable
- profitable in only 0% of rolling 3-month windows
- did not beat simply holding the market
- very deep drawdown (-96%)
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 |
|---|---|---|---|---|---|---|---|---|---|
| Mar 2021 | bullish choppy high vol | 1582 | -114.99 | -0.73 | 1149 | 433 | 72.6 | -95.94 | 0h 49m |
| Feb 2021 | bullish trending high vol | 3098 | +100.47 | 0.33 | 2293 | 805 | 74.0 | -94.2 | 0h 29m |
| Jan 2021 | bullish trending high vol | 6392 | -76.01 | -0.12 | 4677 | 1715 | 73.2 | -92.96 | 0h 33m |
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 patterns · 2 thing(s) worth reviewing before trusting the numbers
| Line | Pattern | Detail | |
|---|---|---|---|
| 13 | review | missing_startup_candles | uses recursive indicators (ADX, DX, EMA, MINUS_DI) but startup_candle_count is not set (default 0). Their value at a bar depends on all bars before it, so freqtrade trims no warmup and the backtest opens with unwarmed values that can't occur live. Set it to a few times the longest period and confirm with `freqtrade recursive-analysis` |
| 70 | review | enter_tag_overwrite | enter_tag/exit_tag is written by 4 separate assignments -- they share one column and run in source order, so a row matching more than one condition keeps only the LAST tag. Per-tag statistics won't mean what they appear to |
ran by Ron · took s
Lookahead analysis
freqtrade lookahead-analysis: detects strategies peeking at future candles.