风险等级改成了波动率

This commit is contained in:
zhangkun9038@dingtalk.com 2025-08-19 08:16:35 +08:00
parent 986baf8c11
commit 727cf3d340
2 changed files with 115 additions and 64 deletions

View File

@ -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个

View File

@ -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. 根据实际表现微调状态阈值