From baa8277aeebba182ae133d2017d0eb48f4bdd5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Sat, 14 Feb 2026 23:43:33 +0800 Subject: [PATCH] 1 --- backend/api/routes/account.py | 42 ++++++++++++++++++++++-------- trading_system/position_manager.py | 32 ++++++++++++++--------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/backend/api/routes/account.py b/backend/api/routes/account.py index 9fe3228..1f70bbd 100644 --- a/backend/api/routes/account.py +++ b/backend/api/routes/account.py @@ -1822,20 +1822,40 @@ async def sync_positions( except Exception as e: logger.debug(f"获取 {symbol} 成交记录失败: {e}") client_order_id = None + prefix_matched = False if system_order_prefix: if not entry_order_id: - logger.debug(f" {symbol} 无法获取开仓订单号,跳过补建") - continue - try: - order_info = await client.client.futures_get_order(symbol=symbol, orderId=int(entry_order_id), recvWindow=20000) - cid = (order_info or {}).get("clientOrderId") or "" - client_order_id = cid or None - if not cid.startswith(system_order_prefix): - logger.debug(f" {symbol} 开仓订单 clientOrderId={cid!r} 非系统前缀,跳过补建") + logger.debug(f" {symbol} 无法获取开仓订单号,将用「是否有止损/止盈单」兜底判断") + else: + try: + order_info = await client.client.futures_get_order(symbol=symbol, orderId=int(entry_order_id), recvWindow=20000) + cid = (order_info or {}).get("clientOrderId") or "" + client_order_id = cid or None + if cid.startswith(system_order_prefix): + prefix_matched = True + else: + logger.debug(f" {symbol} 开仓订单 clientOrderId={cid!r} 非系统前缀,将用「是否有止损/止盈单」兜底判断") + except Exception as e: + logger.debug(f" {symbol} 查询开仓订单失败: {e},将用「是否有止损/止盈单」兜底判断") + if not prefix_matched: + has_sltp = False + try: + normal = await client.get_open_orders(symbol) + for o in (normal or []): + if _order_is_sltp(o, "type"): + has_sltp = True + break + if not has_sltp: + algo = await client.futures_get_open_algo_orders(symbol=symbol, algo_type="CONDITIONAL") + for o in (algo or []): + if _order_is_sltp(o, "orderType"): + has_sltp = True + break + except Exception as e: + logger.debug(f"检查 {symbol} 止盈止损单失败: {e}") + if only_recover_when_has_sltp and not has_sltp: + logger.debug(f" {symbol} 未匹配系统前缀且无止损/止盈单,跳过补建") continue - except Exception as e: - logger.debug(f" {symbol} 查询开仓订单失败: {e},跳过补建") - continue elif only_recover_when_has_sltp: has_sltp = False try: diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index ab24cff..ac29f30 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -2863,7 +2863,10 @@ class PositionManager: if sync_recover: system_order_prefix = (config.TRADING_CONFIG.get("SYSTEM_ORDER_ID_PREFIX") or "").strip() if system_order_prefix: - logger.info(f" → 补建「系统单」记录(仅当开仓订单 clientOrderId 前缀为 {system_order_prefix!r} 时创建)") + logger.info( + f" → 补建「系统单」记录:开仓订单 clientOrderId 前缀为 {system_order_prefix!r} 时创建;" + "未匹配前缀时若有止损/止盈单也补建(便于历史单/监控一致)" + ) else: logger.info(" → 补建「系统单」记录(仅当存在止损/止盈单时创建,避免手动单误建)" if sync_recover_only_has_sltp else " → 补建缺失持仓记录") for symbol in missing_in_db: @@ -2889,19 +2892,24 @@ class PositionManager: except Exception: pass client_order_id_sync = None + prefix_matched = False # 是否通过 clientOrderId 前缀确认为系统单 if system_order_prefix: if not entry_order_id: - logger.debug(f" {symbol} 无法获取开仓订单号,跳过补建") - continue - try: - order_info = await self.client.client.futures_get_order(symbol=symbol, orderId=int(entry_order_id), recvWindow=20000) - cid = (order_info or {}).get("clientOrderId") or "" - client_order_id_sync = cid or None - if not cid.startswith(system_order_prefix): - logger.debug(f" {symbol} 开仓订单 clientOrderId={cid!r} 非系统前缀,跳过补建") - continue - except Exception as e: - logger.debug(f" {symbol} 查询开仓订单失败: {e},跳过补建") + logger.debug(f" {symbol} 无法获取开仓订单号,将用「是否有止损/止盈单」兜底判断") + else: + try: + order_info = await self.client.client.futures_get_order(symbol=symbol, orderId=int(entry_order_id), recvWindow=20000) + cid = (order_info or {}).get("clientOrderId") or "" + client_order_id_sync = cid or None + if cid.startswith(system_order_prefix): + prefix_matched = True + else: + logger.debug(f" {symbol} 开仓订单 clientOrderId={cid!r} 非系统前缀,将用「是否有止损/止盈单」兜底判断") + except Exception as e: + logger.debug(f" {symbol} 查询开仓订单失败: {e},将用「是否有止损/止盈单」兜底判断") + # 未通过前缀确认时:若有止损/止盈单则仍补建(历史单或前缀未写入时也能被监控) + if not prefix_matched and sync_recover_only_has_sltp and not (await _symbol_has_sltp(symbol)): + logger.debug(f" {symbol} 未匹配系统前缀且无止损/止盈单,跳过补建") continue elif sync_recover_only_has_sltp and not (await _symbol_has_sltp(symbol)): logger.debug(f" {symbol} 无止损/止盈单,跳过补建")