feat(position_manager): 优化止损与止盈逻辑,确保实际止损距离与盈亏比计算一致

在 `position_manager.py` 中更新了止损和止盈计算逻辑,确保使用实际止损距离进行盈亏比的计算,避免因保证金封顶导致的止盈不合理。同时,新增止盈上限配置,防止止盈距离过大。此改动提升了交易策略的准确性与风险控制能力。
This commit is contained in:
薇薇安 2026-02-19 18:30:23 +08:00
parent f5570f4804
commit 43daa922a4

View File

@ -709,17 +709,13 @@ class PositionManager:
)
# ⚠️ 2026-01-29优化计算止损距离用于盈亏比止盈计算确保达到3:1目标
stop_distance_for_tp = None
if side == 'BUY':
stop_distance_for_tp = entry_price - stop_loss_price
else:
stop_distance_for_tp = stop_loss_price - entry_price
# 如果ATR可用使用ATR计算更准确的止损距离用于盈亏比止盈
# 实际止损距离(用于 TP1 最小盈亏比,必须与真实挂单一致,避免 SL 被保证金封顶后 TP 仍按 ATR 拉很远)
actual_stop_distance = (entry_price - stop_loss_price) if side == 'BUY' else (stop_loss_price - entry_price)
stop_distance_for_tp = actual_stop_distance
# 如果ATR可用使用ATR计算更准确的止损距离仅用于 get_take_profit_price 的盈亏比,不用于 TP1 的 MIN_RR_FOR_TP1
if atr is not None and atr > 0 and entry_price > 0:
atr_percent = atr / entry_price
atr_multiplier = config.TRADING_CONFIG.get('ATR_STOP_LOSS_MULTIPLIER', 3.0) # 2026-02-12优化默认3.0,避免噪音止损
# 使用ATR计算的止损距离更准确用于盈亏比止盈
stop_distance_for_tp = entry_price * atr_percent * atr_multiplier
take_profit_pct_margin = config.TRADING_CONFIG.get('TAKE_PROFIT_PERCENT', 0.30)
@ -760,13 +756,13 @@ class PositionManager:
take_profit_1_amount = margin_usdt * take_profit_1_pct_margin
tp1_distance = take_profit_1_amount / quantity
# ⚠️ 2026-02-10优化确保TP1至少有 1.2倍 的盈亏比 (相对于止损距离)
# 避免在高波动(宽止损)情况下,固定保证金比例止盈导致盈亏比过低
if stop_distance_for_tp is not None and stop_distance_for_tp > 0:
# ⚠️ 2026-02-10优化确保TP1至少有 1.2倍 的盈亏比 (相对于【实际】止损距离)
# 使用 actual_stop_distance真实挂单距离避免 SL 被保证金封顶后仍用 ATR 宽距离推高 TP 导致 4% SL vs 62% TP 的畸形
if actual_stop_distance is not None and actual_stop_distance > 0:
min_rr_for_tp1 = config.TRADING_CONFIG.get('MIN_RR_FOR_TP1', 1.5)
min_tp1_distance = stop_distance_for_tp * min_rr_for_tp1
min_tp1_distance = actual_stop_distance * min_rr_for_tp1
if min_tp1_distance > tp1_distance:
logger.info(f"{symbol} [优化] TP1距离 ({tp1_distance:.4f}) 小于 {min_rr_for_tp1}止损距离 ({min_tp1_distance:.4f}),已自动调整以保证盈亏比")
logger.info(f"{symbol} [优化] TP1距离 ({tp1_distance:.4f}) 小于 {min_rr_for_tp1}实际止损距离 ({min_tp1_distance:.4f}),已自动调整以保证盈亏比")
tp1_distance = min_tp1_distance
# ⚠️ 2026-02-12优化确保TP1至少覆盖双向手续费避免微利单实际上亏损
@ -776,6 +772,18 @@ class PositionManager:
logger.info(f"{symbol} [优化] TP1距离 ({tp1_distance:.4f}) 小于 手续费磨损距离 ({min_fee_distance:.4f}),已自动调整以覆盖成本")
tp1_distance = min_fee_distance
# ⚠️ 止盈上限TP1 不超过配置的止盈比例避免“4% 止损 vs 62% 止盈”的畸形(与 USE_MARGIN_CAP_FOR_TP 一致)
if margin_usdt and margin_usdt > 0 and quantity > 0:
tp1_max_pct = config.TRADING_CONFIG.get('TAKE_PROFIT_1_PERCENT', 0.20)
if tp1_max_pct is not None and tp1_max_pct > 1:
tp1_max_pct = tp1_max_pct / 100.0
tp1_max_pct = (tp1_max_pct or 0.20) * 1.5 # 允许第一目标最多约 30% 保证金
tp1_max_amount = margin_usdt * tp1_max_pct
tp1_max_distance = tp1_max_amount / quantity
if tp1_distance > tp1_max_distance:
logger.info(f"{symbol} [优化] TP1距离 ({tp1_distance:.4f}) 超过止盈上限 ({tp1_max_distance:.4f},约{tp1_max_pct*100:.0f}% margin),已封顶")
tp1_distance = tp1_max_distance
if tp1_distance > 0:
if side == 'BUY':
take_profit_1 = entry_price + tp1_distance