增加移动止损单独的日志处理

This commit is contained in:
薇薇安 2026-02-26 11:50:52 +08:00
parent df2b8d6372
commit 432fc85a79

View File

@ -97,6 +97,46 @@ def _log_trade_db_failure(symbol, entry_order_id, side, quantity, entry_price, a
logger.warning(f"写入落库失败日志失败: {e}") logger.warning(f"写入落库失败日志失败: {e}")
_TRAILING_LOG_PATH: Optional[Path] = None
def _get_trailing_stop_log_path() -> Optional[Path]:
"""保本/移动止损专用日志路径logs/profit_protection.log便于 tail/grep 确认是否执行。"""
global _TRAILING_LOG_PATH
if _TRAILING_LOG_PATH is not None:
return _TRAILING_LOG_PATH
try:
root = Path(__file__).parent.parent
log_dir = root / "logs"
log_dir.mkdir(parents=True, exist_ok=True)
_TRAILING_LOG_PATH = log_dir / "profit_protection.log"
return _TRAILING_LOG_PATH
except Exception:
return None
def _log_trailing_stop_event(account_id: int, symbol: str, event: str, **kwargs):
"""将保本/移动止损相关事件写入专用日志(一行 JSON便于确认是否正常执行。"""
path = _get_trailing_stop_log_path()
if not path:
return
try:
rec = {
"ts": datetime.utcnow().isoformat() + "Z",
"account_id": account_id,
"symbol": symbol,
"event": event,
}
for k, v in kwargs.items():
if v is not None and k not in rec:
if isinstance(v, float):
rec[k] = round(v, 6)
else:
rec[k] = v
with open(path, "a", encoding="utf-8") as f:
f.write(json.dumps(rec, ensure_ascii=False) + "\n")
except Exception as e:
logger.debug(f"写入保本/移动止损日志失败: {e}")
# User Data Stream 缓存(持仓/余额优先读 WS减少 REST # User Data Stream 缓存(持仓/余额优先读 WS减少 REST
try: try:
from .user_data_stream import get_stream_instance, get_positions_from_cache, get_balance_from_cache from .user_data_stream import get_stream_instance, get_positions_from_cache, get_balance_from_cache
@ -1481,8 +1521,10 @@ class PositionManager:
logger.warning(f"[账号{self.account_id}] {symbol} 同步跳过: 止损或止盈为空 stop_loss={stop_loss} take_profit={take_profit}") logger.warning(f"[账号{self.account_id}] {symbol} 同步跳过: 止损或止盈为空 stop_loss={stop_loss} take_profit={take_profit}")
return return
sync_type = "保本/移动止损同步" if (position_info.get("breakevenStopSet") or position_info.get("trailingStopActivated")) else "SL/TP同步"
logger.info( logger.info(
f"[账号{self.account_id}] {symbol} 开始同步止损/止盈至交易所: SL={float(stop_loss):.4f} TP={float(take_profit):.4f}" f"[账号{self.account_id}] {symbol} 开始同步止损/止盈至交易所 [{sync_type}]: "
f"止损触发价={float(stop_loss):.4f} 止盈触发价={float(take_profit):.4f}"
) )
# 验证止损价格是否合理。保本/移动止损时:多单止损可≥入场价、空单止损可≤入场价,不得被改回亏损价 # 验证止损价格是否合理。保本/移动止损时:多单止损可≥入场价、空单止损可≤入场价,不得被改回亏损价
@ -1541,7 +1583,15 @@ class PositionManager:
await self.client.cancel_open_algo_orders_by_order_types( await self.client.cancel_open_algo_orders_by_order_types(
symbol, {"STOP_MARKET", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET"} symbol, {"STOP_MARKET", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET"}
) )
logger.info(f"[账号{self.account_id}] {symbol} 已取消旧保护单,准备挂新单") logger.info(
f"[账号{self.account_id}] {symbol} 已取消旧保护单,准备挂新单 [{sync_type}] "
f"条件价: 止损={float(stop_loss):.4f} 止盈={float(take_profit):.4f}"
)
if sync_type == "保本/移动止损同步":
_log_trailing_stop_event(
self.account_id, symbol, "sync_to_exchange",
stop_loss=float(stop_loss), take_profit=float(take_profit), msg="准备挂新单"
)
except Exception as e: except Exception as e:
logger.warning(f"[账号{self.account_id}] {symbol} 取消旧保护单异常: {e},继续尝试挂新单") logger.warning(f"[账号{self.account_id}] {symbol} 取消旧保护单异常: {e},继续尝试挂新单")
@ -1756,7 +1806,10 @@ class PositionManager:
except Exception: except Exception:
pass pass
if sl_order: if sl_order:
logger.info(f"[账号{self.account_id}] {symbol} ✓ 止损单已成功挂到交易所: {sl_order.get('algoId', 'N/A')}") logger.info(
f"[账号{self.account_id}] {symbol} ✓ 止损单已成功挂到交易所: {sl_order.get('algoId', 'N/A')} "
f"触发价={float(stop_loss):.4f}"
)
else: else:
if sl_failed_due_to_gte: if sl_failed_due_to_gte:
logger.warning(f"{symbol} 条件单被拒(持仓未就绪或已平),跳过交易所止损单,将依赖 WebSocket 监控") logger.warning(f"{symbol} 条件单被拒(持仓未就绪或已平),跳过交易所止损单,将依赖 WebSocket 监控")
@ -1873,7 +1926,10 @@ class PositionManager:
except Exception: except Exception:
pass pass
if tp_order: if tp_order:
logger.info(f"[账号{self.account_id}] {symbol} ✓ 止盈单已成功挂到交易所: {tp_order.get('algoId', 'N/A')}") logger.info(
f"[账号{self.account_id}] {symbol} ✓ 止盈单已成功挂到交易所: {tp_order.get('algoId', 'N/A')} "
f"触发价={float(take_profit):.4f}"
)
else: else:
logger.warning(f"{symbol} ⚠️ 止盈单挂单失败将依赖WebSocket监控") logger.warning(f"{symbol} ⚠️ 止盈单挂单失败将依赖WebSocket监控")
@ -1889,10 +1945,15 @@ class PositionManager:
if position_info.get("exchangeSlOrderId") or position_info.get("exchangeTpOrderId"): if position_info.get("exchangeSlOrderId") or position_info.get("exchangeTpOrderId"):
logger.info( logger.info(
f"[账号{self.account_id}] {symbol} 已挂币安保护单: " f"[账号{self.account_id}] {symbol} 已挂币安保护单 [{sync_type}]: "
f"SL={position_info.get('exchangeSlOrderId') or '-'} " f"SL={position_info.get('exchangeSlOrderId') or '-'} 触发价={float(stop_loss):.4f} | "
f"TP={position_info.get('exchangeTpOrderId') or '-'}" f"TP={position_info.get('exchangeTpOrderId') or '-'} 触发价={float(take_profit):.4f}"
) )
if sync_type == "保本/移动止损同步":
_log_trailing_stop_event(
self.account_id, symbol, "sync_to_exchange_ok",
stop_loss=float(stop_loss), take_profit=float(take_profit), msg="已挂币安保护单"
)
logger.info(f"[账号{self.account_id}] {symbol} 止损/止盈同步至交易所完成") logger.info(f"[账号{self.account_id}] {symbol} 止损/止盈同步至交易所完成")
else: else:
logger.warning(f"[账号{self.account_id}] {symbol} 同步结束但未挂上保护单(止损或止盈挂单均失败),将依赖 WebSocket 监控") logger.warning(f"[账号{self.account_id}] {symbol} 同步结束但未挂上保护单(止损或止盈挂单均失败),将依赖 WebSocket 监控")
@ -2041,10 +2102,13 @@ class PositionManager:
position_info['stopLoss'] = breakeven position_info['stopLoss'] = breakeven
position_info['breakevenStopSet'] = True position_info['breakevenStopSet'] = True
logger.info(f"{symbol} [定时检查] 盈利{pnl_percent_margin:.2f}%≥{lock_pct*100:.0f}%,止损已移至含手续费保本价 {breakeven:.4f}") logger.info(f"{symbol} [定时检查] 盈利{pnl_percent_margin:.2f}%≥{lock_pct*100:.0f}%,止损已移至含手续费保本价 {breakeven:.4f}")
_log_trailing_stop_event(self.account_id, symbol, "breakeven_set", breakeven=breakeven, pnl_pct=pnl_percent_margin, source="定时检查")
logger.info(f"{symbol} [定时检查] 尝试将保本止损同步至交易所") logger.info(f"{symbol} [定时检查] 尝试将保本止损同步至交易所")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price)
_log_trailing_stop_event(self.account_id, symbol, "breakeven_sync_ok", breakeven=breakeven, source="定时检查")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "breakeven_sync_fail", breakeven=breakeven, error=str(sync_e), source="定时检查")
logger.warning( logger.warning(
f"{symbol} [定时检查] 同步保本止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"{symbol} [定时检查] 同步保本止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
@ -2058,15 +2122,18 @@ class PositionManager:
f"{symbol} 移动止损激活: 止损移至含手续费保本价 {breakeven:.4f} (入场: {entry_price:.4f}) " f"{symbol} 移动止损激活: 止损移至含手续费保本价 {breakeven:.4f} (入场: {entry_price:.4f}) "
f"(盈利: {pnl_percent_margin:.2f}% of margin)" f"(盈利: {pnl_percent_margin:.2f}% of margin)"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_activated", breakeven=breakeven, pnl_pct=pnl_percent_margin, source="定时检查")
logger.info(f"{symbol} [定时检查] 尝试将移动止损同步至交易所") logger.info(f"{symbol} [定时检查] 尝试将移动止损同步至交易所")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=breakeven, source="定时检查")
logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所") logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=breakeven, error=str(sync_e), source="定时检查")
logger.warning( logger.warning(
f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
) )
else: else:
# 盈利超过阈值后,止损移至保护利润位(基于保证金) # 盈利超过阈值后,止损移至保护利润位(基于保证金)
# 如果已经部分止盈,使用剩余仓位计算 # 如果已经部分止盈,使用剩余仓位计算
@ -2089,14 +2156,17 @@ class PositionManager:
f"(保护{trailing_protect*100:.1f}% of remaining margin = {protect_amount:.4f} USDT, " f"(保护{trailing_protect*100:.1f}% of remaining margin = {protect_amount:.4f} USDT, "
f"剩余数量: {remaining_quantity:.4f})" f"剩余数量: {remaining_quantity:.4f})"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="定时检查-剩余仓位")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=new_stop_loss, source="定时检查")
logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所") logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=new_stop_loss, error=str(sync_e), source="定时检查")
logger.warning( logger.warning(
f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
) )
else: else:
new_stop_loss = entry_price + (remaining_pnl - protect_amount) / remaining_quantity new_stop_loss = entry_price + (remaining_pnl - protect_amount) / remaining_quantity
new_stop_loss = min(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL')) new_stop_loss = min(new_stop_loss, self._breakeven_stop_price(entry_price, 'SELL'))
@ -2108,14 +2178,17 @@ class PositionManager:
f"(保护{trailing_protect*100:.1f}% of remaining margin = {protect_amount:.4f} USDT, " f"(保护{trailing_protect*100:.1f}% of remaining margin = {protect_amount:.4f} USDT, "
f"剩余数量: {remaining_quantity:.4f})" f"剩余数量: {remaining_quantity:.4f})"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="定时检查-剩余仓位")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=new_stop_loss, source="定时检查")
logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所") logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=new_stop_loss, error=str(sync_e), source="定时检查")
logger.warning( logger.warning(
f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
) )
else: else:
# 未部分止盈,使用原始仓位计算;保护金额至少覆盖手续费 # 未部分止盈,使用原始仓位计算;保护金额至少覆盖手续费
protect_amount = max(margin * trailing_protect, self._min_protect_amount_for_fees(margin, leverage)) protect_amount = max(margin * trailing_protect, self._min_protect_amount_for_fees(margin, leverage))
@ -2129,14 +2202,17 @@ class PositionManager:
f"{symbol} 移动止损更新: {new_stop_loss:.4f} " f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)" f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="定时检查")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=new_stop_loss, source="定时检查")
logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所") logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=new_stop_loss, error=str(sync_e), source="定时检查")
logger.warning( logger.warning(
f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
) )
else: else:
# 做空:止损价 = 开仓价 + (当前盈亏 - 保护金额) / 数量 # 做空:止损价 = 开仓价 + (当前盈亏 - 保护金额) / 数量
# 注意:对于做空,止损价应该高于开仓价,所以用加法 # 注意:对于做空,止损价应该高于开仓价,所以用加法
@ -2151,14 +2227,17 @@ class PositionManager:
f"{symbol} 移动止损更新: {new_stop_loss:.4f} " f"{symbol} 移动止损更新: {new_stop_loss:.4f} "
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)" f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="定时检查")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=new_stop_loss, source="定时检查")
logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所") logger.info(f"{symbol} [定时检查] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=new_stop_loss, error=str(sync_e), source="定时检查")
logger.warning( logger.warning(
f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"{symbol} [定时检查] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
) )
# 检查止损(使用更新后的止损价,基于保证金收益比) # 检查止损(使用更新后的止损价,基于保证金收益比)
# ⚠️ 重要:止损检查应该在时间锁之前,止损必须立即执行 # ⚠️ 重要:止损检查应该在时间锁之前,止损必须立即执行
@ -4171,10 +4250,13 @@ class PositionManager:
logger.info( logger.info(
f"[账号{self.account_id}] {symbol} [实时监控] 盈利{pnl_percent_margin:.2f}%≥{lock_pct*100:.0f}%,止损已移至含手续费保本价 {breakeven:.4f}(留住盈利)" f"[账号{self.account_id}] {symbol} [实时监控] 盈利{pnl_percent_margin:.2f}%≥{lock_pct*100:.0f}%,止损已移至含手续费保本价 {breakeven:.4f}(留住盈利)"
) )
_log_trailing_stop_event(self.account_id, symbol, "breakeven_set", breakeven=breakeven, pnl_pct=pnl_percent_margin, source="实时监控")
logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 尝试将保本止损同步至交易所") logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 尝试将保本止损同步至交易所")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float)
_log_trailing_stop_event(self.account_id, symbol, "breakeven_sync_ok", breakeven=breakeven, source="实时监控")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "breakeven_sync_fail", breakeven=breakeven, error=str(sync_e), source="实时监控")
logger.warning( logger.warning(
f"[账号{self.account_id}] {symbol} [实时监控] 同步保本止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"[账号{self.account_id}] {symbol} [实时监控] 同步保本止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
@ -4198,16 +4280,19 @@ class PositionManager:
f"[账号{self.account_id}] {symbol} [实时监控] 移动止损激活: 止损移至保护利润位 {new_stop_loss:.4f} " f"[账号{self.account_id}] {symbol} [实时监控] 移动止损激活: 止损移至保护利润位 {new_stop_loss:.4f} "
f"(盈利: {pnl_percent_margin:.2f}% of margin, 保护: {trailing_protect*100:.1f}% of margin)" f"(盈利: {pnl_percent_margin:.2f}% of margin, 保护: {trailing_protect*100:.1f}% of margin)"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_activated", new_stop_loss=new_stop_loss, pnl_pct=pnl_percent_margin, source="实时监控")
# 同步至交易所:取消原止损单并按新止损价重挂,使移动止损也有交易所保护 # 同步至交易所:取消原止损单并按新止损价重挂,使移动止损也有交易所保护
logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 尝试将移动止损同步至交易所") logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 尝试将移动止损同步至交易所")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=new_stop_loss, source="实时监控")
logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 已同步移动止损至交易所") logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=new_stop_loss, error=str(sync_e), source="实时监控")
logger.warning( logger.warning(
f"[账号{self.account_id}] {symbol} [实时监控] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"[账号{self.account_id}] {symbol} [实时监控] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
) )
else: else:
# ⚠️ 优化:如果分步止盈第一目标已触发,移动止损不再更新剩余仓位的止损价 # ⚠️ 优化:如果分步止盈第一目标已触发,移动止损不再更新剩余仓位的止损价
# 原因分步止盈第一目标触发后剩余50%仓位止损已移至成本价(保本),等待第二目标 # 原因分步止盈第一目标触发后剩余50%仓位止损已移至成本价(保本),等待第二目标
@ -4227,10 +4312,13 @@ class PositionManager:
f"[账号{self.account_id}] {symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} " f"[账号{self.account_id}] {symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)" f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="实时监控")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=new_stop_loss, source="实时监控")
logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 已同步移动止损至交易所") logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=new_stop_loss, error=str(sync_e), source="实时监控")
logger.warning( logger.warning(
f"[账号{self.account_id}] {symbol} [实时监控] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"[账号{self.account_id}] {symbol} [实时监控] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,
@ -4244,10 +4332,13 @@ class PositionManager:
f"[账号{self.account_id}] {symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} " f"[账号{self.account_id}] {symbol} [实时监控] 移动止损更新: {new_stop_loss:.4f} "
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)" f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
) )
_log_trailing_stop_event(self.account_id, symbol, "trailing_update", new_stop_loss=new_stop_loss, source="实时监控")
try: try:
await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float) await self._ensure_exchange_sltp_orders(symbol, position_info, current_price=current_price_float)
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_ok", new_stop_loss=new_stop_loss, source="实时监控")
logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 已同步移动止损至交易所") logger.info(f"[账号{self.account_id}] {symbol} [实时监控] 已同步移动止损至交易所")
except Exception as sync_e: except Exception as sync_e:
_log_trailing_stop_event(self.account_id, symbol, "trailing_sync_fail", new_stop_loss=new_stop_loss, error=str(sync_e), source="实时监控")
logger.warning( logger.warning(
f"[账号{self.account_id}] {symbol} [实时监控] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}", f"[账号{self.account_id}] {symbol} [实时监控] 同步移动止损至交易所失败: {type(sync_e).__name__}: {sync_e}",
exc_info=False, exc_info=False,