diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py index 2bf6416..53daf0d 100644 --- a/trading_system/risk_manager.py +++ b/trading_system/risk_manager.py @@ -761,18 +761,25 @@ class RiskManager: if stop_loss_price_price is not None: candidate_prices.append(('价格百分比', stop_loss_price_price)) - # ⚠️ 修复:选择"更紧的止损"(更接近入场价),保护资金 - # - 做多(BUY):止损价越低越紧(更接近入场价)→ 取最大值(更高的止损价,更接近入场价) - # - 做空(SELL):止损价越高越紧(更接近入场价)→ 取最小值(更低的止损价,更接近入场价) - # 注意:做空时,止损价高于入场价,所以"更紧"意味着"更小的止损价"(更接近入场价) - if side == 'BUY': - # 做多:止损价越低越紧 → 取最大值(更高的止损价,更接近入场价) - stop_loss_price = max(p[1] for p in candidate_prices) - selected_method = [p[0] for p in candidate_prices if p[1] == stop_loss_price][0] + # ⚠️ 优化:如果ATR可用,优先使用ATR止损,不强制取"更紧"的止损 + # 只有在ATR不可用时,才使用保证金止损作为兜底 + if stop_loss_price_atr is not None: + stop_loss_price = stop_loss_price_atr + selected_method = 'ATR' + # 记录被覆盖的保证金止损(仅供参考) + logger.debug(f"优先使用ATR止损: {stop_loss_price:.4f}, 忽略保证金止损: {stop_loss_price_margin:.4f}") else: - # 做空:止损价越高越紧 → 取最小值(更低的止损价,更接近入场价) - stop_loss_price = min(p[1] for p in candidate_prices) - selected_method = [p[0] for p in candidate_prices if p[1] == stop_loss_price][0] + # ATR不可用,使用保证金止损和价格百分比止损中"更紧"的一个(保护资金) + if side == 'BUY': + # 做多:取最大值(更高的止损价,更接近入场价) + stop_loss_price = max(p[1] for p in candidate_prices if p[0] != 'ATR') + else: + # 做空:取最小值(更低的止损价,更接近入场价) + stop_loss_price = min(p[1] for p in candidate_prices if p[0] != 'ATR') + + # 找到对应的策略名称 + matched = [p[0] for p in candidate_prices if abs(p[1] - stop_loss_price) < 1e-9] + selected_method = matched[0] if matched else '保证金' # 如果提供了技术分析数据,计算技术止损(允许更紧的止损,但需要在保证金止损范围内) technical_stop = None @@ -823,16 +830,24 @@ class RiskManager: ) # 重新选择最终的止损价(包括技术止损) - # 仍保持“更宽松/更远”的选择规则 - if side == 'BUY': - # 做多:选择更高的止损价(更接近入场价,更紧) - final_stop_loss = max(p[1] for p in candidate_prices) - selected_method = [p[0] for p in candidate_prices if p[1] == final_stop_loss][0] + # ⚠️ 优化:如果列表中包含ATR止损,优先使用ATR止损(通常更宽,能容忍波动) + # 否则使用"更紧"的止损来保护资金 + + atr_candidate = next((p for p in candidate_prices if p[0] == 'ATR'), None) + + if atr_candidate: + final_stop_loss = atr_candidate[1] + selected_method = 'ATR' else: - # ⚠️ 关键修复:做空必须选择更低的止损价(更接近入场价,更紧) - # 注意:对于SELL单,止损价高于入场价,所以"更低的止损价"意味着更接近入场价 - final_stop_loss = min(p[1] for p in candidate_prices) - selected_method = [p[0] for p in candidate_prices if p[1] == final_stop_loss][0] + if side == 'BUY': + # 做多:选择更高的止损价(更紧) + final_stop_loss = max(p[1] for p in candidate_prices) + selected_method = [p[0] for p in candidate_prices if p[1] == final_stop_loss][0] + else: + # ⚠️ 关键修复:做空必须选择更低的止损价(更接近入场价,更紧) + # 注意:对于SELL单,止损价高于入场价,所以"更低的止损价"意味着更接近入场价 + final_stop_loss = min(p[1] for p in candidate_prices) + selected_method = [p[0] for p in candidate_prices if p[1] == final_stop_loss][0] # ⚠️ 关键修复:验证最终止损价对应的保证金百分比不超过配置值 if side == 'BUY':