Files
one_divine_lot/docs/05-需求池/已完成/R-018.md
T

7.9 KiB
Raw Blame History

需求:R-018 交易关联驱动持仓份额动态调整(归属 = 账本写操作)

登记:2026-09-08 来源:老师指令(2026-09-08 新优化需求讨论)| 需求状态:已完成 归档日期:2026-09-08 | 实现迭代:16-交易关联驱动持仓份额动态调整(验收通过 2026-09-08) 讨论记录索引:R-018.md 正文(Q1-Q5/R1-R7 + 数据域分界 + T2/T3);实现细节见 04-迭代记录/16-交易关联驱动持仓份额动态调整/ 归档路径:本文件已移入 05-需求池/已完成/

迭代状态标记:已定稿(2026-09-08)→ 已实现(迭代 16)→ 已归档(验收通过 2026-09-08,口径=自动化为主体 + 只读走查 + 真实使用顺带确认)

需求描述(一句话)

交易记录出发给委托关联策略/持仓时,自动同步调整该策略下持仓的份额(关联即账本写操作),支持一笔委托拆多段分配给不同策略;取消/改归属时做逆操作回滚份额;账本生命周期只由关联交易 + 手动份额操作驱动,同步机制不写账本。

〇、数据域分界(最根本前提,2026-09-08 老师拍板)

「全部持仓」= 对账单域:唯一数据源 = PositionSyncQMT 快照,10s 内存同步,整体替换)。包括幽灵清仓在内的一切同步机制只作用于对账单域,QMT 说了算(老师原话:幽灵清仓本就是一个同步机制,不可以让幽灵把爪子伸太长)。

「策略持仓」= 账本域(strategy_holdings:写操作只来自两条通道——

  1. 交易关联分配器(本需求新增):建仓 / 加仓 / 减仓 / 清仓 / 作废;
  2. 手动份额操作(+ 添加持仓 / 移出 / 全部移入):无交易来源时的兜底通道(Q3:保留现在的建仓逻辑;份额以 QMT 持仓信息为基础创建,受「已分配 ≤ 总持仓」校验)。

既有行为变更:R-014 定稿的「幽灵自动清仓」(连续 3 轮消失 → closeHolding 本地全部策略当前持仓)不再写 strategy_holdings;账本行转历史只由「卖出单关联 → reduceShares 归 0 → closeHolding」产生。影响既有定稿:技术约束-017(幽灵清仓条款)、产品约束-011、R-014、迭代 12(已实现待验收)需修订;PositionSync 删减幽灵清仓逻辑(变更理由 = 本次讨论,写入变更记录)。

背景与现状

  1. QMT 实盘持仓(对账单):PositionSync 10s 内存快照,真实 volume/price(技术约束-017);
  2. 本地策略账本 strategy_holdingsshares + 生命周期(open/add/reduce/close),此前靠手动份额操作维护;账本 ≠ 对账单(R-014:holding_id 是交易锚点,不掺易变快照);
  3. 交易归属 trade_orders.strategy_id/holding_id:手动设置(R-009/R-017),只做过滤/展示/追溯,不改数量——本需求改变这一点。

展示行关系(防误解):策略持仓 tab 当前持仓行 = QMT 快照 ∩ 账本 shares>0(行由对账单驱动、份额由账本驱动)。卖出全清 → QMT 无此 code → 展示行随快照消失(≤10s,与幽灵清仓无关);此时账本行仍为当前持仓(closed_at NULL),作为待关联锚点保留,直到卖出单被关联。

讨论记录(2026-09-08

# 决策点 结论(老师拍板)
1 归属候选按什么给?(Q1 策略级下拉,不做预先判断(有无持仓/历史持仓),指向动作发生后按目标策略当时的活动持仓状态现场判定
2 驱动量基准?(Q4 已成交量(撤单/废单不动账)
3 交互模型?(R4 统一分配器) 不分买卖两套流程:一笔委托已成交量可拆 0..N 段(策略×量);待分配余额 = 成交量 − 已分配段和;默认输入 = 余额全量可改小;允许部分关联(剩余保留「未关联」醒目提示);买入卖出均可拆多段
4 买入关联动作?(原始第 2 条) 该策略有活动持仓 → addShares 加仓;无活动持仓(含曾有历史/作废行)→ openHolding新仓(不复活旧行;Q5
5 卖出关联动作?(原始第 3 条) 活动仓 ≥ 段量 → reduceShares,归 0 → closeHolding;活动仓 < 段量 → 自动截断段量=可容纳量归零清仓,余额保留继续分配;该策略无活动持仓 → 关联失败提示(R1)
6 撤段逆操作?(R3,粒度=段) 撤建仓买入段 → 持仓作废(新增第三态,非 closeHolding,不产生假清仓历史);撤加仓买入段 → reduceShares 减回,归 0 且无真实卖出 → 作废;撤卖出段 → 恢复活动仓 + 份额加回(撤销语义,区别于 Q5 新买入不接旧仓)
7 改归属语义? 撤旧段 + 加新段,原子;撤卖出段若该 holding 已被真实卖出(非本单所致)无法恢复 → 提示不可撤
8 数据域分界?(本轮核心) 幽灵清仓等同步机制只作用于对账单域;策略持仓写操作只来自交易关联 + 手动份额操作
9 T1 卖出关联 vs 幽灵清仓时序竞态 关闭:幽灵不写账本 → 卖出后账本行保留为待关联锚点,无 30s 竞态
10 T2 R-0177 天清仓候选) 退役确认:新时序下清仓发生在卖出单关联之后,不存在「系统先清、用户后补」场景,候选回归「当前持仓 + 未关联」;R-017 的 holdingId 键控/占位安全逻辑保留
11 T3 漏关联兜底 软提示确认:检测「账本有活动行 + QMT 快照无此 code」时提示老师去关联/移出;不自动写账本(不违背分界)

核心规则汇总

触发 判定 动作
买入段 该策略该 code 有活动持仓 addShares(加仓,量=段量)
买入段 无活动持仓(含曾有历史/作废行) openHolding 建新仓(不复活旧行)
卖出段 活动仓 ≥ 段量 reduceShares;归 0 → closeHolding(账本转历史唯一途径)
卖出段 活动仓 < 段量 自动截断:段量=可容纳量 → 归零清仓,余额保留继续分配
卖出段 该策略无活动持仓 关联失败提示

撤段逆操作:撤建仓买入 → 持仓作废(第三态);撤加仓买入 → 减回归 0 作废;撤卖出 → 恢复活动仓 + 份额加回。改归属 = 撤旧段 + 加新段(原子)。

存储 / 模型调整方向

  1. holding 第三态strategy_holdings 增加作废标记(如 void_at);活动 = closed_at IS NULL AND void_at IS NULL;作废行不进 R-016 历史「已清仓」层,保留数据可追溯;活动唯一索引(同策略同 code)收窄至两态皆空;
  2. 归属单列 → 分段表:新表(如 trade_order_attributionsorder_id → strategy_id/holding_id/volume/direction/created_at),一笔委托 N 段;R-010 by-holding 与 R-009 history 策略过滤改经段表 join(同一单可出现在多个 holding 展开里);trade_orders 原两列退役或降级为「主归属」快照,已有单组归属迁移为第一段;
  3. 软提示(T3:账本有活动行 + QMT 快照无此 code 时的可见性提示(不动账本)。

边界

:幽灵清仓账本侧退役(PositionSync 删幽灵清仓逻辑)+ 策略级候选 + 统一份额分配器(拆段/余额)+ 买卖份额联动 + 撤段逆操作(含作废第三态)+ 归属分段存储 + 查询/展示适配 + R-017 7 天候选退役(holdingId 键控/占位保留)+ 漏关联软提示 + 回归。

不做:自动归属推导仍不暴露(可另议);全部持仓 tab / 未分配 tab 份额联动 UI;跨策略「未分配余额」自动兜底;账本写操作自动化兜底(软提示不自动改账本)。

验收

见规划后的迭代验收标准(本需求涉及既有已实现功能变更:迭代 12 幽灵清仓语义、迭代 15 R-017 退役,验收需含存量回归)。