在 `trades.py` 中更新 `sync_trades_from_binance` 方法,确保使用当前账号的 API 密钥进行订单同步,并优化了日志记录以反映同步状态。新增自动全量同步逻辑,处理无记录情况下的补全需求。更新 `database/models.py` 中的 `update_pending_by_entry_order_id` 方法,提供兜底机制以完善 pending 记录,确保在缺失 clientOrderId 时仍能更新交易状态。此改动提升了交易记录的完整性与系统的稳定性。
72 lines
4.7 KiB
Markdown
72 lines
4.7 KiB
Markdown
# 订单记录入库方式演变说明(为何 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」的日志。
|