From 018328efd1786df8e5afb98700e263365561f447 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Sat, 7 Jun 2025 02:59:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=86=8A=E5=B8=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chat/result15.md | 543 ++++++++++++++++++++++++++ config_examples/freqaiprimer.json | 6 +- freqtrade/templates/freqaiprimer.json | 18 +- freqtrade/templates/freqaiprimer.py | 58 +++ 4 files changed, 613 insertions(+), 12 deletions(-) create mode 100644 chat/result15.md diff --git a/chat/result15.md b/chat/result15.md new file mode 100644 index 00000000..0c925622 --- /dev/null +++ b/chat/result15.md @@ -0,0 +1,543 @@ +> 当前策略的config, freqai部分, 如何调整配置能提升策略表现 +> + +你当前的 FreqAI 配置已经非常完整,涵盖了数据预处理、特征工程、模型训练、异常检测等多个方面。 + +--- + +## ✅ 当前配置亮点 + +| 模块 | 说明 | +|------|------| +| 多时间帧特征 | `include_timeframes`: ["3m", "15m", "1h"] | +| 相关币种特征 | 使用 BTC/USDT 和 SOL/USDT 做相关性分析 | +| 标签周期 | `label_period_candles`: 24(预测未来 24 根 K 线) | +| 特征选择 | 使用递归消除法(recursive_elimination) | +| 异常检测 | 使用 IsolationForest + SVM 过滤异常值 | +| 模型参数 | LightGBMRegressor,n_estimators=400 | + +--- + +## 🚀 如何优化 FreqAI 配置以提升策略表现? + +以下是 **6 个关键优化方向**,每个都附有建议配置和理由: + +--- + +### ✅ 1. **增加标签周期长度** + +> 当前:`label_period_candles: 24` + +#### 🔧 建议: +```json +"label_period_candles": 48 +``` + +#### 📌 理由: +- 更长的标签周期可以让模型学习更远期的趋势 +- 对于中长期趋势策略更有帮助 +- 可结合 ROI 设置进行匹配 + +--- + +### ✅ 2. **使用 PCA 降维(Principal Component Analysis)** + +> 当前:`principal_component_analysis`: false + +#### 🔧 建议: +```json +"principal_component_analysis": true +``` + +#### 📌 理由: +- 减少冗余特征,提高模型泛化能力 +- 对抗过拟合 +- 尤其适用于多时间帧 + 多币种场景 + +--- + +### ✅ 3. **调整模型训练参数(LightGBM)** + +> 当前:`n_estimators`: 400, `learning_rate`: 0.01 + +#### 🔧 建议: +```json +"model_training_parameters": { + "n_estimators": 600, + "learning_rate": 0.005, + "num_leaves": 40, + "max_depth": 10, + "min_data_in_leaf": 20, + "feature_fraction": 0.8, + "bagging_fraction": 0.8, + "bagging_freq": 5 +} +``` + +#### 📌 理由: +- 更多迭代次数 + 更低学习率 = 更稳定收敛 +- 增加叶子数和深度可以捕捉更复杂的模式 +- 添加正则化项防止过拟合 + +--- + +### ✅ 4. **增加更多相关币种用于特征提取** + +> 当前:`include_corr_pairlist`: ["BTC/USDT", "SOL/USDT"] + +#### 🔧 建议: +```json +"include_corr_pairlist": ["BTC/USDT", "ETH/USDT", "SOL/USDT", "XRP/USDT"] +``` + +#### 📌 理由: +- 不同币种之间存在联动效应 +- 增加更多主流币种可以增强市场状态识别能力 +- 尤其在牛市或熊市中效果显著 + +--- + +### ✅ 5. **启用增量训练(Incremental Training)** + +> 当前未启用 + +#### 🔧 建议: +```json +"incremental_train": true +``` + +#### 📌 理由: +- 在 live trading 中持续更新模型,而不是完全重训练 +- 提高模型对最新市场的适应速度 +- 减少 retrain 时间开销 + +--- + +### ✅ 6. **调整 outlier_protection_percentage** + +> 当前:`outlier_protection_percentage`: 0.1 + +#### 🔧 建议: +```json +"outlier_protection_percentage": 0.15 +``` + +#### 📌 理由: +- 市场波动剧烈时,适当放宽异常值过滤范围 +- 防止误删极端行情下的有效信号 +- 可结合 volatility_forecast 动态调整 + +--- + +## ✅ 推荐的优化后 FreqAI 配置(只展示修改部分) + +```json +"freqai": { + "enabled": true, + "identifier": "test58", + "train_period_days": 7, + "backtest_period_days": 1, + "live_retrain_hours": 2, + "purge_old_models": 2, + + "feature_parameters": { + "include_timeframes": ["3m", "15m", "1h"], + "include_corr_pairlist": ["BTC/USDT", "ETH/USDT", "SOL/USDT", "XRP/USDT"], + "label_period_candles": 48, + "include_shifted_candles": 3, + "DI_threshold": 0.7, + "weight_factor": 0.9, + "principal_component_analysis": true, + "use_SVM_to_remove_outliers": true, + "indicator_periods_candles": [10, 20, 50], + "plot_feature_importances": 10, + "outlier_protection_percentage": 0.15 + }, + + "data_split_parameters": { + "test_size": 0.2, + "shuffle": false + }, + + "model_training_parameters": { + "n_estimators": 600, + "learning_rate": 0.005, + "num_leaves": 40, + "max_depth": 10, + "min_data_in_leaf": 20, + "feature_fraction": 0.8, + "bagging_fraction": 0.8, + "bagging_freq": 5, + "verbose": -1 + }, + + "incremental_train": true +} +``` + +--- + +## ✅ 总结:推荐优化一览表 + +| 优化点 | 是否推荐 | 描述 | +|--------|----------|------| +| 增加 label_period_candles | ✅ 是 | 学习更远期趋势 | +| 启用 PCA 降维 | ✅ 是 | 减少冗余特征 | +| 调整 LightGBM 参数 | ✅ 是 | 提高模型性能 | +| 增加相关币种 | ✅ 是 | 增强市场感知 | +| 启用增量训练 | ✅ 是 | 提升实时适应性 | +| 放宽异常值过滤 | ✅ 是 | 避免误删极端行情 | + +--- + +🎯 **下一步建议:** + +你可以先尝试以下组合进行 backtest 测试: + +```bash +freqtrade backtesting --strategy freqaiprimer --config config_examples/freqaiprimer.json --timerange 20240101-20250101 --freqaimodel LightGBMMultiTargetRegressor +``` + +如果你希望我帮你: +- 实现动态调整 label_period_candles +- 加入模型漂移检测 +- 自动调整 outlier_protection_percentage + +请告诉我你想优先实现哪个功能,我可以为你定制这部分逻辑。 + +------ + +- Datetime: 2025-06-07 02:11:35 + +- Model: _qwen3/qwen-plus-latest + +- Selected files: + - result/backtest-result-2025-06-06_17-55-14.json + - result/analytic.log + - result/backtest-result-2025-06-06_17-55-14.meta.json + - result/backtest-result-2025-06-06_17-55-14_FreqaiPrimer.json + - result/backtest-result-2025-06-06_17-55-14_FreqaiPrimer.py + - result/backtest-result-2025-06-06_17-55-14_config.json + - result/backtest_trades.csv + - result/output.log + +> 在下行行情下,这个策略会亏损严重, 请给分析原因和解决策略 + +你当前的策略在**下行行情中表现不佳,亏损严重**,这是一个非常典型的问题。我们来从多个角度分析原因,并提出针对性的优化建议。 + +--- + +## 📉 一、回测结果总结(关键数据) + +| 指标 | 数值 | 说明 | +|------|------|------| +| 总交易数 | 10 | 少量交易但亏损集中 | +| 胜率 | 20% | 非常低,仅 2 赢,5 输 | +| 平均盈利 | -1.96% | 所有交易平均亏损近 2% | +| 最大单笔亏损 | -5.15%(TRUMP/USDT) | 单笔最大亏损超过 5% | +| ROI 设置 | `{"0": 0.028, "12": 0.016, "48": 0.009, "120": 0}` | 初始目标为 2.8%,但未达成 | +| Trailing Stop 设置 | `trailing_stop_positive = 0.237` | 追踪止损偏高,可能无法及时止盈 | + +--- + +## 🔍 二、亏损原因分析 + +### ✅ 1. **趋势判断滞后 + 止损设置不合理** + +- 策略使用了 EMA200 和价格背离作为主要信号 +- 在下行行情中: + - EMA200 反应慢,导致入场点位滞后 + - 价格背离信号容易“假突破”,造成频繁误判 +- 当前 trailing stop 设置为 `0.237`,但在下跌行情中根本无法触发,反而被提前止损 + +#### 📌 示例: + +```json +"trailing_stop_positive": 0.237, +"trailing_stop_positive_offset": 0.318, +``` + +这意味着只有当价格反弹到比最低价高出 23.7% 才会开始追踪,这在下跌趋势中几乎不可能实现。 + +--- + +### ✅ 2. **模型预测偏差 + 动态阈值失效** + +你的策略依赖 FreqAI 的 `&-price_value_divergence` 来判断买卖点,但在下行行情中: + +- 模型输出的 `labels_mean` 和 `labels_std` 偏移较大 +- 动态阈值计算逻辑过于简单,没有考虑市场状态变化 +- 导致买入信号过早触发,卖出信号延迟或缺失 + +#### 📌 示例代码段: + +```python +self.buy_threshold = labels_mean - k_buy * labels_std +self.sell_threshold = labels_mean + k_sell * labels_std +``` + +在下行行情中,`labels_mean` 下降,但 `k_buy * labels_std` 仍保持不变,导致买点不准确。 + +--- + +### ✅ 3. **缺乏空头保护机制** + +你的策略是纯多头策略(`is_short: false`),但在下跌行情中: + +- 没有做空机制 +- 没有对冲手段 +- 没有根据大盘走势动态调整仓位或暂停交易 + +#### 📌 回测日志显示: + +```log +Market change: -6.96% +``` + +大盘整体下跌近 7%,而你的策略仍然坚持做多,导致系统性亏损。 + +--- + +### ✅ 4. **入场条件过于宽松** + +你的入场条件包括: + +```python +cond1 = (dataframe["&-price_value_divergence"] < self.buy_threshold) +cond2 = (dataframe["volume_z_score"] > 1.5) +cond3 = (dataframe["rsi"] < 40) +cond4 = (dataframe["close"] <= dataframe["bb_lowerband"]) +buy_condition = cond1 & cond2 & cond3 & cond4 +``` + +这些条件在下跌行情中很容易满足,尤其是 RSI < 40 和 close 在布林下轨以下,容易形成“抄底陷阱”。 + +--- + +### ✅ 5. **出场逻辑单一 + ROI 不灵活** + +- ROI 设置为固定时间衰减曲线,但在下跌行情中需要更激进的止损 +- trailing stop 设置过高,无法有效锁定利润 +- sell_condition 中只有一个 RSI > 75 的条件,太弱 + +--- + +## 🚀 三、解决方案与优化建议 + +### ✅ 1. **加入大盘趋势过滤器(Market Trend Filter)** + +你可以通过 BTC/USDT 或 ETH/USDT 的趋势来判断是否开启交易。 + +#### 🔧 修改 `populate_indicators()`: + +```python +def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + # 获取 BTC/USDT 的趋势 + btc_df = self.dp.get_pair_dataframe("BTC/USDT", self.timeframe) + dataframe["btc_ema200"] = ta.EMA(btc_df, timeperiod=200) + dataframe["btc_trend"] = (btc_df["close"] > dataframe["btc_ema200"]).astype(int) + + # 如果 BTC 处于下降趋势,则禁止交易 + if dataframe["btc_trend"].iloc[-1] == 0: + logger.info(f"[{metadata['pair']}] BTC 处于下降趋势,暂停交易") + dataframe["enter_long"] = 0 + return dataframe + + # 否则继续执行原有逻辑... +``` + +--- + +### ✅ 2. **动态调整 trailing stop 参数** + +在下跌行情中,适当降低 trailing stop 的距离,提高退出速度。 + +#### 🔧 修改 `adjust_trade_position()`: + +```python +def adjust_trade_position(self, trade: Trade, current_time: datetime, + current_rate: float, current_profit: float, + min_roi: Dict[float, float], max_profit: float): + hold_time = (current_time - trade.open_date_utc).total_seconds() / 60 + + if hold_time < 15: + return None + + profit_ratio = (current_rate - trade.open_rate) / trade.open_rate + + # 如果大盘处于下跌趋势,缩短 trailing stop 距离 + market_trend = self.get_market_trend() + if market_trend == 'bear': + self.trailing_stop_distance = 0.005 # 更快退出 + self.trailing_stop_start = 0.01 + else: + self.trailing_stop_distance = 0.01 + self.trailing_stop_start = 0.03 + + if profit_ratio >= self.trailing_stop_start and not self.trailing_stop_enabled: + self.trailing_stop_enabled = True + trade.adjust_max_rate(current_rate) + + if self.trailing_stop_enabled: + max_rate = trade.max_rate + trailing_stop_price = max_rate * (1 - self.trailing_stop_distance) + if current_rate < trailing_stop_price: + return -1 + trade.adjust_max_rate(current_rate) + + if hold_time > 30: + return -1 + + return None +``` + +--- + +### ✅ 3. **优化入场条件:增加趋势确认机制** + +避免在下跌趋势中盲目抄底。 + +#### 🔧 修改 `populate_entry_trend()`: + +```python +if "&-price_value_divergence" in dataframe.columns: + # 新增:只在价格高于短期均线时才允许入场 + dataframe["ema20"] = ta.EMA(dataframe, timeperiod=20) + cond5 = (dataframe["close"] > dataframe["ema20"]) + + cond1 = (dataframe["&-price_value_divergence"] < self.buy_threshold) + cond2 = (dataframe["volume_z_score"] > 1.5) + cond3 = (dataframe["rsi"] < 40) + cond4 = (dataframe["close"] <= dataframe["bb_lowerband"]) + + buy_condition = cond1 & cond2 & cond3 & cond4 & cond5 +``` + +--- + +### ✅ 4. **动态调整 ROI 目标** + +在下跌行情中,ROI 应该更快衰减,甚至设为负值以强制止损。 + +#### 🔧 修改 `generate_roi_table()`: + +```python +def generate_roi_table(self, params: Dict) -> Dict[int, float]: + market_trend = self.get_market_trend() + + if market_trend == 'bear': + roi_table = { + "0": -0.01, # 强制止损 + "5": 0.005, # 极端情况下微利退出 + "15": 0.01, + "30": 0.015 + } + else: + roi_table = { + "0": params.get("roi_t0", 0.02), + "30": params.get("roi_t1", 0.01), + "60": params.get("roi_t2", 0.0), + } + + return roi_table +``` + +--- + +### ✅ 5. **加入大盘联动因子(Pair Correlation)** + +你可以利用 BTC/USDT 的波动率来动态调整其他币种的止损幅度。 + +#### 🔧 示例逻辑: + +```python +def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime, + current_rate: float, current_profit: float, **kwargs) -> float: + + # 获取 BTC 波动率 + btc_df = self.dp.get_pair_dataframe("BTC/USDT", self.timeframe) + volatility = (btc_df["close"].pct_change(24)).abs().mean() + + base_stop = -0.05 # 基础止损 + adjusted_stop = base_stop * (1 + volatility * 2) # 波动越大,止损越紧 + + return max(adjusted_stop, -0.1) # 最大不超过 -10% +``` + +--- + +### ✅ 6. **加入“市场状态识别”模块** + +你可以使用 RSI + ADX + Volatility 综合判断市场状态。 + +#### 🔧 示例逻辑: + +```python +def get_market_trend(self, dataframe: DataFrame) -> str: + rsi = dataframe["rsi"].iloc[-1] + adx = dataframe["adx"].iloc[-1] + trend_strength = abs(dataframe["trend_strength"].iloc[-1]) + + if adx > 25 and trend_strength < -0.01: + return "bear" + elif adx > 25 and trend_strength > 0.01: + return "bull" + else: + return "sideways" +``` + +然后在 `populate_entry_trend()` 和 `custom_stoploss()` 中使用这个状态。 + +--- + +## ✅ 四、推荐配置修改(config.json) + +```json +{ + "stoploss": -0.1, + "minimal_roi": { + "0": -0.01, + "5": 0.005, + "15": 0.01, + "30": 0.015 + }, + "trailing_stop": true, + "trailing_stop_positive": 0.01, + "trailing_stop_positive_offset": 0.02, + "trailing_only_offset_is_reached": true +} +``` + +--- + +## ✅ 五、总结:亏损原因 & 对策一览表 + +| 问题 | 原因 | 解决方案 | +|------|------|----------| +| 趋势判断滞后 | 使用 EMA200 + price divergence | 加入 BTC 趋势过滤器 | +| 动态阈值失效 | 没有考虑市场状态 | 根据市场状态调整 buy/sell threshold | +| 止损设置不合理 | trailing_stop_positive 过高 | 动态调整 trailing stop | +| 入场条件宽松 | 容易抄底失败 | 加入 EMA20 过滤 | +| 缺乏空头保护 | 没有做空机制 | 加入大盘趋势过滤器 | +| ROI 设置不合理 | 固定衰减,未适应下跌行情 | 动态 ROI 表 | +| 模型漂移 | labels_mean/std 偏移 | 加入 Z-score 标准化 | + +--- + +🎯 **下一步建议:** + +你可以优先实现以下功能之一,我为你定制具体代码: + +| 功能 | 推荐指数 | 描述 | +|------|----------|------| +| BTC 趋势过滤器 | ⭐⭐⭐⭐⭐ | 防止在熊市中盲目做多 | +| 动态 trailing stop | ⭐⭐⭐⭐ | 提高退出效率 | +| 动态 ROI 表 | ⭐⭐⭐⭐ | 自适应不同市场环境 | +| 市场状态识别 | ⭐⭐⭐ | 提升策略鲁棒性 | +| 模型漂移检测 | ⭐⭐⭐ | 防止模型退化 | + +--- + +如果你希望我帮你实现其中某一个功能,请告诉我你想优先实现哪个功能,我可以为你生成完整代码。 + +------ diff --git a/config_examples/freqaiprimer.json b/config_examples/freqaiprimer.json index 960f003b..61a70deb 100644 --- a/config_examples/freqaiprimer.json +++ b/config_examples/freqaiprimer.json @@ -81,15 +81,15 @@ "feature_parameters": { "include_timeframes": [ "3m", - "15m", - "1h" + "1h", + "12h", ], "include_corr_pairlist": [ "BTC/USDT", "SOL/USDT" ], "outlier_protection_percentage": 0.1, - "label_period_candles": 24, + "label_period_candles": 8, "include_shifted_candles": 3, "DI_threshold": 0.7, "weight_factor": 0.9, diff --git a/freqtrade/templates/freqaiprimer.json b/freqtrade/templates/freqaiprimer.json index e4ba3879..ab698f3b 100644 --- a/freqtrade/templates/freqaiprimer.json +++ b/freqtrade/templates/freqaiprimer.json @@ -16,21 +16,21 @@ }, "protection": {}, "roi": { - "0": 0.167, - "24": 0.036000000000000004, - "55": 0.012, - "119": 0 + "0": 0.028, + "12": 0.016, + "48": 0.009, + "120": 0 }, "stoploss": { - "stoploss": -0.057 + "stoploss": -0.279 }, "trailing": { "trailing_stop": true, - "trailing_stop_positive": 0.148, - "trailing_stop_positive_offset": 0.189, - "trailing_only_offset_is_reached": true + "trailing_stop_positive": 0.237, + "trailing_stop_positive_offset": 0.318, + "trailing_only_offset_is_reached": false } }, "ft_stratparam_v": 1, - "export_time": "2025-06-06 02:05:54.035420+00:00" + "export_time": "2025-06-06 14:26:19.180290+00:00" } \ No newline at end of file diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 550f7eb0..46c4bbc7 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -390,6 +390,29 @@ class FreqaiPrimer(IStrategy): return None profit_ratio = (current_rate - trade.open_rate) / trade.open_rate + + # 获取市场趋势并分别处理 + market_trend = self.get_market_trend() + + # 👇 分别处理 bull、bear、sideways 三种情况 + if market_trend == 'bull': + # 牛市:放宽 trailing stop,允许更多利润积累 + self.trailing_stop_distance = 0.015 + self.trailing_stop_start = 0.04 + logger.debug(f"[{trade.pair}] 当前为牛市,设置 trailing_stop_distance={self.trailing_stop_distance}, start={self.trailing_stop_start}") + + elif market_trend == 'bear': + # 熊市:收紧 trailing stop,快速止盈 + self.trailing_stop_distance = 0.005 + self.trailing_stop_start = 0.01 + logger.debug(f"[{trade.pair}] 当前为熊市,设置 trailing_stop_distance={self.trailing_stop_distance}, start={self.trailing_stop_start}") + + elif market_trend == 'sideways': + # 震荡市:保持默认值 + self.trailing_stop_distance = 0.01 + self.trailing_stop_start = 0.03 + logger.debug(f"[{trade.pair}] 当前为震荡市,使用默认 trailing_stop 参数") + if profit_ratio >= self.trailing_stop_start and not self.trailing_stop_enabled: self.trailing_stop_enabled = True trade.adjust_max_rate(current_rate) @@ -405,6 +428,7 @@ class FreqaiPrimer(IStrategy): if hold_time > 30: logger.info(f"[{trade.pair}] 持仓时间超过30分钟,强制平仓") + return -1 return None @@ -455,3 +479,37 @@ class FreqaiPrimer(IStrategy): adjusted_rate = proposed_rate * (1 + 0.0025) logger.debug(f"[{pair}] 自定义卖出价:{adjusted_rate:.6f}(原价:{proposed_rate:.6f})") return adjusted_rate + + def get_market_trend(self, dataframe: DataFrame = None) -> str: + """ + 使用 BTC/USDT 的 EMA200 判断大盘趋势 + 返回值: 'bull'(牛市)、'bear'(熊市)、'sideways'(震荡) + """ + + try: + # 获取 BTC/USDT 的数据 + btc_df = self.dp.get_pair_dataframe("BTC/USDT", self.timeframe) + if len(btc_df) < 200: + logger.warning("BTC 数据不足,返回默认趋势:sideways") + return "sideways" + + # 计算 EMA200 + btc_df["ema200"] = ta.EMA(btc_df, timeperiod=200) + + # 当前价格与 EMA200 的关系 + price_above_ema = (btc_df["close"].iloc[-1] > btc_df["ema200"].iloc[-1]) + + # 近期趋势强度(过去 50 根 K 线的平均涨跌幅) + trend_strength = btc_df["close"].pct_change(50).iloc[-1] + + # 判断市场状态 + if price_above_ema and trend_strength > 0.03: + return "bull" + elif not price_above_ema and trend_strength < -0.03: + return "bear" + else: + return "sideways" + + except Exception as e: + logger.error(f"获取市场趋势失败:{e}", exc_info=True) + return "sideways"