feat(account, position_manager): 优化持仓同步逻辑与日志记录

在持仓同步功能中,增加了对系统订单前缀的默认处理,确保在无配置时使用默认前缀 "ats_"。同时,调整了日志记录逻辑,明确区分系统单与手动单的补建条件,提升了日志的可读性与准确性。这一改动旨在增强系统的可用性与用户友好性,确保持仓与数据库记录的一致性。
This commit is contained in:
薇薇安 2026-02-25 14:48:31 +08:00
parent 6a9fcddfdc
commit 81747c4eef
3 changed files with 25 additions and 9 deletions

View File

@ -1920,12 +1920,15 @@ async def sync_positions(
or ""
)
system_order_prefix = (system_order_prefix or "").strip()
# 无配置时用默认前缀 ats_与 position_manager 一致,便于补建「系统限价/条件单事后成交」的记录
if not system_order_prefix:
system_order_prefix = "ats_"
except Exception:
pass
system_order_prefix = "ats_"
if missing_in_db:
logger.info(f"发现 {len(missing_in_db)} 个持仓在币安存在但数据库中没有记录: {', '.join(missing_in_db)}")
if system_order_prefix:
logger.info(f"对开仓订单 clientOrderId 前缀为「{system_order_prefix}」的持仓补建(系统单标识")
logger.info(f"对开仓订单 clientOrderId 前缀为「{system_order_prefix}」的持仓补建(系统单;匹配到则不再要求有止损/止盈单")
elif only_recover_when_has_sltp:
logger.info(" → 仅对「存在止损/止盈单」的持仓补建记录(视为系统单),避免手动单误建")
for symbol in missing_in_db:
@ -2022,7 +2025,12 @@ async def sync_positions(
pass
if is_clearly_manual:
continue
elif only_recover_when_has_sltp:
# 已通过系统前缀匹配到开仓订单的,直接补建,不要求有止损/止盈单(系统单一定能对应 DB
is_system_order_by_prefix = bool(
system_order_prefix and client_order_id
and str(client_order_id).strip().startswith(system_order_prefix)
)
if only_recover_when_has_sltp and not is_system_order_by_prefix:
has_sltp = False
try:
normal = await client.get_open_orders(symbol)
@ -2039,7 +2047,7 @@ async def sync_positions(
except Exception as e:
logger.debug(f"检查 {symbol} 止盈止损单失败: {e}")
if not has_sltp:
logger.debug(f" {symbol} 无止损/止盈单,跳过补建(视为非系统单)")
logger.debug(f" {symbol} 无止损/止盈单且未匹配到系统前缀,跳过补建")
continue
if entry_order_id and hasattr(Trade, 'get_by_entry_order_id'):
try:

View File

@ -4,6 +4,15 @@
---
## 〇、常见误解:为什么「持仓 5 单、订单记录只有 1 单」?
- **持仓列表**:数据来自**币安 API**`get_open_positions()`),是交易所上真实存在的持仓,与 DB 无关。
- **订单记录**:数据来自**本系统数据库 `trades` 表**,只有「本系统开仓并成功写库」或「同步/补建」时才会有一条记录。
因此**不是**「持仓存在就一定先在 DB 有了」——恰恰相反:币安上可以有 5 个持仓(本系统开的、手动在 App 开的、其它工具开的,或本系统开了但当时写库失败),而 DB 里只有我们成功写入或补建的那几条,所以订单记录会少于或等于持仓数。要对齐做法:使用**持仓同步**(见下文「补建」)或**同步币安订单**把「币安有仓、DB 无记录」的持仓补建到 DB订单记录就会和持仓一致。
---
## 一、数据模型(与币安对应的关键字段)
| 字段 | 含义 | 与币安对应 |

View File

@ -490,13 +490,12 @@ class PositionManager:
filled_quantity = 0.0
entry_mode_used = "limit-only" if not smart_entry_enabled else ("limit+fallback" if allow_market_fallback else "limit-chase")
# 生成 client_order_id先落库 pendingWS 按 o.c 匹配完善,减少对 REST 同步依赖
# 生成 client_order_id先落库 pendingWS/对账 按 client_order_id 匹配完善,确保限价/条件单事后成交也能对应 DB
prefix = (config.TRADING_CONFIG.get("SYSTEM_ORDER_ID_PREFIX") or "").strip()
client_order_id = None
if prefix:
prefix = prefix or "ats_" # 无配置时用默认前缀,保证系统单始终有 pending 可对账
client_order_id = f"{prefix}_{int(time.time() * 1000)}_{random.randint(0, 0xFFFF):04x}"[:36]
pending_trade_id = None
if DB_AVAILABLE and Trade and client_order_id:
if DB_AVAILABLE and Trade:
try:
pending_trade_id = Trade.create(
symbol=symbol,