From 369a3e7b8a28ea01132d4d57ea64aa242b14a6d8 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Tue, 24 Feb 2026 00:52:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=9E=E7=9B=98=E5=BC=80?= =?UTF-8?q?=E4=BB=93=E9=A2=91=E7=B9=81=E9=97=AE=E9=A2=98=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=9C=BA=E9=97=B4=E9=9A=94/=E5=86=B7?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E4=BF=9D=E6=8A=A4/=E6=8F=90=E9=AB=98?= =?UTF-8?q?=E5=85=A5=E5=9C=BA=E6=9D=A1=E4=BB=B6=E4=B8=A5=E6=A0=BC=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- freqtrade/templates/freqaiprimer.py | 53 ++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 3e97065d..2acfe7e3 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -388,7 +388,7 @@ class FreqaiPrimer(IStrategy): stochrsi_neutral_threshold = IntParameter(20, 30, default=25, optimize=True, load=True, space='buy') volume_multiplier = DecimalParameter(1.2, 2.0, decimals=1, default=1.5, optimize=True, load=True, space='buy') bb_width_threshold = DecimalParameter(0.01, 0.03, decimals=3, default=0.02, optimize=True, load=True, space='buy') - min_condition_count = IntParameter(2, 4, default=3, optimize=True, load=True, space='buy') + min_condition_count = IntParameter(3, 5, default=4, optimize=True, load=True, space='buy') # 剧烈拉升检测参数 - 使用Hyperopt可优化参数 h1_max_candles = IntParameter(100, 300, default=200, optimize=True, load=True, space='buy') @@ -396,7 +396,7 @@ class FreqaiPrimer(IStrategy): h1_max_consecutive_candles = IntParameter(1, 4, default=2, optimize=True, load=True, space='buy') # 入场间隔控制参数(分钟) - entry_interval_minutes = IntParameter(20, 200, default=42, optimize=True, load=True, space='buy') + entry_interval_minutes = IntParameter(60, 240, default=90, optimize=True, load=True, space='buy') # EMA20斜率阈值参数(用于趋势强度过滤) ema20_slope_threshold = DecimalParameter(0.0005, 0.005, decimals=4, default=0.001, optimize=True, load=True, space='buy') @@ -1342,7 +1342,7 @@ class FreqaiPrimer(IStrategy): ) -> bool: """ 交易买入前的确认函数,用于最终决定是否执行交易 - 此处实现从API获取数据、高波动禁止入场、时间戳和RMSE检查逻辑 + 包含入场间隔控制、基础保护机制 """ self.strategy_log(f"[{pair}] confirm_trade_entry 被调用 - 价格: {rate:.8f}, 时间: {current_time}") @@ -1351,6 +1351,42 @@ class FreqaiPrimer(IStrategy): self.strategy_log(f"[{pair}] 非多头交易,跳过入场检查") return False + # ========== 基础保护1:入场间隔控制 ========== + if pair in self._last_entry_time: + last_entry = self._last_entry_time[pair] + time_since_last_entry = (current_time - last_entry).total_seconds() / 60 + interval_minutes = self.entry_interval_minutes.value + + if time_since_last_entry < interval_minutes: + self.strategy_log( + f"[{pair}] 入场间隔不足: 距离上次入场 {time_since_last_entry:.1f}分钟, " + f"需要 {interval_minutes}分钟, 拒绝入场" + ) + return False + + # ========== 基础保护2:冷启动保护 ========== + time_since_start = (current_time - self._strategy_start_time).total_seconds() + if time_since_start < 300: # 5分钟冷启动保护 + self.strategy_log(f"[{pair}] 冷启动保护中: 策略启动 {time_since_start:.0f}秒, 拒绝入场") + return False + + # ========== 基础保护3:检查当前技术指标 ========== + try: + dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) + if len(dataframe) < 10: + self.strategy_log(f"[{pair}] 数据不足,拒绝入场") + return False + + last_candle = dataframe.iloc[-1] + + # 检查RSI是否过高(避免追高) + if 'rsi' in last_candle and last_candle['rsi'] > 65: + self.strategy_log(f"[{pair}] RSI过高({last_candle['rsi']:.1f} > 65),拒绝入场") + return False + + except Exception as e: + self.strategy_log(f"[{pair}] 技术指标检查出错: {str(e)}") + # 获取虚机名字 import os virtual_host_name = os.environ.get('VIRTUAL_HOST_NAME') @@ -1434,6 +1470,9 @@ class FreqaiPrimer(IStrategy): self.strategy_log(f" - 入场信号: {values.get('&s-entry_signal')}") self.strategy_log(f" - 出场信号: {values.get('&s-exit_signal')}") + # 记录入场时间 + self._last_entry_time[pair] = current_time + return True except requests.RequestException as e: @@ -1443,8 +1482,12 @@ class FreqaiPrimer(IStrategy): self.strategy_log(f"[{pair}] 检查过程中发生错误: {str(e)}") return False else: - # 虚机名字不是kiko,跳过外部数据获取和RMSE限制,直接允许入场 - self.strategy_log(f"[{pair}] 虚机名字不是kiko,跳过外部数据获取和RMSE限制,直接允许入场") + # 虚机名字不是kiko,只使用基础保护机制 + self.strategy_log(f"[{pair}] 虚机名字不是kiko,使用基础保护机制,允许入场") + + # 记录入场时间 + self._last_entry_time[pair] = current_time + return True