From fcd39bfd31eb9db1712011b247db9d62e2fff42f Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Sun, 29 Jun 2025 06:37:52 +0000 Subject: [PATCH] =?UTF-8?q?debug=20log=E7=BB=93=E5=90=88=E8=B1=86=E5=8C=85?= =?UTF-8?q?=E5=AF=B9=E5=B8=81=E5=AF=B9=E8=A1=8C=E6=83=85=E6=88=AA=E5=9B=BE?= =?UTF-8?q?=E5=88=86=E6=9E=90,=20=E8=AE=A9grok=E8=BF=9B=E8=A1=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20https://x.com/i/grok=3Fconversation=3D1939204516592?= =?UTF-8?q?906372?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- freqtrade/templates/freqaiprimer.py | 76 ++++++++++++++--------------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 6c2b7d6a..3750443d 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -270,42 +270,50 @@ class FreqaiPrimer(IStrategy): ] def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - """ - 生成买入信号,优化条件以增加交易机会 - """ - pair = metadata.get('pair', 'Unknown') - conditions = [] + pair = metadata.get('pair', 'Unknown') + conditions = [] # 获取市场趋势得分 trend_score = self.get_market_trend(dataframe=dataframe, metadata=metadata) - # 动态调整 cond2 和 cond3 的阈值 - # volume_z_score 阈值范围:0.5 (强牛市, trend_score=100) 到 2.0 (强熊市, trend_score=0) + # 动态调整成交量阈值:牛市(trend_score=100)-> 0.5,熊市(trend_score=0)-> 1.5 volume_z_score_min = 0.5 - volume_z_score_max = 2.0 + volume_z_score_max = 1.5 volume_z_score_threshold = self.linear_map(trend_score, 0, 100, volume_z_score_max, volume_z_score_min) - # rsi 阈值范围:40 (强牛市, trend_score=100) 到 60 (强熊市, trend_score=0) + # 动态调整 RSI 阈值:牛市(trend_score=100)-> 40,熊市(trend_score=0)-> 60 rsi_min = 40 rsi_max = 60 rsi_threshold = self.linear_map(trend_score, 0, 100, rsi_max, rsi_min) + # 新增:动态调整 STOCHRSI 阈值,牛市 -> 30,熊市 -> 50 + stochrsi_min = 30 + stochrsi_max = 50 + stochrsi_threshold = self.linear_map(trend_score, 0, 100, stochrsi_max, stochrsi_min) + if "&-price_value_divergence" in dataframe.columns: + # 计算 STOCHRSI + stochrsi = ta.STOCHRSI(dataframe, timeperiod=14, fastk_period=3, fastd_period=3) + dataframe["stochrsi_k"] = stochrsi["fastk"] + cond1 = (dataframe["&-price_value_divergence"] < self.buy_threshold) cond2 = (dataframe["volume_z_score"] > volume_z_score_threshold) cond3 = (dataframe["rsi"] < rsi_threshold) cond4 = (dataframe["close"] <= dataframe["bb_lowerband"]) - buy_condition = cond1 & cond2 & cond3 & cond4 + cond5 = (dataframe["stochrsi_k"] < stochrsi_threshold) # 新增 STOCHRSI 条件 + buy_condition = cond1 & cond2 & cond3 & cond4 & cond5 conditions.append(buy_condition) divergence_value = dataframe['&-price_value_divergence'].iloc[-1] if not dataframe['&-price_value_divergence'].isna().all() else np.nan volume_z_score_value = dataframe['volume_z_score'].iloc[-1] if not dataframe['volume_z_score'].isna().all() else np.nan rsi_value = dataframe['rsi'].iloc[-1] if not dataframe['rsi'].isna().all() else np.nan + stochrsi_value = dataframe['stochrsi_k'].iloc[-1] if not dataframe['stochrsi_k'].isna().all() else np.nan logger.debug(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]}, " - f"close={dataframe['close'].iloc[-1]:.6f} <= bb_lowerband={dataframe['bb_lowerband'].iloc[-1]:.6f}: {cond4.iloc[-1]}") + f"close={dataframe['close'].iloc[-1]:.6f} <= bb_lowerband={dataframe['bb_lowerband'].iloc[-1]:.6f}: {cond4.iloc[-1]}, " + f"stochrsi_k={stochrsi_value:.2f} < {stochrsi_threshold:.2f}: {cond5.iloc[-1]}") else: logger.warning(f"[{pair}] ⚠️ &-price_value_divergence 列缺失,跳过买入信号生成") @@ -320,7 +328,6 @@ class FreqaiPrimer(IStrategy): logger.debug(f"[{pair}] 无有效买入条件") return dataframe - def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: pair = metadata.get('pair', 'Unknown') conditions = [] @@ -515,43 +522,27 @@ class FreqaiPrimer(IStrategy): return adjusted_rate def get_market_trend(self, dataframe: DataFrame = None, metadata: dict = None) -> int: - """ - 计算市场趋势得分,0 表示强熊,100 表示强牛,50 表示中性。 - 综合 3m、15m 和 1h 时间框架的趋势,使用对数函数映射,非线性增强两端趋势。 - 融合价格趋势、K 线形态、StochRSI 和量价关系。 - - 参数: - dataframe: 可选,外部传入的 BTC/USDT 数据(3m 时间框架),默认为 None(自动获取)。 - metadata: 可选,包含币种信息。 - - 返回值: - int: 0-100 的趋势得分。 - """ try: - # 初始化得分和权重 timeframes = ["3m", "15m", "1h"] - weights = {"3m": 0.5, "15m": 0.3, "1h": 0.2} # 短期框架权重更高 + weights = {"3m": 0.5, "15m": 0.3, "1h": 0.2} # 默认权重 trend_scores = {} - pair = metadata.get('pair', 'Unknown') if metadata else 'Unknown' logger.debug(f"[{pair}] 正在计算多时间框架市场趋势得分") for tf in timeframes: - # 获取对应时间框架的数据 if tf == "3m" and dataframe is not None: btc_df = dataframe else: btc_df = self.dp.get_pair_dataframe("BTC/USDT", tf) - # 检查数据量 - min_candles = 200 if tf == "3m" else 100 if tf == "15m" else 50 # 不同时间框架所需最小数据量 + min_candles = 200 if tf == "3m" else 100 if tf == "15m" else 50 if len(btc_df) < min_candles: logger.warning(f"BTC 数据不足({tf},{len(btc_df)} 根K线),使用默认得分:50") trend_scores[tf] = 50 continue - # --- 价格趋势 --- - ema_short_period = 50 if tf == "3m" else 20 if tf == "15m" else 12 # 调整周期以适应时间框架 + # 价格趋势 + ema_short_period = 50 if tf == "3m" else 20 if tf == "15m" else 12 ema_long_period = 200 if tf == "3m" else 80 if tf == "15m" else 50 btc_df["ema_short"] = ta.EMA(btc_df, timeperiod=ema_short_period) btc_df["ema_long"] = ta.EMA(btc_df, timeperiod=ema_long_period) @@ -571,7 +562,7 @@ class FreqaiPrimer(IStrategy): elif ema_short_slope < -0.005: price_score -= 15 - # --- K 线形态 --- + # K线形态 btc_df["bullish_engulfing"] = ( (btc_df["close"].shift(1) < btc_df["open"].shift(1)) & (btc_df["close"] > btc_df["open"]) & @@ -588,13 +579,13 @@ class FreqaiPrimer(IStrategy): kline_score = 0 if btc_df["bullish_engulfing"].iloc[-1]: kline_score += 15 - elif btc_df["bearish_engulfing"].iloc[-1]: + elif btc_df["bearish_engulfing"]: kline_score -= 15 volatility = btc_df["close"].pct_change(10).std() * 100 if volatility > 0.5: kline_score += 10 if price_score > 0 else -10 - # --- StochRSI --- + # StochRSI stochrsi = ta.STOCHRSI(btc_df, timeperiod=14, fastk_period=3, fastd_period=3) btc_df["stochrsi_k"] = stochrsi["fastk"] btc_df["stochrsi_d"] = stochrsi["fastd"] @@ -611,7 +602,7 @@ class FreqaiPrimer(IStrategy): elif stochrsi_k < 50: stochrsi_score -= 5 - # --- 量价关系 --- + # 量价关系 btc_df["volume_mean_20"] = btc_df["volume"].rolling(20).mean() btc_df["volume_std_20"] = btc_df["volume"].rolling(20).std() btc_df["volume_z_score"] = (btc_df["volume"] - btc_df["volume_mean_20"]) / btc_df["volume_std_20"] @@ -623,7 +614,7 @@ class FreqaiPrimer(IStrategy): if btc_df["adx"].iloc[-1] > 25: volume_score += 10 if price_score > 0 else -10 - # --- 综合得分 --- + # 综合得分 raw_score = price_score + kline_score + stochrsi_score + volume_score raw_score = max(min(raw_score, 50), -50) @@ -638,14 +629,19 @@ class FreqaiPrimer(IStrategy): f"价格得分:{price_score}, K线得分:{kline_score}, " f"StochRSI得分:{stochrsi_score}, 量价得分:{volume_score}") - # 加权融合多时间框架得分 + # 动态调整权重:当 1h 得分显著高于 3m(差值 > 20),提高 1h 权重 + if trend_scores.get("1h", 50) - trend_scores.get("3m", 50) > 20: + weights = {"3m": 0.3, "15m": 0.3, "1h": 0.4} + logger.debug(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) final_score = int(round(final_score)) final_score = max(0, min(100, final_score)) logger.info(f"[{pair}] 最终趋势得分:{final_score}, " - f"3m得分:{trend_scores.get('3m', 50)}, 15m得分:{trend_scores.get('15m', 50)}, " - f"1h得分:{trend_scores.get('1h', 50)}") + f"3m得分:{trend_scores.get('3m', 50)}, 15m得分:{trend_scores.get('15m', 50)}, " + f"1h得分:{trend_scores.get('1h', 50)}") return final_score except Exception as e: