From 8d19ede45d614b50be200793f4e1b1b01eded644 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Sat, 31 May 2025 10:50:22 +0000 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E5=AD=A6=E4=B9=A0=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E9=87=8D=E6=96=B0=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- freqtrade/templates/freqaiprimer.py | 56 +++++++++++++++++++---------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 9fdef785..6cc9e5d4 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -46,6 +46,20 @@ class FreqaiPrimer(IStrategy): use_dynamic_roi = True position_adjuster = True + plot_config = { + "main_plot": {}, + "subplots": { + "Signals": { + "enter_long": {"color": "green"}, + "exit_long": {"color": "red"} + }, + "FreqAI Predictions": { + "&-trend_strength": {"color": "blue"}, + "&-volatility_forecast": {"color": "orange"}, + "&-divergence_score": {"color": "purple"} + } + } + } freqai_info = { "model": "LightGBMMultiTargetRegressor", @@ -53,6 +67,7 @@ class FreqaiPrimer(IStrategy): "include_timeframes": ["5m", "15m", "1h"], "label_period_candles": 24, "include_shifted_candles": 3, + "principal_component_analysis": True, }, "data_split_parameters": { "test_size": 0.2, @@ -106,16 +121,6 @@ class FreqaiPrimer(IStrategy): "%-bb_width-period", "%-roc-period", "%-relative_volume-period", "%-close-bb_lower-period", "%-tema-period", "%-price_trend_diff-period", "%-roc_mfi_ratio-period" ] - for col in columns_to_clean: - dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0).ffill().fillna(0) - - columns_to_clean = [ - "%-rsi-period", "%-mfi-period", "%-sma-period", "%-ema-period", "%-adx-period", - "bb_lowerband-period", "bb_middleband-period", "bb_upperband-period", - "%-bb_width-period", "%-roc-period", "%-relative_volume-period", "%-close-bb_lower-period", "%-tema-period", - "%-price_trend_diff-period", "%-roc_mfi_ratio-period" - ] - for col in columns_to_clean: dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan) dataframe[col] = dataframe[col].ffill().fillna(0) @@ -147,7 +152,7 @@ class FreqaiPrimer(IStrategy): dataframe["trend_change"] = dataframe["&-trend_strength"].pct_change(label_period) dataframe["&-divergence_score"] = dataframe["price_change"] - dataframe["trend_change"] - # 👇 新增:清理所有目标列中的非有限值 + # 👇 新增:清理所有目标列中的非有限值 + clip 背离评分 target_columns = [ "&-trend_strength", "&-volatility_forecast", @@ -161,9 +166,11 @@ class FreqaiPrimer(IStrategy): dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan) dataframe[col] = dataframe[col].ffill().fillna(0) + # 对背离评分做裁剪,防止极端值干扰交易信号 + dataframe["&-divergence_score"] = dataframe["&-divergence_score"].clip(-1, 1) + return dataframe - # 👇 缓存 mean/std 供后续使用 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe = self.freqai.start(dataframe, metadata, self) @@ -182,17 +189,25 @@ class FreqaiPrimer(IStrategy): return dataframe - # 👇 使用背离信号作为入场条件 def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: conditions = [] if "&-divergence_score" in df.columns: - buy_condition = df["&-divergence_score"] > 0.01 + mean_divergence = df["mean_divergence"].iloc[-1] if "mean_divergence" in df.columns else 0 + std_divergence = df["std_divergence"].iloc[-1] if "std_divergence" in df.columns else 1 + # 计算 Z-score + z_score_divergence = (df["&-divergence_score"] - mean_divergence) / std_divergence + + # 正向背离:Z-score > 1 + buy_condition = z_score_divergence > 1 + + # 结合趋势强度过滤 if "&-trend_strength" in df.columns: buy_condition &= df["&-trend_strength"] > 0.005 + # 成交量过滤:成交量需大于 20 日均值的 1 倍 df["vol_mean"] = df["volume"].rolling(20).mean() buy_condition &= (df["volume"] > df["vol_mean"] * 1) @@ -203,14 +218,21 @@ class FreqaiPrimer(IStrategy): return df - # 👇 使用背离信号作为出场条件 def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame: conditions = [] if "&-divergence_score" in df.columns: - sell_condition = df["&-divergence_score"] < -0.01 + mean_divergence = df["mean_divergence"].iloc[-1] if "mean_divergence" in df.columns else 0 + std_divergence = df["std_divergence"].iloc[-1] if "std_divergence" in df.columns else 1 + # 计算 Z-score + z_score_divergence = (df["&-divergence_score"] - mean_divergence) / std_divergence + + # 负向背离:Z-score < -1 + sell_condition = z_score_divergence < -1 + + # 结合趋势强度过滤 if "&-trend_strength" in df.columns: sell_condition &= df["&-trend_strength"] < -0.005 @@ -221,7 +243,6 @@ class FreqaiPrimer(IStrategy): return df - # 👇 自定义止损(基于波动率缩放) def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) @@ -233,7 +254,6 @@ class FreqaiPrimer(IStrategy): return dynamic_stoploss - # 👇 动态调整持仓止盈 def adjust_trade_position(self, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, min_roi: Dict[float, float], max_profit: float) -> Optional[Dict[float, float]]: