From 0826cf04690a4b81d267e5d94ee4513cdebb7745 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Tue, 23 Dec 2025 21:27:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A2=E5=8A=A8=E7=8E=87=20AI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- freqtrade/templates/freqaiprimer.py | 69 +++++++++++++++-------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 704aca92..b43af298 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -355,18 +355,20 @@ class FreqaiPrimer(IStrategy): 0, ) - # 新增:持仓时长预测标签 - # 计算到达最高点需要多少根K线(未来20根内的最高价位置) - max_lookahead = 20 # 预测未来20根K线(60分钟) + # 新增:未来波动率预测标签(极端化方案) + # 计算当前波动率(过10根K线的收盘价波动) + current_volatility = dataframe["close"].pct_change().rolling(window=10, min_periods=5).std() - # 找到未来20根K线内的最高价 - future_high_20 = dataframe["high"].rolling(window=max_lookahead, min_periods=1).max().shift(-max_lookahead + 1) + # 计算未来10根K线的波动率(向未来移动) + future_pct_change = dataframe["close"].pct_change().shift(-1) # 未来的收盘价变化 + future_volatility = future_pct_change.rolling(window=10, min_periods=5).std().shift(-9) # 未来10根K线的波动率 - # 计算到达最高点的K线数(简化版本:如果涨幅 > 0.8%,则标记为1=长期持有,否则0=短期) - dataframe["&s-optimal_hold_duration"] = np.where( - (future_high_20 - dataframe["close"]) / dataframe["close"] > 0.008, # 未来能涨 > 0.8%(从1.5%降低) - 1, # 标记为长期持有(预计需要更长时间) - 0 # 短期快速出场 + # 标签:未来波动率 > 当前波动率 * 1.5 则标记为高波动(趋势启动) + volatility_ratio = future_volatility / (current_volatility + 1e-8) # 避免除以0 + dataframe["&s-future_volatility"] = np.where( + volatility_ratio > 1.5, + 1, # 未来高波动(趋势启动),继续持有 + 0 # 未来低波动(震荡市),快速止盈 ) return dataframe @@ -879,13 +881,6 @@ class FreqaiPrimer(IStrategy): except Exception: trade_age_minutes = 0.0 - # 新增:读取 AI 预测的持仓时长信号 - hold_duration_signal = None - if '&s-optimal_hold_duration' in df.columns: - hold_duration_signal = float(last_row['&s-optimal_hold_duration']) - elif '&-optimal_hold_duration' in df.columns: - hold_duration_signal = float(last_row['&-optimal_hold_duration']) - # 基于持仓时长的阈值衰减:持仓越久,阈值越低,越容易出场 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) @@ -894,23 +889,31 @@ class FreqaiPrimer(IStrategy): if current_profit <= 0.02: dynamic_threshold *= 0.8 - # 新逻辑:如果 AI 预测需要长期持有(hold_duration_signal > 0.5),且持仓时间还很短,则提高阈值 - if hold_duration_signal is not None and hold_duration_signal > 0.5: # AI 预测需要长期持有(从0.6降至0.5) - # 如果持仓时间 < 30分钟,阈值提高 50%,更难出场 - if trade_age_minutes < 30: + # 新增:读取 AI 预测的未来波动率信号(极端化方案) + future_vol_signal = None + if '&s-future_volatility' in df.columns: + future_vol_signal = float(last_row['&s-future_volatility']) + elif '&-future_volatility' in df.columns: + future_vol_signal = float(last_row['&-future_volatility']) + + # 极端化逻辑:根据 AI 预测的未来注动率调整阈值 + if future_vol_signal is not None: + if future_vol_signal > 0.6: # AI 预测趋势启动(高波动) + # 阈值提高 50%,耐心持有 dynamic_threshold *= 1.5 + # 如果是早期(<30分钟),再提高 30% + if trade_age_minutes < 30: + dynamic_threshold *= 1.3 logger.info( - f"[持仓时长 AI] [{pair}] AI 预测需要长期持有,提高阈值至 {dynamic_threshold:.2f}" + f"[波动率 AI] [{pair}] AI 预测趋势启动(高波动 {future_vol_signal:.2f}),提高阈值至 {dynamic_threshold:.2f}" ) - # 如果持仓时间 30-60分钟,阈值提高 20% - elif trade_age_minutes < 60: - dynamic_threshold *= 1.2 - elif hold_duration_signal is not None and hold_duration_signal < 0.3: # AI 预测短期快速出场(从0.4降至0.3) - # 阈值降低 20%,更容易出场 - dynamic_threshold *= 0.8 - logger.info( - f"[持仓时长 AI] [{pair}] AI 预测短期出场,降低阈值至 {dynamic_threshold:.2f}" - ) + elif future_vol_signal < 0.4: # AI 预测震荡市(低波动) + # 阈值降低 40%,快速止盈 + dynamic_threshold *= 0.6 + logger.info( + f"[波动率 AI] [{pair}] AI 预测震荡市(低波动 {future_vol_signal:.2f}),降低阈值至 {dynamic_threshold:.2f}" + ) + # 0.4-0.6 之间:中性区间,不调整 # 设定下限,避免阈值过低 dynamic_threshold = max(0.05, dynamic_threshold) @@ -919,14 +922,14 @@ class FreqaiPrimer(IStrategy): logger.info( f"[{pair}] ML 审核官拒绝出场: exit_signal 概率 {exit_prob:.2f} < 动态阈值 {dynamic_threshold:.2f}" f" | 原应出场原因: {exit_reason} | 持仓: {trade_age_minutes:.1f}min, 利润: {current_profit:.4f}" - f" | 持仓时长AI: {hold_duration_signal if hold_duration_signal is not None else 'N/A'}" + f" | 波动率AI: {future_vol_signal if future_vol_signal is not None else 'N/A'}" ) allow_exit = False else: logger.info( f"[{pair}] ML 审核官允许出场: exit_signal 概率 {exit_prob:.2f} >= 动态阈值 {dynamic_threshold:.2f}" f" | 出场原因: {exit_reason} | 持仓: {trade_age_minutes:.1f}min, 利润: {current_profit:.4f}" - f" | 持仓时长AI: {hold_duration_signal if hold_duration_signal is not None else 'N/A'}" + f" | 波动率AI: {future_vol_signal if future_vol_signal is not None else 'N/A'}" ) except Exception as e: logger.warning(f"[{pair}] ML 审核官出场检查失败,允许出场: {e}")