当前系统订单跟踪存在哪些严重的bug5

订单跟踪严重 Bug 分析

一、订单跟踪链路概览

sequenceDiagram
    participant Exec as Executor
    participant WSM as WebSocketOrderManager
    participant WS as WebSocket
    participant PM as PositionManager
    participant Repo as TradeRepository

    Exec->>WSM: track_order(oid, coin, timeout)
    WSM->>WSM: _timeout_then_verify 线程启动
    Exec->>WSM: wait_for_order(tracking)
    Note over WS: orderUpdates / userFills
    WS->>RealtimeKline: on_message
    RealtimeKline->>WSM: handle_message(msg)
    WSM->>WSM: _on_order_update / _on_user_fill
    WSM->>WSM: result_event.set()
    Exec->>Exec: 更新 order_result,返回
    Exec->>PM: 返回 order_result
    PM->>Repo: save_position + save_order
  • 追踪入口executor._track_limit_order 对限价单调用 track_order + wait_for_order,依赖 WebSocket 的 orderUpdates/userFills 或超时后 HTTP 补查。
  • 消息来源realtime_kline_service_base.on_message 根据 channel in ("orderUpdates", "userFills") 转发给 _ws_order_manager.handle_message
  • 持久化position_manager 在开仓/平仓成功后调用 _repo.save_position_repo.save_order(先 position 后 order)。

二、严重 / 高优先级 Bug

1. 持久化部分写入导致数据不一致(严重)

位置position_manager.py 开仓约 179–183 行、平仓约 537–548 行。

现象:先执行 _repo.save_position(position),再执行 _repo.save_order(..., leg_a/leg_b)。若 save_order 抛异常(如 DB 短暂不可用),position 已写入 DB,订单未写入,导致:

  • 库中存在仓位记录但无对应订单明细;
  • 对账、审计、统计会漏单或报错。

建议

  • 将“写 position + 写 order(s)”放在同一事务中(同一 connection、同一 transaction),任一步失败则整体回滚;或
  • 先写 order(s) 再写 position,并在文档中约定“有 position 必有 order”,便于监控与修复脚本识别“有仓无单”的脏数据。

2. order_id 类型未统一,存在隐蔽风险(高)

位置executor._parse_order_response 约 1133–1140 行;models.OrderResult.order_id 标注为 int | None

现象:Hyperliquid API 返回的 oid 在 JSON 中可能是数字或字符串,代码直接 result.order_id = filled.get("oid") / resting.get("oid"),未做类型归一化。后果:

  • WebSocketOrderManager 内已用 _safe_int_oid / int(oid) 做查找,故 _tracking 查找通常正常;
  • 但若其他地方用 order_result.order_id 做 key、比较或传给 query_order_status 等,在 str/int 混用场景下可能出错或静默行为异常;
  • 类型标注与运行时不一致,增加维护成本。

建议:在解析下单响应时统一将 oid 转为 int(转换失败时记录日志并置为 None),并保证 OrderResult.order_id 始终为 int | None


3. 订单管理器未就绪时订单推送被丢弃(高)

位置realtime_kline_service_base.on_message 约 612–624 行。

现象:当 channel in ("orderUpdates", "userFills") 时,若 _trading_orchestrator._executor._ws_order_manager 为 None 或未就绪,消息被丢弃并只打 warning。可能场景:

  • 服务启动顺序导致 WebSocket 先连上并开始收包,而 executor/order_manager 尚未初始化;
  • 断线重连后,在 verify_pending_orders 执行前已有订单状态推送到达,但此时若存在某种“未就绪”状态,推送仍会被丢弃。

后果:断线期间已成交的订单无法通过 WS 及时结算,只能依赖超时后的 HTTP 补查,用户等待时间变长,或偶发误判为超时。

建议

  • 明确启动顺序,保证在开始接收交易相关 WebSocket 消息前 _ws_order_manager 已创建;
  • 若无法保证,可考虑在“未就绪”时对 orderUpdates/userFills 做有限缓冲(如按 oid 缓存最近 N 条),在 order_manager 就绪后回放一次(需防重放导致重复处理);
  • 或至少在日志中区分“未就绪丢弃”与“正常处理”,便于排查。

4. HTTP 订单状态解析对未知 status 一律视为 TIMEOUT(中高)

位置websocket_order_manager._parse_order_response 约 296–315 行。

现象:仅显式处理 filled / canceled / margincanceled / rejected / open,其余(如交易所返回 partial 或其他新状态)统一返回 OrderStatus.TIMEOUT。若交易所对“部分成交”等返回非 open 且非 filled 的 status,会被误判为超时,进而:

  • 主线程认为订单“超时”,可能触发撤单 + 市价平仓或回滚;
  • 实际订单可能仍在挂单或部分成交,造成逻辑与交易所状态不一致。

建议:查阅交易所文档,对 partial 等已知状态做显式映射(如视为仍 PENDING 或单独状态);对真正未知的 status 再落为 TIMEOUT,并打 warning 带上原始 raw_status,便于后续扩展。


三、中优先级 / 设计层面问题

5. 重连/清理时取消订阅格式与 order 订阅不匹配(中)

位置enhanced_ws_manager 约 800–806 行(强制清理时按 sub_key 构造 unsubscribe 的 subscription)。

现象sub_key(type, coin, interval),取消订阅时构造 {type, coin, interval}。而 orderUpdates/userFills 的订阅格式为 {type, user},无 coin/interval。因此对 order 类频道发出的 unsubscribe 是错误格式,服务端可能无法正确识别,仅起到“本地清理 active_subscriptions”作用。

影响:重连后仍会用 self.subscriptions 里的完整对象重新 subscribe,所以订单推送一般能恢复;主要影响是清理阶段与服务端状态可能不一致,以及未来若依赖“先取消再订阅”的语义时可能出问题。

建议:按订阅类型分支构造 unsubscribe 的 payload(例如对 orderUpdates/userFills/user 使用 type+user,对 candle 等使用 type+coin+interval),或统一用“完整 subscription 对象”作为 key/取消参数,避免只用 (type, coin, interval)。


6. 订单消息与 K 线消息共用同一连接与去重逻辑(中)

位置:订单消息在 message_deduplicator 中已排除(orderUpdates/userFills 不参与去重),但订单与 K 线仍在同一 WebSocket 连接、同一 on_message 中处理。

现象:若 K 线处理阻塞或抛错,可能拖慢或影响订单消息处理(取决于异常是否被吞掉)。当前实现里订单分支在 K 线解析之前且 return,因此影响有限,但架构上订单与高吞吐 K 线混在一起,存在潜在延迟或相互影响风险。

建议:中长期可考虑将订单通道与行情通道分离(例如独立连接或独立 worker),或至少保证订单分支的异常不导致整条消息被跳过且无监控。


四、已确认无问题的设计点

  • result_event 与 _tracking 的配对:所有 _tracking.pop(oid) 的路径都伴随 tracking.result_event.set(),不会造成 wait_for_order 永久阻塞。
  • 同一 oid 多路径结算_resolve_via_http_timeout_then_verifyverify_pending_orders 之间通过二次拿锁和 get(oid) 检查,避免重复结算或状态覆盖。
  • userFills 与 orderUpdates 顺序:先到 userFills 则累计;先到 orderUpdates filled 则用 limitPx 或已累计值,后到的 userFills 进 cache,由 wait_for_order 内 pop 并回填,逻辑一致。
  • 重连后补查WebSocketReconnectedEvent 触发 verify_pending_orders,对当前所有 PENDING 做 HTTP 补查,能弥补断线期间遗漏的成交。

五、建议修复顺序

  1. 优先:修复“position 与 order 持久化”的事务/顺序(Bug 1),避免数据不一致。
  2. :统一 order_id 类型并在解析处归一化为 int(Bug 2);加强“订单管理器未就绪”时的策略与可观测性(Bug 3)。
  3. 中高:扩展 _parse_order_responsepartial 等状态的语义(Bug 4)。
  4. :修正重连/清理时 order 相关订阅的取消格式(Bug 5);视需求评估订单与 K 线通道分离(Bug 6)。

以上为当前代码库下订单跟踪相关的严重与重要 bug 分析及修复建议。

Read more

跑步的技巧(滚动落地)

“滚动落地(rolling contact / rolling foot strike)”不是一种教条式的“脚法”,而是一种 让冲击沿着整只脚、整条后链逐级传递的落地机制。 它的核心不是“你先用哪儿着地”,而是: 你的脚落地之后,冲击是不是像轮子一样滚过去,而不是像锤子一样砸下去。 这就是滚动落地的本质。 一、什么叫“滚动落地”? 你可以把它理解成两种完全不同的落地方式: 1. 砸地(撞击式) 脚像锤子一样拍到地上: * 要么后跟先砸 * 要么前掌先戳 * 冲击集中在一个点 * 一个结构瞬间吃掉大部分载荷 结果就是: * 后跟砸 → 膝盖难受 * 前掌戳 → 前脚掌磨烂 * 都不是长跑友好模式 这叫 撞击式着地(impact strike)。 2. 滚地(滚动式) 脚像轮胎一样“滚”过地面: * 不是某一点硬砸 * 而是外侧中足先轻触 * 再向前滚到前掌 * 最后从大脚趾蹬离

By SHI XIAOLONG

AMI的优越性

世界模型(World Models)的具体例子 如下,我按类型分类,便于理解。每类都附带实际实现、演示效果和应用场景。 1. Yann LeCun / Meta 的 JEPA 系列(最直接对应“世界模型”概念) 这些是 LeCun 主张的非生成式抽象预测世界模型代表。 * I-JEPA(Image JEPA,2023) 输入一张图像,模型把不同区域(context 和 target)编码成抽象表示,然后预测 target 的表示(不在像素级别重建)。 例子:给定一张遮挡了部分物体的图片,模型能预测“被遮挡物体的大致位置和属性”,构建对物体持久性和空间关系的理解。 这是一个“原始世界模型”,能学习物理常识(如物体不会凭空消失)。 * V-JEPA / V-JEPA 2(Video JEPA,

By SHI XIAOLONG

什么是:“世界模型(World Models)”

世界模型(World Models) 是人工智能领域的一个核心概念,尤其在 Yann LeCun 等研究者推动的下一代 AI 架构中占据中心位置。它指的是 AI 系统在内部构建的对现实世界的抽象模拟或内部表示,让机器能够像人类或动物一样“理解”物理世界、预测未来、规划行动。 简单比喻 想象你闭上眼睛也能“看到”房间里的物体会如何移动、碰撞或掉落——这就是你大脑里的世界模型。AI 的世界模型就是类似的“数字孪生”(digital twin)或“内部模拟器”:它不是简单记住数据,而是学习世界的动态、因果关系和物理直觉(如重力、物体持久性、遮挡、因果等)。 为什么需要世界模型? 当前主流的大型语言模型(LLM) 擅长处理文本(统计模式预测),但存在根本局限: * 缺乏对物理世界的真正理解 → 容易“幻觉”、无法可靠规划。 * 样本效率低 → 人类/

By SHI XIAOLONG

K线周期可配置化设计方案

K线周期可配置化设计方案 1. 背景与目标 当前 Beta 套利策略的 K 线周期硬编码为 "1h",分散在多个文件中。需要: 1. 将 K 线周期从 1h 改为 2h 2. 提取为环境变量 BETA_ARB_KLINE_INTERVAL,使其可在 .env 中配置 2. 影响范围分析 2.1 需要修改的文件(共 6 个) 文件 硬编码位置 修改内容 src/trading/config.py BetaArbConfig dataclass 新增 kline_interval 字段,

By SHI XIAOLONG