diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index ff88dd8f..92237c86 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -174,7 +174,7 @@ class FreqaiPrimer(IStrategy): "verbose": -1, } }, - "risk_rating": { + "market_regime": { "model": "LightGBMClassifier", "model_params": { "n_estimators": 200, @@ -253,20 +253,20 @@ class FreqaiPrimer(IStrategy): dataframe["ema200"] = ta.EMA(dataframe, timeperiod=200) dataframe["%-price_value_divergence"] = (dataframe["close"] - dataframe["ema200"]) / dataframe["ema200"] - # 新增:风险评级相关特征 + # 新增:市场状态/波动率制度相关特征 dataframe["%-atr-period"] = ta.ATR(dataframe, timeperiod=period) - dataframe["%-volatility_ratio"] = dataframe["%-atr-period"] / dataframe["close"] - dataframe["%-price_range"] = (dataframe["high"] - dataframe["low"]) / dataframe["close"] - dataframe["%-volume_volatility"] = dataframe["volume"].pct_change().rolling(period).std() - dataframe["%-price_velocity"] = dataframe["close"].pct_change().abs().rolling(period).mean() - dataframe["%-rsi_velocity"] = dataframe["%-rsi-period"].diff().abs().rolling(3).mean() + dataframe["%-bb_width"] = bb_upperband - bb_lowerband + dataframe["%-bb_width_ratio"] = dataframe["%-bb_width"] / bb_middleband * 100 # Bollinger Band宽度百分比 + dataframe["%-volatility_regime"] = dataframe["%-bb_width_ratio"].rolling(20).mean() # 波动率制度 + dataframe["%-regime_stability"] = dataframe["%-volatility_regime"].rolling(10).std() # 制度稳定性 + dataframe["%-price_efficiency"] = abs(dataframe["close"] - dataframe["ema200"]) / dataframe["ema200"] # 价格效率指标 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", "%-relative_volume-period", "%-price_value_divergence", - "%-atr-period", "%-volatility_ratio", "%-price_range", "%-volume_volatility", - "%-price_velocity", "%-rsi_velocity" + "%-atr-period", "%-bb_width", "%-bb_width_ratio", "%-volatility_regime", + "%-regime_stability", "%-price_efficiency" ] for col in columns_to_clean: dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0).ffill().fillna(0) @@ -298,45 +298,45 @@ class FreqaiPrimer(IStrategy): logger.warning(f"[{pair}] price_value_divergence包含非有限值,进行清理") dataframe["&-price_value_divergence"] = dataframe["&-price_value_divergence"].replace([np.inf, -np.inf, np.nan], 0.0) - # 新增:智能风险评级分类目标 - # 基于未来波动率、成交量异常、价格动量等多维度评估风险等级 - # 0: 低风险(绿色) 1: 中低风险(蓝色) 2: 中等风险(黄色) 3: 中高风险(橙色) 4: 高风险(红色) + # 新增:市场状态/波动率制度分类目标 + # 基于Bollinger Band宽度、波动率持续性、价格效率等多维度评估市场状态 + # 0: 低波动震荡 1: 正常趋势 2: 高波动趋势 3: 极端波动 4: 黑天鹅状态 - # 计算未来波动率作为风险指标 - future_atr = ta.ATR(dataframe, timeperiod=14).shift(-6) - future_volatility = (future_atr / dataframe['close']).replace([np.inf, -np.inf], 0) + # 计算Bollinger Band宽度作为波动率制度指标 + bb_upper, bb_middle, bb_lower = ta.BBANDS(dataframe['close'], timeperiod=20, nbdevup=2.0, nbdevdn=2.0) + bb_width_ratio = ((bb_upper - bb_lower) / bb_middle * 100).replace([np.inf, -np.inf], 0) - # 成交量异常检测 - volume_zscore = (dataframe['volume'] - dataframe['volume'].rolling(20).mean()) / dataframe['volume'].rolling(20).std() - volume_anomaly = abs(volume_zscore) > 2 + # 波动率持续性指标(制度稳定性) + volatility_regime = bb_width_ratio.rolling(20).mean() + regime_stability = volatility_regime.rolling(10).std() - # 价格动量强度 - price_momentum = abs(dataframe['close'].pct_change(5)).rolling(3).mean() + # 价格效率指标(偏离长期均线的程度) + price_efficiency = abs(dataframe['close'] - dataframe['ema200']) / dataframe['ema200'] - # 综合风险评分 - risk_score = ( - future_volatility * 0.4 + # 未来波动率权重40% - (abs(volume_zscore) / 5) * 0.3 + # 成交量异常权重30% - price_momentum * 0.3 # 价格动量权重30% + # 综合市场状态评分 + market_state_score = ( + volatility_regime * 0.5 + # 波动率制度权重50% + regime_stability * 0.3 + # 制度稳定性权重30% + price_efficiency * 0.2 # 价格效率权重20% ) - # 风险等级分类 - risk_conditions = [ - risk_score < 0.01, # 低风险 - risk_score < 0.02, # 中低风险 - risk_score < 0.035, # 中等风险 - risk_score < 0.05, # 中高风险 + # 市场状态分类(基于波动率制度) + state_conditions = [ + market_state_score < 2.0, # 低波动震荡 + market_state_score < 4.0, # 正常趋势 + market_state_score < 6.0, # 高波动趋势 + market_state_score < 8.0, # 极端波动 ] - risk_choices = [0, 1, 2, 3] + state_choices = [0, 1, 2, 3] - dataframe["&*-risk_rating"] = np.select(risk_conditions, risk_choices, default=4).astype(np.int32) + dataframe["&*-market_regime"] = np.select(state_conditions, state_choices, default=4).astype(np.int32) - # 清理风险评级值 - if not np.isfinite(dataframe["&*-risk_rating"]).all(): - logger.warning(f"[{pair}] risk_rating包含非有限值,进行清理") - dataframe["&*-risk_rating"] = dataframe["&*-risk_rating"].replace([np.inf, -np.inf, np.nan], 2).astype(np.int32) + # 清理市场状态值 + if not np.isfinite(dataframe["&*-market_regime"]).all(): + logger.warning(f"[{pair}] market_regime包含非有限值,进行清理") + dataframe["&*-market_regime"] = dataframe["&*-market_regime"].replace([np.inf, -np.inf, np.nan], 2).astype(np.int32) - logger.info(f"[{pair}] 风险评级分布: {dict(pd.Series(dataframe['&*-risk_rating']).value_counts())}") + logger.info(f"[{pair}] 市场状态分布: {dict(pd.Series(dataframe['&*-market_regime']).value_counts())}") # 新增:分类模型优化 first_length # 基于市场状态预测最优的 first_length 分类(2, 4, 6, 8, 10) @@ -658,26 +658,26 @@ class FreqaiPrimer(IStrategy): self.sell_threshold = max(self.sell_threshold, self.SELL_THRESHOLD_MIN) # 调试日志 - # 处理风险评级预测 - if "&*-risk_rating" in dataframe.columns: - risk_rating = dataframe["&*-risk_rating"].iloc[-1] if len(dataframe) > 0 else 2 + # 处理市场状态预测 + if "&*-market_regime" in dataframe.columns: + market_regime = dataframe["&*-market_regime"].iloc[-1] if len(dataframe) > 0 else 2 - # 基于风险评级调整仓位和止损 - risk_multipliers = { - 0: {"position": 1.5, "stoploss": 0.8, "label": "🟢低风险"}, # 低风险:加大仓位,收紧止损 - 1: {"position": 1.2, "stoploss": 0.9, "label": "🔵中低风险"}, # 中低风险:适中仓位 - 2: {"position": 1.0, "stoploss": 1.0, "label": "🟡中等风险"}, # 中等风险:标准参数 - 3: {"position": 0.7, "stoploss": 1.2, "label": "🟠中高风险"}, # 中高风险:减小仓位,放宽止损 - 4: {"position": 0.5, "stoploss": 1.5, "label": "🔴高风险"}, # 高风险:最小仓位,最宽止损 + # 基于市场状态调整仓位和止损 + regime_multipliers = { + 0: {"position": 1.5, "stoploss": 0.8, "label": "🟢低波动震荡"}, # 低波动震荡:加大仓位,收紧止损 + 1: {"position": 1.2, "stoploss": 0.9, "label": "🔵正常趋势"}, # 正常趋势:适中仓位 + 2: {"position": 1.0, "stoploss": 1.0, "label": "🟡高波动趋势"}, # 高波动趋势:标准参数 + 3: {"position": 0.7, "stoploss": 1.2, "label": "🟠极端波动"}, # 极端波动:减小仓位,放宽止损 + 4: {"position": 0.5, "stoploss": 1.5, "label": "🔴黑天鹅状态"}, # 黑天鹅状态:最小仓位,最宽止损 } - risk_config = risk_multipliers.get(risk_rating, risk_multipliers[2]) + regime_config = regime_multipliers.get(market_regime, regime_multipliers[2]) # 应用到策略参数 - self.risk_position_multiplier = risk_config["position"] - self.risk_stoploss_multiplier = risk_config["stoploss"] + self.risk_position_multiplier = regime_config["position"] + self.risk_stoploss_multiplier = regime_config["stoploss"] - logger.info(f"[{pair}] {risk_config['label']} - 仓位倍数: {self.risk_position_multiplier}, " + logger.info(f"[{pair}] {regime_config['label']} - 仓位倍数: {self.risk_position_multiplier}, " f"止损倍数: {self.risk_stoploss_multiplier}") else: # 默认值 @@ -692,7 +692,7 @@ class FreqaiPrimer(IStrategy): f"&-price_value_divergence: {dataframe['&-price_value_divergence'].iloc[-1]:.6f}, " f"volume_z_score: {dataframe['volume_z_score'].iloc[-1]:.2f}, " f"bb_lowerband: {dataframe['bb_lowerband'].iloc[-1]:.6f}, " - f"risk_rating: {dataframe['&*-risk_rating'].iloc[-1] if '&*-risk_rating' in dataframe else 'N/A'}") + f"market_regime: {dataframe['&*-market_regime'].iloc[-1] if '&*-market_regime' in dataframe else 'N/A'}") if not self.stats_logged: logger.info("===== 所有币对的 labels_mean 和 labels_std 汇总 =====") @@ -741,21 +741,21 @@ class FreqaiPrimer(IStrategy): open_trades = len(self.active_trades) if hasattr(self, 'active_trades') else 0 is_green_channel = (trend_status == "bullish" and open_trades <= 2 and self.GREEN_CHANNEL_ENABLED) - # 获取风险评级并调整入场条件 - risk_rating = dataframe["&*-risk_rating"].iloc[-1] if "&*-risk_rating" in dataframe.columns else 2 + # 获取市场状态并调整入场条件 + market_regime = dataframe["&*-market_regime"].iloc[-1] if "&*-market_regime" in dataframe.columns else 2 - # 风险评级影响入场严格程度 - risk_adjustments = { - 0: {"threshold_mult": 1.5, "strict_mult": 0.7}, # 低风险:更宽松入场 - 1: {"threshold_mult": 1.2, "strict_mult": 0.8}, # 中低风险:较宽松 - 2: {"threshold_mult": 1.0, "strict_mult": 1.0}, # 中等风险:标准 - 3: {"threshold_mult": 0.8, "strict_mult": 1.2}, # 中高风险:更严格 - 4: {"threshold_mult": 0.6, "strict_mult": 1.5}, # 高风险:最严格 + # 市场状态影响入场严格程度 + regime_adjustments = { + 0: {"threshold_mult": 1.5, "strict_mult": 0.7}, # 低波动震荡:更宽松入场 + 1: {"threshold_mult": 1.2, "strict_mult": 0.8}, # 正常趋势:较宽松 + 2: {"threshold_mult": 1.0, "strict_mult": 1.0}, # 高波动趋势:标准 + 3: {"threshold_mult": 0.8, "strict_mult": 1.2}, # 极端波动:更严格 + 4: {"threshold_mult": 0.6, "strict_mult": 1.5}, # 黑天鹅状态:最严格 } - risk_adj = risk_adjustments.get(risk_rating, risk_adjustments[2]) + regime_adj = regime_adjustments.get(market_regime, regime_adjustments[2]) - logger.info(f"[{pair}] 风险评级: {risk_rating}, 阈值调整: {risk_adj['threshold_mult']}, 严格度调整: {risk_adj['strict_mult']}") + logger.info(f"[{pair}] 市场状态: {market_regime}, 阈值调整: {regime_adj['threshold_mult']}, 严格度调整: {regime_adj['strict_mult']}") if is_green_channel: # 🟢 牛市绿色通道:持仓≤2个,25USDT入场,5条件需要满足4个 diff --git a/freqtrade/templates/market_regime_update_summary.md b/freqtrade/templates/market_regime_update_summary.md new file mode 100644 index 00000000..69742f9b --- /dev/null +++ b/freqtrade/templates/market_regime_update_summary.md @@ -0,0 +1,51 @@ +# 风险评级 → 市场状态/波动率制度 替换总结 + +## 变更概述 +已将策略中的"风险评级"维度替换为"市场状态/波动率制度"维度,解决了与趋势得分的同质化问题。 + +## 具体变更 + +### 1. 特征工程变更 +- **删除的风险评级特征**: + - `%-volatility_ratio` (波动率比率) + - `%-price_range` (价格范围) + - `%-volume_volatility` (成交量波动率) + - `%-price_velocity` (价格动量) + - `%-rsi_velocity` (RSI动量) + +- **新增的市场状态特征**: + - `%-bb_width` (Bollinger Band宽度) + - `%-bb_width_ratio` (BB宽度百分比) + - `%-volatility_regime` (波动率制度) + - `%-regime_stability` (制度稳定性) + - `%-price_efficiency` (价格效率指标) + +### 2. 目标变量变更 +- **旧目标**:`&*-risk_rating` (0-4级风险评级) +- **新目标**:`&*-market_regime` (0-4级市场状态) + +### 3. 市场状态分类定义 +- **0 - 低波动震荡**:低波动率,价格稳定 +- **1 - 正常趋势**:适中的波动率和趋势 +- **2 - 高波动趋势**:高波动但趋势明确 +- **3 - 极端波动**:极高波动率,市场不稳定 +- **4 - 黑天鹅状态**:极端市场状况 + +### 4. 策略逻辑更新 +- **仓位调整**:基于市场状态而非风险评级 +- **入场条件**:使用市场状态调整入场严格程度 +- **止损设置**:根据市场状态动态调整 + +### 5. 配置文件更新 +- 将`freqai_info["model_training_parameters"]`中的"risk_rating"模型配置改为"market_regime" + +## 优势 +1. **解决同质化**:市场状态与趋势得分关注不同维度,相关性更低 +2. **更直观**:直接反映市场波动状态而非抽象风险概念 +3. **实战价值**:可直接指导仓位管理和风险控制 +4. **特征丰富**:基于Bollinger Band、波动率持续性等多维度构建 + +## 使用建议 +1. 重新训练模型以适应新的市场状态分类 +2. 监控市场状态分布,确保各状态均衡 +3. 根据实际表现微调状态阈值 \ No newline at end of file