From 171ce86feaaf570dbd3476ef8035d8f570c9f955 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Tue, 23 Dec 2025 13:42:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=87=BA=E5=9C=BA=E7=BD=AE=E4=BF=A1=E5=BA=A6+?= =?UTF-8?q?=E5=85=A5=E5=9C=BA=E7=BD=AE=E4=BF=A1=E5=BA=A6+log+4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- freqtrade/templates/freqaiprimer.py | 46 ++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 4efe23d8..7348fbba 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -838,17 +838,47 @@ class FreqaiPrimer(IStrategy): exit_prob = 1.0 if str(val).lower() in ['exit', 'sell', '1'] else 0.0 if exit_prob is not None: - # ML 审核官逻辑:只有当 exit_signal 概率足够高时才允许出场 - # 使用 hyperopt 参数,默认 0.65 - exit_threshold = self.ml_exit_signal_threshold.value - if exit_prob < exit_threshold: - logger.info(f"[{pair}] ML 审核官拒绝出场: exit_signal 概率 {exit_prob:.2f} < 阈值 {exit_threshold:.2f}(上涨概率高,继续持仓), 出场原因: {exit_reason}") + # ML 审核官逻辑:使用动态阈值,仅对“盈利单 + 策略型 exit_signal”做轻量终审 + base_threshold = self.ml_exit_signal_threshold.value + + # 从 kwargs 获取当前利润,freqtrade 会传入 current_profit + current_profit = float(kwargs.get('current_profit', 0.0)) + + # 若为亏损单(current_profit <= 0),不启用 ML 审核官,直接允许出场 + if current_profit <= 0: + logger.info(f"[{pair}] ML 审核官跳过出场审核: 当前利润 {current_profit:.4f} <= 0, 允许出场, 出场原因: {exit_reason}") + return True + + # 计算持仓时长(分钟) + try: + trade_age_minutes = max(0.0, (current_time - trade.open_date_utc).total_seconds() / 60.0) + except Exception: + trade_age_minutes = 0.0 + + # 基于持仓时长的阈值衰减:持仓越久,阈值越低,越容易出场 + age_factor = min(trade_age_minutes / (24 * 60.0), 1.0) # 0~1,对应 0~24 小时+ + dynamic_threshold = base_threshold * (1.0 - 0.3 * age_factor) + + # 小利润单(<=2%)再额外放宽 20% + if current_profit <= 0.02: + dynamic_threshold *= 0.8 + + # 设定下限,避免阈值过低 + dynamic_threshold = max(0.05, dynamic_threshold) + + if exit_prob < dynamic_threshold: + logger.info( + f"[{pair}] ML 审核官拒绝出场: exit_signal 概率 {exit_prob:.2f} < 动态阈值 {dynamic_threshold:.2f}" + f"(base={base_threshold:.2f}, trade_age_min={trade_age_minutes:.1f}, current_profit={current_profit:.4f}),继续持仓, 出场原因: {exit_reason}" + ) allow_exit = False else: - logger.info(f"[{pair}] ML 审核官允许出场: exit_signal 概率 {exit_prob:.2f} >= 阈值 {exit_threshold:.2f}, 出场原因: {exit_reason}") + logger.info( + f"[{pair}] ML 审核官允许出场: exit_signal 概率 {exit_prob:.2f} >= 动态阈值 {dynamic_threshold:.2f}" + f"(base={base_threshold:.2f}, trade_age_min={trade_age_minutes:.1f}, current_profit={current_profit:.4f}),出场原因: {exit_reason}" + ) except Exception as e: - logger.warning(f"[{pair}] ML 审核官出场检查失败,允许出场: {e}") - + logger.warning(f"[{pair}] ML 审核官出场检查失败,允许出场: {e}") return allow_exit def custom_stoploss(self, pair: str, trade: 'Trade', current_time, current_rate: float,