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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | # BreakoutStrategyV1 - 突破策略(捕捉快速下跌/上涨) # 适用于 15 分钟周期,快速响应市场变化 import numpy as np import pandas as pd from pandas import DataFrame from datetime import datetime from typing import Optional from functools import reduce import logging from freqtrade.strategy import IStrategy, DecimalParameter, IntParameter import talib.abstract as ta logger = logging.getLogger(__name__) class BreakoutStrategyV1(IStrategy): """ 突破策略 V1 - 捕捉快速行情 核心逻辑: 1. 价格突破检测:1小时内下跌/上涨超过阈值 2. 成交量放大:当前成交量 > 均量 * 2 3. 动量确认:RSI 极端值 + MACD 方向 4. 波动率过滤:避免过度震荡 做空条件: - 1小时跌幅 > 2.5% - 成交量 > 均量 * 1.8 - RSI < 40 (超卖) - MACD 负值且下降 做多条件: - 1小时涨幅 > 2.5% - 成交量 > 均量 * 1.8 - RSI > 60 (超买) - MACD 正值且上升 风险控制: - 止损: 2% - 止盈: 4% - 最大持仓时间: 4小时 """ INTERFACE_VERSION = 3 # 可调参数 - V1.2 放宽版 breakout_threshold = DecimalParameter(1.0, 3.0, default=1.5, space="buy") # 突破阈值降低 volume_multiplier = DecimalParameter(1.2, 2.5, default=1.3, space="buy") # 成交量倍数降低到1.3 rsi_oversold = IntParameter(30, 50, default=50, space="buy") # 做空RSI: < 50 (很宽松) rsi_overbought = IntParameter(50, 70, default=55, space="buy") # 做多RSI放宽 # 时间周期 - 改用30分钟,减少噪音 timeframe = '30m' # 风险控制 - 放宽止损 minimal_roi = { "0": 0.03, # 3% 止盈 "30": 0.02, # 30分钟后 2% "60": 0.015, # 1小时后 1.5% "120": 0.01 # 2小时后 1% } stoploss = -0.025 # 2.5% 止损(放宽) # 追踪止损 trailing_stop = True trailing_stop_positive = 0.015 trailing_stop_positive_offset = 0.02 trailing_only_offset_is_reached = True startup_candle_count = 100 use_exit_signal = True exit_profit_only = False order_types = { 'entry': 'limit', # 使用限价单 'exit': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False } can_short: bool = True # 允许做空 leverage_default = 2 # 暂时禁用只做空模式,双向测试 short_only_mode = False def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """计算技术指标""" # === 基础指标 === dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) dataframe['ema_20'] = ta.EMA(dataframe['close'], timeperiod=20) dataframe['ema_50'] = ta.EMA(dataframe['close'], timeperiod=50) # === 成交量指标 === dataframe['volume_ma'] = dataframe['volume'].rolling(window=20).mean() dataframe['volume_ratio'] = dataframe['volume'] / dataframe['volume_ma'] # === 价格变化率 === # 1小时变化 (2根30分钟K线) dataframe['price_change_1h'] = dataframe['close'].pct_change(periods=2) * 100 # 30分钟变化 (1根K线) dataframe['price_change_30m'] = dataframe['close'].pct_change(periods=1) * 100 # === MACD === macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9) dataframe['macd'] = macd['macd'] dataframe['macdsignal'] = macd['macdsignal'] dataframe['macd_hist'] = macd['macd'] - macd['macdsignal'] # === 波动率 === dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) dataframe['volatility'] = dataframe['atr'] / dataframe['close'] * 100 # === ADX (趋势强度) === dataframe['adx'] = ta.ADX(dataframe, timeperiod=14) dataframe['adx_pos'] = ta.PLUS_DI(dataframe, timeperiod=14) dataframe['adx_neg'] = ta.MINUS_DI(dataframe, timeperiod=14) # === 突破信号 === # 做空突破:快速下跌 dataframe['breakout_short'] = ( (dataframe['price_change_1h'] < -self.breakout_threshold.value) | # 1小时跌幅 > 阈值 (dataframe['price_change_30m'] < -self.breakout_threshold.value * 0.7) # 或30分钟急跌 ).astype(int) # 做多突破:快速上涨 dataframe['breakout_long'] = ( (dataframe['price_change_1h'] > self.breakout_threshold.value) | # 1小时涨幅 > 阈值 (dataframe['price_change_30m'] > self.breakout_threshold.value * 0.7) # 或30分钟急涨 ).astype(int) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """做多 - 快速上涨突破""" dataframe.loc[:, 'enter_long'] = 0 # 熊市模式 - 禁用做多 if getattr(self, 'short_only_mode', False): return dataframe conditions = [ # === 突破检测 === dataframe['breakout_long'] == 1, # === 成交量确认 === dataframe['volume_ratio'] > self.volume_multiplier.value, # === 动量确认 === dataframe['rsi'] > self.rsi_overbought.value, # 动量强劲 dataframe['macd_hist'] > 0, # MACD 上升 # === 趋势确认 === dataframe['close'] > dataframe['ema_20'], # 价格在均线上方 # === 波动率过滤 === dataframe['volatility'] < 8, # 避免极端波动 ] if conditions: dataframe.loc[reduce(lambda x, y: x & y, conditions), 'enter_long'] = 1 return dataframe def populate_entry_trend_short(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """做空 - 快速下跌突破""" dataframe.loc[:, 'enter_short'] = 0 conditions = [ # === 突破检测 === dataframe['breakout_short'] == 1, # === 成交量确认 === dataframe['volume_ratio'] > self.volume_multiplier.value, # === 动量确认 === dataframe['rsi'] < self.rsi_oversold.value, # 超卖 dataframe['macd_hist'] < 0, # MACD 下降 # === 趋势确认 === dataframe['close'] < dataframe['ema_20'], # 价格在均线下方 # === 波动率过滤 === dataframe['volatility'] < 8, # 避免极端波动 ] 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: """做多平仓""" dataframe.loc[:, 'exit_long'] = 0 conditions = [ # 反转信号 (dataframe['rsi'] > 75) | # 严重超买 (dataframe['price_change_30m'] < -1.5) # 30分钟快速下跌 ] if conditions: dataframe.loc[reduce(lambda x, y: x | y, conditions), 'exit_long'] = 1 return dataframe def populate_exit_trend_short(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """做空平仓""" dataframe.loc[:, 'exit_short'] = 0 conditions = [ # 反转信号 (dataframe['rsi'] < 30) | # 严重超卖 (dataframe['price_change_30m'] > 1.5) # 30分钟快速上涨 ] if conditions: dataframe.loc[reduce(lambda x, y: x | y, conditions), 'exit_short'] = 1 return dataframe def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, current_time: datetime, entry_tag: Optional[str], side: str, **kwargs) -> bool: """入场确认 - 额外安全检查""" dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1] # 检查波动率是否过高(避免极端行情) if last_candle['volatility'] > 10: logger.info(f"波动率过高,跳过 {pair}: {last_candle['volatility']:.2f}%") return False # 检查成交量是否异常(可能是数据问题) if last_candle['volume_ratio'] > 10: logger.info(f"成交量异常,跳过 {pair}: ratio={last_candle['volume_ratio']:.2f}") return False return True def leverage(self, pair: str, current_time: datetime, current_rate: float, proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str, **kwargs) -> float: """动态杠杆 - 根据信号强度调整""" dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1] # 根据成交量强度调整杠杆 volume_strength = min(last_candle['volume_ratio'] / 3, 1.5) # 最大1.5倍 # 基础杠杆 * 强度调整 leverage = self.leverage_default * (0.8 + volume_strength * 0.4) return min(leverage, max_leverage) |
Strategy League — fixed backtest that feeds the ranking
Export report Freqtrade logsRun finished · took 62.1s
ℹ️ This strategy uses a trailing stop — freqtrade only
re-checks these once per 30m 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=1.00) — hard to tell apart from luck
- only 0% of resampled runs were profitable
- did not beat simply holding the market
- very deep drawdown (-90%)
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 |
|---|---|---|---|---|---|---|---|---|---|
| Feb 2021 | bullish trending high vol | 26 | -2.25 | -0.88 | 9 | 17 | 34.6 | -90.05 | 0h 13m |
| Jan 2021 | bullish trending high vol | 1458 | -87.65 | -0.60 | 588 | 870 | 40.3 | -88.29 | 0h 11m |
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 · 1 thing(s) worth reviewing before trusting the numbers
| Line | Pattern | Detail | |
|---|---|---|---|
| 72 | review | startup_candles_too_small | startup_candle_count is 100, but ADX(timeperiod=14) needing 12x warmup needs at least 168 candles -- so the first 68+ candles of every backtest use an indicator that hasn't warmed up. Recursive indicators (EMA/RSI/ADX/ATR) want several times their period, not exactly it |
ran by Ron · took s
Lookahead analysis
freqtrade lookahead-analysis: detects strategies peeking at future candles.