diff --git a/strategy.py b/strategy.py index ee0caf7..a33e08b 100644 --- a/strategy.py +++ b/strategy.py @@ -1,15 +1,9 @@ """ -Structure Flow Strategy v2.2b — 1H S/R 实验版 +Structure Flow Strategy v2.2c — 冷却期修复版 ============================================== 变更记录: - v2.2b (2026-06-09): 原版 — 4H级别S/R + 趋势强度 - v2.2b-1h-sr (2026-06-10): 实验版 — 将S/R从4H改为1H级别,趋势强度仍用4H - -改动: - support_alive/resistance_alive 从4H级别 → 1H级别 - support/resistance 引用 从4H → 1H - in_demand/in_supply 从4H → 1H - 趋势强度(strong_uptrend/downtrend)保持在4H + v2.2c (2026-06-11): 1H S/R 替代 4H S/R + v2.2c-coolfix (2026-06-11): 修复冷却期无限阻止下单 bug """ from datetime import datetime @@ -20,7 +14,7 @@ from freqtrade.strategy import IStrategy, IntParameter, informative from freqtrade.persistence import Trade -class StructureFlowStrategyV22c(IStrategy): +class StructureFlowStrategyV22d(IStrategy): can_short = True stoploss = -0.15 use_custom_stoploss = True @@ -160,6 +154,35 @@ class StructureFlowStrategyV22c(IStrategy): return bullish_pin, bearish_pin, bullish_engulf, bearish_engulf + # ===================== + # 工具:冷却期正确实现(修复 bug) + # ===================== + + def _apply_cooldown(self, signal: pd.Series, cooldown_bars: int) -> pd.Series: + """ + 正确应用冷却期:入场后才冷却,而非条件满足就冷却。 + + 原逻辑 bug:long_base.rolling(cooldown).max().shift(1) == 0 + - 当市场持续满足入场条件时,rolling window 里永远有 True + - 导致冷却期无限阻止下单 + + 修复逻辑:遍历 K 线,模拟"入场 -> 冷却"过程。 + - 满足条件 + 距离上次入场 > cooldown -> 允许入场 + - 入场后 cooldown 根 K 线内不再入场 + """ + n = len(signal) + result = [False] * n + last_entry = -99999 # 上次入场的 bar 索引 + + # 遍历(对 numpy array 操作,O(n) 约几毫秒) + values = signal.values # numpy array,快速访问 + for i in range(n): + if values[i] and (i - last_entry) > cooldown_bars: + result[i] = True + last_entry = i + + return pd.Series(result, index=signal.index) + # ================================================================ # 信息时间框架 — D1 宏观结构 # ================================================================ @@ -301,7 +324,7 @@ class StructureFlowStrategyV22c(IStrategy): return dataframe # ===================== - # 入场信号 + # 入场信号(修复冷却期逻辑) # ===================== def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: @@ -332,8 +355,9 @@ class StructureFlowStrategyV22c(IStrategy): & dataframe["strong_uptrend_4h"] ) - long_recent = long_base.rolling(cooldown, min_periods=1).max().shift(1) == 0 - dataframe.loc[long_base & long_recent, "enter_long"] = 1 + # ✅ 修复:正确应用冷却期(基于实际入场,而非条件满足) + long_entries = self._apply_cooldown(long_base, cooldown) + dataframe.loc[long_entries, "enter_long"] = 1 # ── 做空(使用1H S/R) ── short_stop_dist = (dataframe["resistance"] - dataframe["open"]) / dataframe["open"] @@ -347,8 +371,9 @@ class StructureFlowStrategyV22c(IStrategy): & dataframe["strong_downtrend_4h"] ) - short_recent = short_base.rolling(cooldown, min_periods=1).max().shift(1) == 0 - dataframe.loc[short_base & short_recent, "enter_short"] = 1 + # ✅ 修复:正确应用冷却期(基于实际入场,而非条件满足) + short_entries = self._apply_cooldown(short_base, cooldown) + dataframe.loc[short_entries, "enter_short"] = 1 return dataframe @@ -424,4 +449,3 @@ class StructureFlowStrategyV22c(IStrategy): }, }, } -