# 订单记录入库方式演变说明(为何 12 号下午之前能对上、后来对不上) ## 时间线(按 Git 提交) - **2月12日及之前**:订单能对上一些。 - **2月12日下午**:提交 `0df841c` 只改了止盈比例和配置/前端,**未改入库逻辑**。 - **2月14日**:`3d9f58f`(使用自定义订单号)、`11cd55f`(client_order_id 支持)—— 下单带 `newClientOrderId`,补建逻辑收紧。 - **2月16日**:`5154b49` 引入 **pending 预落库** + UDS 按 `client_order_id` 完善。 - **2月17日**:`415589e` 等增强 UDS/同步;UDS 开仓 FILLED 时**无 clientOrderId 直接 return**,不完善。 ## 12 号下午之前的入库方式(能对上的原因) 1. **没有 pending 预落库** 开仓流程是:REST 下单 → 轮询等待成交 → 成交后**直接** `Trade.create(entry_order_id=order.get("orderId"), client_order_id=order.get("clientOrderId"), ...)`。 2. **完全依赖 REST 返回** - `entry_order_id` 来自 REST 的 `orderId`,一定能拿到。 - `client_order_id` 来自 REST 的 `clientOrderId`,当时未传 `newClientOrderId`,可能是币安自动生成或空。 3. **User Data Stream 不参与开仓落库** 当时 UDS 主要做平仓回写;开仓是否落库只取决于 **position_manager 里 REST 成交后那一次 `Trade.create`**,链路简单,所以容易和币安对上。 ## 后来的改动(导致对不上的可能原因) 1. **2月14日 3d9f58f** - 下单时带 `newClientOrderId`(`SYSTEM_ORDER_ID_PREFIX` + 时间戳)。 - 补建缺失持仓逻辑收紧:只补建「clientOrderId 带系统前缀」或「有止损/止盈单」的仓位;手动单、无前缀单不再自动建记录。 2. **2月16日 5154b49** - **先落 pending**:开仓前 `Trade.create(status="pending", client_order_id=..., entry_order_id=None)`。 - 下单时把 `client_order_id` 传给币安(`new_client_order_id`)。 - 成交后:优先用 **UDS 推送的 clientOrderId** 找到 pending,再 `update_pending_to_filled` 填 `entry_order_id`/价格/数量;若 UDS 未收到或推送里**没有 clientOrderId**,则跳过完善,pending 会一直缺 `entry_order_id`。 - REST 端成交后也有「有 pending 则完善、否则新建」的兜底,但若 REST 超时/异常,就只剩「未完善的 pending」或没记录。 3. **2月17日 415589e** - UDS 开仓 FILLED:**若没有 clientOrderId,直接 return**,不尝试用 orderId 做任何回填。 综合效果: - 一旦 **UDS 断连、丢包或推送里缺少 clientOrderId**,pending 无法被 UDS 完善。 - 若 **REST 端也失败**(超时、异常、进程重启等),就会出现「币安有成交、系统只有 pending 或无记录」的情况,对不上。 ## 已做的改进(本次) 1. **同步接口按当前账号 API 拉取** 使用 `Account.get_credentials(account_id)`,不再用全局 config,多账号/多配置时订单能对到正确账号。 2. **DB 无记录时自动全量** 若该账号在 DB 中没有任何交易记录,同步时会自动按「全量交易对」从币安拉订单并创建/补全记录。 3. **UDS 无 clientOrderId 时用 orderId 兜底** - 新增 `Trade.update_pending_by_entry_order_id(symbol, account_id, order_id, entry_price, quantity)`: - 若 DB 中已有该 `entry_order_id` 则跳过; - 否则在该 symbol+account 下找「status=pending 且 entry_order_id 为空」的记录,**若恰好 1 条**则用本订单号/价格/数量更新。 - 在 `user_data_stream` 中:开仓 FILLED 时若**没有 client_order_id**,不再直接 return,而是先尝试上述兜底;只有兜底也匹配不到唯一 pending 时才仅打 debug 日志。 这样即使 UDS 未带 clientOrderId(或 listenKey 断连导致漏推),只要该 symbol 下只有一条待完善的 pending,仍能用 orderId 补上,减少「币安有、系统没有」的情况。 ## 建议自检 1. **配置** - 当前账号是否已配置 BINANCE_API_KEY / BINANCE_API_SECRET(同步用的是当前选中账号的 API)。 - 若使用「系统单」前缀:`SYSTEM_ORDER_ID_PREFIX` 是否与下单时一致(影响补建和区分系统单)。 2. **对账** - 在前端选好账号后,用「同步订单」勾选「全量同步」、选 7 天或 30 天,先补全历史。 - 再用「校验与币安一致性」接口查看是否还有缺失/不一致。 3. **日志** - 若仍有漏记,可查: - UDS:开仓 FILLED 是否带 `c`(clientOrderId)、是否有「已用 orderId 兜底完善」。 - 同步/补建:是否有「创建新交易记录」或「补全 entry_order_id」的日志。