diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 47f25c65..c6e10bca 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -103,10 +103,10 @@ class FreqaiPrimer(IStrategy): # 配置日志格式,包含时间戳 logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - level=logging.DEBUG, + level=logging.info, datefmt='%Y-%m-%d %H:%M:%S,%f'[:-3] # 毫秒精度 ) - logger.debug("✅ 策略已初始化,日志级别设置为 DEBUG") + logger.info("✅ 策略已初始化,日志级别设置为 DEBUG") self.trailing_stop_enabled = False self.pair_stats = {} self.stats_logged = False @@ -141,7 +141,7 @@ class FreqaiPrimer(IStrategy): dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0).ffill().fillna(0) pair = metadata.get('pair', 'Unknown') - logger.debug(f"[{pair}] 特征工程完成,列:{list(dataframe.columns)}") + logger.info(f"[{pair}] 特征工程完成,列:{list(dataframe.columns)}") return dataframe def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame: @@ -174,7 +174,7 @@ class FreqaiPrimer(IStrategy): def is_bearish_market(self, dataframe: DataFrame, metadata: dict, timeframe: str = "1h") -> pd.Series: pair = metadata.get('pair', 'Unknown') - logger.debug(f"[{pair}] 开始计算 1h 熊市信号") + logger.info(f"[{pair}] 开始计算 1h 熊市信号") # 防御性检查 required_columns = ['close_1h', 'high_1h', 'low_1h', 'open_1h', 'stochrsi_k_1h', 'stochrsi_d_1h', 'bb_middle_1h'] @@ -226,7 +226,7 @@ class FreqaiPrimer(IStrategy): bearish_signal = (cond_a & cond_b) | (cond_a & cond_c) | (cond_b & cond_c) | (cond_a & cond_d) # 记录每个条件的触发情况 - logger.debug(f"[{pair}] 熊市信号 - 条件a (价格低于布林中轨): {cond_a.mean():.2%}, " + logger.info(f"[{pair}] 熊市信号 - 条件a (价格低于布林中轨): {cond_a.mean():.2%}, " f"条件b (STOCHRSI>90): {cond_b.mean():.2%}, " f"条件c (看跌形态): {cond_c.mean():.2%}, " f"条件d (成交量下降): {cond_d.mean():.2%}, " @@ -320,7 +320,7 @@ class FreqaiPrimer(IStrategy): logger.error(f"[{pair}] FreqAI 未初始化,回退到规则计算") dataframe["&-price_value_divergence"] = dataframe["price_value_divergence"] else: - logger.debug(f"[{pair}] 调用 FreqAI 预测,类型:{type(self.freqai)}") + logger.info(f"[{pair}] 调用 FreqAI 预测,类型:{type(self.freqai)}") dataframe = self.freqai.start(dataframe, metadata, self) if "&-price_value_divergence" not in dataframe.columns: logger.warning(f"[{pair}] FreqAI 未生成 &-price_value_divergence,回退到规则计算") @@ -380,7 +380,7 @@ class FreqaiPrimer(IStrategy): logger.info(f"[{pair}] 市场趋势得分:{market_trend_score}, labels_mean:{labels_mean:.4f}, labels_std:{labels_std:.4f}") logger.info(f"[{pair}] k_buy:{k_buy:.2f}, k_sell:{k_sell:.2f}") logger.info(f"[{pair}] 动态买入阈值:{self.buy_threshold:.4f}, 卖出阈值:{self.sell_threshold:.4f}") - logger.debug(f"[{pair}] 最新数据 - close: {dataframe['close'].iloc[-1]:.6f}, " + logger.info(f"[{pair}] 最新数据 - close: {dataframe['close'].iloc[-1]:.6f}, " f"rsi: {dataframe['rsi'].iloc[-1]:.2f}, " f"&-price_value_divergence: {dataframe['&-price_value_divergence'].iloc[-1]:.6f}, " f"volume_z_score: {dataframe['volume_z_score'].iloc[-1]:.2f}, " @@ -433,9 +433,9 @@ class FreqaiPrimer(IStrategy): cond7 = ~stochrsi_overbought_aligned # 记录 cond6 和 cond7 的触发情况 - logger.debug(f"[{pair}] cond6 (非熊市) 触发率: {(~bearish_signal_aligned).mean():.2%}, " + logger.info(f"[{pair}] cond6 (非熊市) 触发率: {(~bearish_signal_aligned).mean():.2%}, " f"熊市信号 K 线数: {bearish_signal_aligned.sum()}") - logger.debug(f"[{pair}] cond7 (STOCHRSI 非超买) 触发率: {(~stochrsi_overbought_aligned).mean():.2%}, " + logger.info(f"[{pair}] cond7 (STOCHRSI 非超买) 触发率: {(~stochrsi_overbought_aligned).mean():.2%}, " f"STOCHRSI 超买 K 线数: {stochrsi_overbought_aligned.sum()}") buy_condition = cond1 & cond2 & cond3 & cond4 & cond5 & cond6 & cond7 & (trend_score > 60) @@ -448,7 +448,7 @@ class FreqaiPrimer(IStrategy): stochrsi_value = dataframe["stochrsi_k"].iloc[-1] bb_close_value = dataframe["close"].iloc[-1] bb_lower_value = dataframe["bb_lowerband"].iloc[-1] - logger.debug(f"[{pair}] 买入条件检查 - " + logger.info(f"[{pair}] 买入条件检查 - " f"&-price_value_divergence={divergence_value:.6f} < {self.buy_threshold:.6f}: {cond1.iloc[-1]}, " f"volume_z_score={volume_z_score_value:.2f} > {volume_z_score_threshold:.2f}: {cond2.iloc[-1]}, " f"rsi={rsi_value:.2f} < {rsi_threshold:.2f}: {cond3.iloc[-1]}, " @@ -465,11 +465,11 @@ class FreqaiPrimer(IStrategy): if combined_condition.any(): logger.info(f"[{pair}] 买入信号触发,趋势得分:{trend_score:.2f}") else: - logger.debug(f"[{pair}] 买入条件未满足") + logger.info(f"[{pair}] 买入条件未满足") else: - logger.debug(f"[{pair}] 无有效买入条件") + logger.info(f"[{pair}] 无有效买入条件") - logger.debug(f"[{pair}] 各条件触发率 - " + logger.info(f"[{pair}] 各条件触发率 - " f"cond1: {cond1.mean():.2%}, " f"cond2: {cond2.mean():.2%}, " f"cond3: {cond3.mean():.2%}, " @@ -523,10 +523,10 @@ class FreqaiPrimer(IStrategy): # 综合卖出条件:根据 trend_score 调整逻辑 if trend_score > 85: sell_condition = (cond1 & cond2) | (cond1 & cond3) | (cond2 & cond3) # 中等趋势,至少两个条件满足 - logger.debug(f"[{pair}] 趋势得分 {trend_score:.2f} > 55,需满足至少两个条件") + logger.info(f"[{pair}] 趋势得分 {trend_score:.2f} > 55,需满足至少两个条件") else: sell_condition = cond1 | cond2 | cond3 # 弱势趋势,任一条件满足 - logger.debug(f"[{pair}] 趋势得分 {trend_score:.2f} <= 55,任一条件满足") + logger.info(f"[{pair}] 趋势得分 {trend_score:.2f} <= 55,任一条件满足") conditions.append(sell_condition) @@ -536,7 +536,7 @@ class FreqaiPrimer(IStrategy): stochrsi_value = dataframe["stochrsi_k"].iloc[-1] if not dataframe["stochrsi_k"].isna().all() else np.nan adx_value = dataframe["adx"].iloc[-1] if not dataframe["adx"].isna().all() else np.nan short_term_return = dataframe["short_term_return"].iloc[-1] if not dataframe["short_term_return"].isna().all() else np.nan - logger.debug(f"[{pair}] 卖出条件检查 - " + logger.info(f"[{pair}] 卖出条件检查 - " f"&-price_value_divergence={divergence_value:.6f} > {self.sell_threshold * 1.06:.6f}: {cond1.iloc[-1]}, " f"rsi={rsi_value:.2f} > 75 & stochrsi_k={stochrsi_value:.2f} > 80: {cond2.iloc[-1]}, " f"short_term_return={short_term_return:.2f}% > {rapid_rise_threshold:.2f}% & profit > {min_profit*100:.2f}%: {cond3.iloc[-1]}, " @@ -548,7 +548,7 @@ class FreqaiPrimer(IStrategy): dataframe.loc[reduce(lambda x, y: x & y, conditions), 'exit_long'] = 1 logger.info(f"[{pair}] 出场信号触发,条件满足,趋势得分:{trend_score:.2f}") else: - logger.debug(f"[{pair}] 无有效卖出条件") + logger.info(f"[{pair}] 无有效卖出条件") return dataframe @@ -597,7 +597,7 @@ class FreqaiPrimer(IStrategy): profit_ratio = (current_rate - trade.open_rate) / trade.open_rate initial_stake_amount = trade.stake_amount / 3 - logger.debug(f"{pair} 首次入场金额: {initial_stake_amount:.2f}, 当前持仓金额: {trade.stake_amount:.2f}, " + logger.info(f"{pair} 首次入场金额: {initial_stake_amount:.2f}, 当前持仓金额: {trade.stake_amount:.2f}, " f"加仓次数: {trade.nr_of_successful_entries - 1}") # 加仓逻辑 @@ -607,7 +607,7 @@ class FreqaiPrimer(IStrategy): # 线性映射加仓阈值,趋势值越高,加仓越严格 add_threshold = 80 - 30 * (trend_score / 100) # 趋势值 100 -> 50, 0 -> 80 if profit_ratio <= add_position_threshold and hold_time > 5 and trend_score <= add_threshold: - logger.debug(f"{pair} 初始下注金额: {initial_stake_amount:.2f}, trend_score: {trend_score:.2f}, add_threshold: {add_threshold} ") + logger.info(f"{pair} 初始下注金额: {initial_stake_amount:.2f}, trend_score: {trend_score:.2f}, add_threshold: {add_threshold} ") # 计算加仓金额 add_count = trade.nr_of_successful_entries - 1 @@ -615,9 +615,9 @@ class FreqaiPrimer(IStrategy): if add_count < len(multipliers): multiplier = multipliers[add_count] add_amount = initial_stake_amount * multiplier - logger.debug(f"{pair} 第 {add_count + 1} 次加仓,倍数={multiplier}, " + logger.info(f"{pair} 第 {add_count + 1} 次加仓,倍数={multiplier}, " f"金额 = {initial_stake_amount:.2f} * {multiplier} = {add_amount:.2f}") - logger.debug(f"{pair} 加仓计算: 第 {add_count + 1} 次加仓,倍数={multiplier}, " + logger.info(f"{pair} 加仓计算: 第 {add_count + 1} 次加仓,倍数={multiplier}, " f"金额 = {initial_stake_amount:.2f} * {multiplier} = {add_amount:.2f}") if min_stake is not None and add_amount < min_stake: @@ -673,7 +673,7 @@ class FreqaiPrimer(IStrategy): def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, current_time: datetime, **kwargs) -> bool: # 调试日志:记录输入参数 - logger.debug(f"[{pair}] confirm_trade_entry called with rate={rate}, type(rate)={type(rate)}, " + logger.info(f"[{pair}] confirm_trade_entry called with rate={rate}, type(rate)={type(rate)}, " f"amount={amount}, order_type={order_type}, time_in_force={time_in_force}") # 检查 rate 是否有效 @@ -719,7 +719,7 @@ class FreqaiPrimer(IStrategy): - 长时间持仓降低 ROI 目标。 """ pair = trade.pair - logger.debug(f"[{pair}] 计算自定义 ROI,当前盈利: {current_profit:.2%}, 持仓时间: {trade_dur} 分钟") + logger.info(f"[{pair}] 计算自定义 ROI,当前盈利: {current_profit:.2%}, 持仓时间: {trade_dur} 分钟") # 获取最新数据 dataframe = self.dp.get_pair_dataframe(pair=pair, timeframe=self.timeframe) @@ -753,7 +753,7 @@ class FreqaiPrimer(IStrategy): # 动态调整 ROI,限制在 0% 到 20% 之间 dynamic_roi = {time: min(max(roi * roi_factor, 0.0), 0.2) for time, roi in base_roi.items()} - logger.debug(f"[{pair}] Divergence: {divergence:.4f}, RSI: {rsi:.2f}, 持仓时间: {trade_dur} 分钟, " + logger.info(f"[{pair}] Divergence: {divergence:.4f}, RSI: {rsi:.2f}, 持仓时间: {trade_dur} 分钟, " f"调整系数: divergence={divergence_factor:.2f}, rsi={rsi_factor:.2f}, time={time_factor:.2f}, " f"总系数={roi_factor:.2f}, 动态 ROI 表格: {dynamic_roi}") return dynamic_roi @@ -761,14 +761,14 @@ class FreqaiPrimer(IStrategy): def custom_entry_price(self, pair: str, trade: Trade | None, current_time: datetime, proposed_rate: float, entry_tag: str | None, side: str, **kwargs) -> float: adjusted_rate = proposed_rate * (1 - 0.005) - logger.debug(f"[{pair}] 自定义买入价:{adjusted_rate:.6f}(原价:{proposed_rate:.6f})") + logger.info(f"[{pair}] 自定义买入价:{adjusted_rate:.6f}(原价:{proposed_rate:.6f})") return adjusted_rate def custom_exit_price(self, pair: str, trade: Trade, current_time: datetime, proposed_rate: float, current_profit: float, exit_tag: str | None, **kwargs) -> float: adjusted_rate = proposed_rate * (1 + 0.0025) - logger.debug(f"[{pair}] 自定义卖出价:{adjusted_rate:.6f}(原价:{proposed_rate:.6f})") + logger.info(f"[{pair}] 自定义卖出价:{adjusted_rate:.6f}(原价:{proposed_rate:.6f})") return adjusted_rate def get_market_trend(self, dataframe: DataFrame = None, metadata: dict = None) -> int: @@ -783,7 +783,7 @@ class FreqaiPrimer(IStrategy): logger.error(f"[{pair}] Invalid pair in metadata: {metadata}. Returning default score 50") return 50 - logger.debug(f"[{pair}] 正在计算多时间框架市场趋势得分") + logger.info(f"[{pair}] 正在计算多时间框架市场趋势得分") for tf in timeframes: # 优先使用传入的 dataframe(如果匹配主时间框架),否则加载目标币对数据 @@ -879,14 +879,14 @@ class FreqaiPrimer(IStrategy): mapped_score = 50 * (np.log1p(-raw_score / 50) / np.log1p(1)) trend_scores[tf] = max(0, min(100, int(round(mapped_score)))) - logger.debug(f"[{pair}] {tf} 趋势得分:{trend_scores[tf]}, 原始得分:{raw_score}, " + logger.info(f"[{pair}] {tf} 趋势得分:{trend_scores[tf]}, 原始得分:{raw_score}, " f"价格得分:{price_score}, K线得分:{kline_score}, " f"StochRSI得分:{stochrsi_score}, 量价得分:{volume_score}") # 动态调整权重 if trend_scores.get("1h", 50) - trend_scores.get("3m", 50) > 20 or trend_scores.get("15m", 50) - trend_scores.get("3m", 50) > 20: weights = {"3m": 0.2, "15m": 0.35, "1h": 0.45} - logger.debug(f"[{pair}] 1h 趋势得分({trend_scores.get('1h', 50)})显著高于 3m({trend_scores.get('3m', 50)}),调整权重为 {weights}") + logger.info(f"[{pair}] 1h 趋势得分({trend_scores.get('1h', 50)})显著高于 3m({trend_scores.get('3m', 50)}),调整权重为 {weights}") # 加权融合 final_score = sum(trend_scores[tf] * weights[tf] for tf in timeframes)