This commit is contained in:
薇薇安 2026-02-03 22:51:04 +08:00
parent 833f8096d7
commit 2f50ecd172

View File

@ -761,18 +761,25 @@ class RiskManager:
if stop_loss_price_price is not None: if stop_loss_price_price is not None:
candidate_prices.append(('价格百分比', stop_loss_price_price)) candidate_prices.append(('价格百分比', stop_loss_price_price))
# ⚠️ 修复:选择"更紧的止损"(更接近入场价),保护资金 # ⚠️ 优化如果ATR可用优先使用ATR止损不强制取"更紧"的止损
# - 做多(BUY):止损价越低越紧(更接近入场价)→ 取最大值(更高的止损价,更接近入场价) # 只有在ATR不可用时才使用保证金止损作为兜底
# - 做空(SELL):止损价越高越紧(更接近入场价)→ 取最小值(更低的止损价,更接近入场价) if stop_loss_price_atr is not None:
# 注意:做空时,止损价高于入场价,所以"更紧"意味着"更小的止损价"(更接近入场价) stop_loss_price = stop_loss_price_atr
if side == 'BUY': selected_method = 'ATR'
# 做多:止损价越低越紧 → 取最大值(更高的止损价,更接近入场价) # 记录被覆盖的保证金止损(仅供参考)
stop_loss_price = max(p[1] for p in candidate_prices) logger.debug(f"优先使用ATR止损: {stop_loss_price:.4f}, 忽略保证金止损: {stop_loss_price_margin:.4f}")
selected_method = [p[0] for p in candidate_prices if p[1] == stop_loss_price][0]
else: else:
# 做空:止损价越高越紧 → 取最小值(更低的止损价,更接近入场价) # ATR不可用使用保证金止损和价格百分比止损中"更紧"的一个(保护资金)
stop_loss_price = min(p[1] for p in candidate_prices) if side == 'BUY':
selected_method = [p[0] for p in candidate_prices if p[1] == stop_loss_price][0] # 做多:取最大值(更高的止损价,更接近入场价)
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 technical_stop = None
@ -823,16 +830,24 @@ class RiskManager:
) )
# 重新选择最终的止损价(包括技术止损) # 重新选择最终的止损价(包括技术止损)
# 仍保持“更宽松/更远”的选择规则 # ⚠️ 优化如果列表中包含ATR止损优先使用ATR止损通常更宽能容忍波动
if side == 'BUY': # 否则使用"更紧"的止损来保护资金
# 做多:选择更高的止损价(更接近入场价,更紧)
final_stop_loss = max(p[1] for p in candidate_prices) atr_candidate = next((p for p in candidate_prices if p[0] == 'ATR'), None)
selected_method = [p[0] for p in candidate_prices if p[1] == final_stop_loss][0]
if atr_candidate:
final_stop_loss = atr_candidate[1]
selected_method = 'ATR'
else: else:
# ⚠️ 关键修复:做空必须选择更低的止损价(更接近入场价,更紧) if side == 'BUY':
# 注意对于SELL单止损价高于入场价所以"更低的止损价"意味着更接近入场价 # 做多:选择更高的止损价(更紧)
final_stop_loss = min(p[1] for p in candidate_prices) 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] 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': if side == 'BUY':