预测的波动率用来辅助决策入场
This commit is contained in:
parent
dc29df308d
commit
59f207767a
@ -62,6 +62,106 @@ class FreqaiPrimer(IStrategy):
|
||||
logger.info(message)
|
||||
|
||||
|
||||
def calculate_comprehensive_volatility_signal(self, dataframe: DataFrame, metadata: dict) -> tuple[float, str]:
|
||||
"""
|
||||
计算综合波动率信号和趋势方向
|
||||
返回: (波动率强度, 趋势方向)
|
||||
波动率强度: 0.0-1.0, 数值越高表示波动越大
|
||||
趋势方向: 'up'(上涨), 'down'(下跌), 'neutral'(中性)
|
||||
"""
|
||||
if len(dataframe) < 50:
|
||||
return 0.5, 'neutral' # 数据不足时返回中性值
|
||||
|
||||
# 获取最新数据
|
||||
current_data = dataframe.iloc[-1]
|
||||
recent_data = dataframe.tail(20) # 最近20根K线
|
||||
|
||||
# 1. 基于ATR的波动率计算
|
||||
atr = current_data.get('atr', 0)
|
||||
if atr > 0:
|
||||
atr_normalized = min(atr / current_data['close'] / 0.02, 1.0) # 归一化到0-1
|
||||
else:
|
||||
atr_normalized = 0.3 # 默认中等波动
|
||||
|
||||
# 2. 基于收盘价标准差的波动率
|
||||
price_volatility = recent_data['close'].pct_change().abs().std()
|
||||
if pd.notna(price_volatility):
|
||||
price_volatility_normalized = min(price_volatility / 0.03, 1.0) # 归一化到0-1
|
||||
else:
|
||||
price_volatility_normalized = 0.3
|
||||
|
||||
# 3. 基于布林带宽度的波动率
|
||||
bb_width = 0
|
||||
if 'bb_upper_3m' in dataframe.columns and 'bb_lower_3m' in dataframe.columns:
|
||||
bb_width = (current_data['bb_upper_3m'] - current_data['bb_lower_3m']) / current_data['close']
|
||||
bb_width_normalized = min(bb_width / 0.1, 1.0) # 归一化到0-1
|
||||
else:
|
||||
bb_width_normalized = 0.3
|
||||
|
||||
# 4. 综合波动率强度 (平均值)
|
||||
volatility_strength = (atr_normalized + price_volatility_normalized + bb_width_normalized) / 3.0
|
||||
|
||||
# 5. 趋势方向判断
|
||||
trend_direction = 'neutral'
|
||||
|
||||
# 使用多个时间框架和技术指标进行趋势判断
|
||||
if 'close' in dataframe.columns and len(dataframe) >= 50:
|
||||
# 短期趋势:基于EMA交叉
|
||||
if 'ema_50_3m' in dataframe.columns and 'ema_200_3m' in dataframe.columns:
|
||||
current_close = current_data['close']
|
||||
ema_50 = current_data['ema_50_3m']
|
||||
ema_200 = current_data['ema_200_3m']
|
||||
|
||||
# EMA趋势
|
||||
if current_close > ema_50 > ema_200:
|
||||
trend_direction = 'up'
|
||||
elif current_close < ema_50 < ema_200:
|
||||
trend_direction = 'down'
|
||||
|
||||
# 补充趋势判断:基于RSI和MACD
|
||||
if trend_direction == 'neutral':
|
||||
# RSI趋势判断
|
||||
if 'rsi_3m' in dataframe.columns:
|
||||
rsi = current_data['rsi_3m']
|
||||
if pd.notna(rsi):
|
||||
if rsi > 60:
|
||||
trend_direction = 'up'
|
||||
elif rsi < 40:
|
||||
trend_direction = 'down'
|
||||
|
||||
# MACD趋势判断
|
||||
if trend_direction == 'neutral' and 'macd_3m' in dataframe.columns and 'macd_signal_3m' in dataframe.columns:
|
||||
macd = current_data['macd_3m']
|
||||
macd_signal = current_data['macd_signal_3m']
|
||||
if pd.notna(macd) and pd.notna(macd_signal):
|
||||
if macd > macd_signal:
|
||||
trend_direction = 'up'
|
||||
else:
|
||||
trend_direction = 'down'
|
||||
|
||||
# 6. 结合15分钟数据进行趋势确认
|
||||
try:
|
||||
df_15m = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='15m')
|
||||
if len(df_15m) >= 50:
|
||||
current_15m = df_15m.iloc[-1]
|
||||
|
||||
# 15分钟EMA趋势
|
||||
if 'ema_50_15m' in df_15m.columns and 'ema_200_15m' in df_15m.columns:
|
||||
ema_50_15m = current_15m['ema_50_15m']
|
||||
ema_200_15m = current_15m['ema_200_15m']
|
||||
close_15m = current_15m['close']
|
||||
|
||||
if close_15m > ema_50_15m > ema_200_15m:
|
||||
trend_direction = 'up'
|
||||
elif close_15m < ema_50_15m < ema_200_15m:
|
||||
trend_direction = 'down'
|
||||
except Exception:
|
||||
# 如果无法获取15分钟数据,则使用已有判断
|
||||
pass
|
||||
|
||||
return min(volatility_strength, 1.0), trend_direction
|
||||
|
||||
|
||||
# 只用于adjust_trade_position方法的波动系数获取
|
||||
def get_volatility_coefficient(self, pair: str) -> float:
|
||||
"""
|
||||
@ -918,8 +1018,44 @@ class FreqaiPrimer(IStrategy):
|
||||
# 确保概率在 [0, 1] 范围内(分类器输出可能有浮点误差)
|
||||
entry_prob = max(0.0, min(1.0, entry_prob))
|
||||
entry_threshold = self.ml_entry_signal_threshold.value
|
||||
|
||||
# 新增:读取 AI 预测的未来波动率信号(入场决策版本)
|
||||
future_vol_signal = None
|
||||
if '&s-future_volatility' in df.columns:
|
||||
future_vol_signal = float(last_row['&s-future_volatility'])
|
||||
elif '&-future_volatility' in df.columns:
|
||||
future_vol_signal = float(last_row['&-future_volatility'])
|
||||
|
||||
# 波动率AI入场决策逻辑
|
||||
if future_vol_signal is not None:
|
||||
# 情况A:AI 预测强趋势(高波动 > 0.65),且ML入场信号强 → 更倾向于入场
|
||||
if future_vol_signal > 0.65 and entry_prob >= entry_threshold:
|
||||
self.strategy_log(
|
||||
f"[波动率 AI] [{pair}] AI 预测强趋势(高波动 {future_vol_signal:.2f}),增强入场信心 | "
|
||||
f"ML概率: {entry_prob:.2f}, 阈值: {entry_threshold:.2f}"
|
||||
)
|
||||
# 可以考虑稍微降低入场阈值或增加入场权重
|
||||
# 情况B:AI 预测震荡市(低波动 < 0.35)→ 谨慎入场,可能错过趋势机会但降低风险
|
||||
elif future_vol_signal < 0.35:
|
||||
self.strategy_log(
|
||||
f"[波动率 AI] [{pair}] AI 预测震荡市(低波动 {future_vol_signal:.2f}),谨慎入场 | "
|
||||
f"ML概率: {entry_prob:.2f}, 阈值: {entry_threshold:.2f}"
|
||||
)
|
||||
# 在震荡市中,可以适当提高入场阈值,要求更强的信号才入场
|
||||
adjusted_threshold = entry_threshold * 1.1 # 提高10%的要求
|
||||
if entry_prob < adjusted_threshold:
|
||||
self.strategy_log(
|
||||
f"[波动率 AI] [{pair}] 震荡市中入场信号不足: {entry_prob:.2f} < 调整后阈值 {adjusted_threshold:.2f},拒绝入场"
|
||||
)
|
||||
allow_trade = False
|
||||
else:
|
||||
self.strategy_log(
|
||||
f"[波动率 AI] [{pair}] 震荡市中入场信号充足: {entry_prob:.2f} >= 调整后阈值 {adjusted_threshold:.2f},允许入场"
|
||||
)
|
||||
# 介于 0.35-0.65 之间:中性区间,按原ML审核官逻辑处理
|
||||
|
||||
# 记录entry_signal值用于调试
|
||||
self.strategy_log(f"[{pair}] ML 审核官检查: entry_signal={entry_prob:.2f}, 阈值={entry_threshold:.2f}, 市场状态={market_state}")
|
||||
self.strategy_log(f"[{pair}] ML 审核官检查: entry_signal={entry_prob:.2f}, 阈值={entry_threshold:.2f}, 市场状态={market_state}, 波动率AI: {future_vol_signal if future_vol_signal is not None else 'N/A'}")
|
||||
if entry_prob < entry_threshold:
|
||||
self.strategy_log(f"[{pair}] ML 审核官拒绝入场: entry_signal 概率 {entry_prob:.2f} < 阈值 {entry_threshold:.2f}(上涨概率低,不宜入场)")
|
||||
allow_trade = False
|
||||
@ -1039,8 +1175,40 @@ class FreqaiPrimer(IStrategy):
|
||||
return True
|
||||
# 介于 0.35-0.65 之间:中性区间,不做强制处理,继续走原有 ML 审核官逻辑
|
||||
|
||||
# 使用综合技术指标计算波动率强度和趋势方向
|
||||
volatility_strength, trend_direction = self.calculate_comprehensive_volatility_signal(df, {'pair': pair})
|
||||
|
||||
# 基于趋势方向调整阈值
|
||||
# 如果趋势向上但当前盈利,可能需要更宽松的退出条件以抓住更多收益
|
||||
# 如果趋势向下且当前盈利,可能需要更严格的退出条件以保护利润
|
||||
trend_adjustment = 0.0
|
||||
if trend_direction == 'up' and current_profit > 0:
|
||||
# 上升趋势中盈利,稍微放宽退出条件,让利润继续增长
|
||||
trend_adjustment = -0.05 # 降低阈值,更容易退出(保护利润)
|
||||
elif trend_direction == 'down' and current_profit > 0:
|
||||
# 下降趋势中盈利,收紧退出条件,尽快锁定利润
|
||||
trend_adjustment = 0.05 # 提高阈值,更难退出(保护利润)
|
||||
elif trend_direction == 'up' and current_profit < 0:
|
||||
# 上升趋势中亏损,稍微放宽退出条件,可能及时止损
|
||||
trend_adjustment = -0.03
|
||||
elif trend_direction == 'down' and current_profit < 0:
|
||||
# 下降趋势中亏损,收紧退出条件,等待反弹
|
||||
trend_adjustment = 0.03
|
||||
|
||||
# 应用趋势调整后的阈值
|
||||
trend_adjusted_threshold = dynamic_threshold + trend_adjustment
|
||||
# 确保阈值在合理范围内
|
||||
trend_adjusted_threshold = max(0.05, min(0.95, trend_adjusted_threshold))
|
||||
|
||||
# 记录趋势分析信息
|
||||
self.strategy_log(
|
||||
f"[趋势分析] [{pair}] 波动强度: {volatility_strength:.2f}, "
|
||||
f"趋势方向: {trend_direction}, 趋势调整: {trend_adjustment:.2f}, "
|
||||
f"调整后阈值: {trend_adjusted_threshold:.2f}, 原始阈值: {dynamic_threshold:.2f}"
|
||||
)
|
||||
|
||||
# 设定下限,避免阈值过低
|
||||
dynamic_threshold = max(0.05, dynamic_threshold)
|
||||
dynamic_threshold = max(0.05, trend_adjusted_threshold)
|
||||
|
||||
if exit_prob < dynamic_threshold:
|
||||
self.strategy_log(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user