风险等级改成了波动率
This commit is contained in:
parent
986baf8c11
commit
727cf3d340
@ -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个
|
||||
|
||||
51
freqtrade/templates/market_regime_update_summary.md
Normal file
51
freqtrade/templates/market_regime_update_summary.md
Normal 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. 根据实际表现微调状态阈值
|
||||
Loading…
x
Reference in New Issue
Block a user