迭代14: 策略tab历史持仓展示(R-016)+ 今日已清仓默认层

- R-016 Q1-Q7: 两个策略 tab title 旁「历史持仓」开关 + 清仓范围筛选(近一周默认/1月/3月/半年/1年)
  - SqliteStore.getHoldingsHistory(strategy_id + closed_at 非空 + sinceMs,closed_at DESC,只读)
  - DataStore 门面透传 + strategy-holdings/history 端点(name 兜底 + 参数校验)
  - 前端: 开关/范围下拉/历史行灰显+「已清仓」徽标/展开复用 R-010(rowKey 唯一化)
- R-016 二轮补充(Q8-Q9 老师拍板): 今日已清仓默认层
  - range=today = 本地自然日 00:00 起(特判零点,不落回溯毫秒档)
  - 当天已清仓的持仓默认恒显示、不受「历史持仓」开关控制(开关只控今天之前)
  - rowsToRender 分层合成 + holdingId 去重;标题计数不含已清仓行;零写路径变更
- 回归: test-r016-history 24/24 + 存量回归全绿
This commit is contained in:
2026-09-07 18:15:07 +08:00
parent ed43ecae39
commit 51c70c48fb
14 changed files with 681 additions and 29 deletions
+63
View File
@@ -0,0 +1,63 @@
# 需求:R-016 策略 tab 历史持仓展示(显示/隐藏已清仓持仓 + 清仓时间范围筛选)
> 登记:2026-09-07 | 来源:老师指令(优化功能需求讨论)| 状态:**已定稿(2026-09-07Q1-Q7 老师拍板)**
> 归属:迭代 14 | 计划:PLAN-015 实现状态:**已实现(2026-09-07,待老师人工验收)**
## 需求描述(老师原始诉求)
**两个策略 tab**(做T / 网格超市)**title 旁边**添加以下功能:
1. **显示/隐藏已清仓的历史持仓**(开关);
2. 显示历史持仓时,**默认显示近一周清仓的持仓**,同时提供 **近 1 个月 / 近 3 个月 / 近半年 / 近 1 年** 几个范围选项。
## 背景
- 策略持仓行 = QMT 快照驱动(R-014),卖出清仓后 QMT 无该持仓 → 幽灵清仓把 strategy_holdings 行转历史(closed_at 非空)→ 策略 tab 当场少一行;
- 典型场景(2026-09-07 实际发生):早盘卖出大连热电 1000 股(做T),约 70 秒后该持仓行从做T tab 消失——当日交易记录还在(R-009 已入库、归属 holding_id=15 正确),但 tab 上锚点不可见;
- 历史数据一直在库(strategy_holdings 全量保留),只是**没有展示入口**;
- R-010 持仓行展开(关联委托汇总)以 holding_id 为锚,历史持仓行天然可复用——历史行展开 = 该轮做T/清仓的完整交易复盘(**本需求的核心目标:追溯该持仓相关的历史操作**,老师 2026-09-07 定调)。
## 讨论记录(2026-09-07Q1-Q7 老师拍板)
| # | 问题 | 结论(老师拍板) |
|---|---|---|
| Q1 | 历史行展示哪些字段? | **按建议**:代码 / 名称(取该 holding 最近关联委托的 name 兜底,无则 —)/ 清仓时间 / 持有天数;实时行情列(现价/涨幅/涨停等)历史行显示 **—**(不参与行情订阅);行展开沿用 R-010 看关联委托;成本价从委托推导本期不做 |
| Q2 | 清仓时份额怎么显示?(closeHolding 现把 shares 置 0 | **显示 0 就好了**(老师改判,否决 AI 的「保留 shares」方案):即使显示清仓时的份额也没多少意义,主要目标是追溯该持仓相关的历史操作;**不改 closeHolding 语义**,历史行份额直接显示 DB 原值(0) |
| Q3 | 排序与视觉区分? | **按建议**:当前持仓在前(维持现状排序),历史行追加在后按清仓时间降序;历史行灰显 + 「已清仓」徽标(含清仓日期);标题计数(N 只)只数当前持仓 |
| Q4 | 开关与范围选择要不要记住偏好? | **按建议**:会话级即可(默认关,进 tab 重置为「只看当前」)——查看历史是临时行为,「策略 tab = 当前持仓」是主语义 |
| Q5 | 范围选项集合? | **按建议**:近一周(默认)/ 近 1 个月 / 近 3 个月 / 近半年 / 近 1 年,共 5 档;语义 = closed_at ∈ [now 范围, now];不加「全部历史」 |
| Q6 | 自定义字段值(R-013 values)在历史行怎么处理? | **按建议**:values 数据随行保留,历史行**只读展示**(无编辑入口;服务端本就拒绝已清仓行写入) |
| Q7 | 接口形态? | **按建议**:新增独立只读端点(strategy-holdings/historyargs: strategyId + range),当前持仓路径(strategy-positions / R-014 快照语义)零改动;前端两份结果合并渲染 |
## 边界(定稿)
**做**:两个策略 tab 的历史持仓开关 + 范围筛选(title 旁按钮区);历史行展示(Q1 字段集 + Q2 份额显示 0)+ 行展开复用 R-010;配套后端历史查询端点(SqliteStore 范围查询 + DataStore 门面 + API)。
**不做**:全部持仓 tab 不加此功能(老师点名两个策略 tab);历史行盈亏统计(R-002 Q4 不做统计原则);清仓方式标记(手动清仓 vs 幽灵自动清仓,数据未区分);历史行实时行情;成本价/收益推导;**不改 closeHolding 存储语义**shares 置 0 维持,Q2);范围记忆/偏好持久化(Q4 会话级);「全部历史」档位。
## 关联观察(上一轮会话遗留,不在本需求范围)
- 交易记录 tab 的归属候选(orders/attribution-candidates)只回**当前持仓**——清仓后当日委托无法再通过下拉关联到对应 holding(2026-09-07 大连热电实际遇到);是否立独立需求(如候选纳入近期清仓持仓)待老师定。
## 二轮补充(2026-09-07,Q8-Q9 老师拍板:今日已清仓默认层)
> 追加定稿记录(不改写 Q1-Q7 首轮定稿;本轮在首轮验收前补充,老师 2026-09-07 人工验收前的诉求收窄「历史持仓关 = 当天已清仓也看不见」的体验缺口)。
**老师原始补充诉求**:两个策略 tab 显示历史持仓的交互需要小的逻辑调整——**当前已清仓的持仓默认也显示**;「历史持仓」开关**不控制当天已清仓的持仓**(历史持仓关 ≠ 当天已清仓也被藏起)。
| # | 问题 | 结论(老师拍板 2026-09-07 |
|---|---|---|
| Q8 | 「当天」的边界口径? | **本地自然日 00:00 起**(今天清仓的始终显示;跨零点后自动归入更早历史,由「历史持仓」开关控制) |
| Q9 | 今日已清仓行的视觉与计数? | **沿用历史行灰显 + 「已清仓」徽标**;标题计数(N 只)仍只算当前持仓,不含已清仓行 |
**定稿语义(相对首轮 Q4「默认关 = 只看当前」的修订)**
- 已清仓行分两层:**L1 今日已清仓**range='today'closed_at ≥ 本地自然日 00:00**默认恒显示**,进 tab 即出现、随持仓重载刷新;**L2 历史范围层**week/month/quarter/halfYear/year,仅今天之前)仍由「历史持仓」开关控制(默认关);
- 交互文案同步收窄:「历史持仓」开关 = 显示/隐藏**今天之前**已清仓的历史持仓(title/提示更新);当天清仓的持仓始终显示;
- 展示(灰显/徽标/行情列 —/份额 0/只读字段/行展开)与计数(不含已清仓行)维持 Q1/Q2/Q3/Q6 不变,两层视觉无差异;
- 实现:range='today' 特判本地自然日零点(不走回溯毫秒档);前端 rowsToRender 在开关关时也追加 L1(按 holdingId 去重 L1∩L2,开启历史范围不重复出两行);零写路径变更维持。
**边界修订**:Q5 档位集语义微调为「**今天之前的**回溯范围」;「开关默认关 = 只看当前」修订为「开关默认关 = 当前持仓 + 今日已清仓」;其余边界(不做全部持仓 tab / 不做统计 / 不改 closeHolding / 会话级不持久化等)不变。
## 验收
`docs/04-迭代记录/14-策略tab历史持仓展示/验收标准.md`
+2
View File
@@ -26,6 +26,8 @@
| R-012 | UI 适配 DSH 主题(浅色 / 深色 / 跟随系统) | 神之一手 UI 适配 DSH 浅色/深色/跟随系统主题:141 处硬编码色值替换为宿主 `--dsw-*` token,随主题自动切换;不自行维护主题偏好(**暂定跟随系统**);涨跌红涨绿跌 → 宿主 state-error/success;仅色值 token 化不动布局。**2026-09-02 定稿(暂定跟随系统)并完成(迭代 10),已归档至 已完成/R-012.md** | 老师指令(2026-09-02 | P1 | 已定稿 | 2026-09-02 | 10-UI主题适配 | **已实现(已归档)** |
| R-013 | 策略自定义字段配置(定义随策略,值落库) | 策略可自定义、可扩展:每个策略在设置页「策略分组」子 tab 配置自定义字段(字段名/类型文本·数字·布尔·枚举/枚举项/单位 unit/默认值,configSchema 随策略定义存 settings);每个持仓行按所属策略的定义存一份键值对值(strategy_holdings 新增 values TEXT(JSON) 列);自定义字段作为持仓表列展示,列显隐/排序每策略独立配置(strategyColumns),单元格点击内联编辑。**2026-09-02 定稿(Q1-Q4 + D6)并完成(迭代 11 验收通过),已归档至 已完成/R-013.md** | 老师指令(2026-09-02 | P1 | 已定稿 | 2026-09-02 | 11-策略自定义字段配置 | **已实现(已归档)** |
| R-014 | 持仓内存快照(服务端 10s 定时同步,请求不再穿透 QMT) | 服务端建全量持仓**内存快照**(不落库):PositionSync 启动预热 + 每 10s 全量拉 QMT → 校验 → 整体替换;同步失败保留上次快照(QMT 抖动不再白屏);空快照双重确认(/health + getAsset 账户身份)才接受为真清仓;快照为空读穿透兜底(当场拉一次并回填);**幽灵持仓自动清仓**:QMT 连续 3 轮(约 30s)消失的 code,本地全部策略当前持仓自动转历史(账户身份守卫:accountId 未知跳过、切换重置跳过;部分减持不触发);strategy-positions / unallocated / summary 三个接口改读快照,前端零改动。**2026-09-02 定稿(内存不落库 / 读穿透兜底 / 幽灵自动清仓 / 同步时间不显示,老师逐项拍板),2026-09-02 完成(回归 34/34 + r013 回归 21/21 + typecheck + build 通过),迭代 12 验收待老师人工确认** | 架构梳理讨论引出 + 老师指令(2026-09-02 | P1 | 已定稿 | 2026-09-02 | 12-持仓内存快照 | 已实现(待验收) |
| R-015 | 盘口数据内存化(QuoteSync/QuoteHub 统一管理)+ 数据同步指示灯 | QuoteSync(取数:prime + 5s REST 刷新 + 涨停跌停按交易日缓存)/ QuoteHub(存查:内存快照 + watch 集合 + 读穿透 + 价格单一入口)替换 MarketFeed/MarketDataHub(方案 A 替换不包壳);WS 通路移除;market_quotes_cache 表退役 DROP;涨停价/跌停价字段(/data/instrument 按交易日缓存不落库);会话头部新增持仓/盘口同步指示灯(绿/黄/灰 + 悬停详情 + 点击即 syncNow+ sync-status 端点(吸收临时诊断 market-stats);策略持仓表行情列扩展(涨停/跌停/今开/最高 4 列,默认隐藏)。**2026-09-02 定稿(五项老师逐项拍板),2026-09-02 完成(test-quote-sync 全绿 + 存量回归 34/34、21/21 + typecheck + build),迭代 13 验收待老师人工确认** | 架构演进讨论引出 + 老师指令(2026-09-02 | P1 | 已定稿 | 2026-09-02 | 13-盘口内存快照 | 已实现(待验收) |
| R-016 | 策略 tab 历史持仓展示(显示/隐藏已清仓持仓 + 清仓时间范围筛选) | 两个策略 tab(做T/网格超市)title 旁添加:① 显示/隐藏已清仓历史持仓的开关;② 显示历史时默认展示近一周清仓的持仓,并提供 近1个月/近3个月/近半年/近1年 范围选项。背景:卖出清仓后幽灵清仓(R-014)把持仓行转历史,策略 tab 当场少行(2026-09-07 大连热电做T卖出实际发生);历史数据一直在库(strategy_holdings closed_at 非空),只缺展示入口;历史行可复用 R-010 行展开做交易复盘。**2026-09-07 定稿(Q1-Q7 老师拍板:Q2 改判「份额显示 0 就好,不改 closeHolding 语义」,其余按 AI 建议;核心目标=追溯该持仓相关的历史操作)**;历史行复用 R-010 展开做交易复盘;新增 strategy-holdings/history 端点,当前持仓路径零改动。**2026-09-07 二轮补充(Q8-Q9 老师拍板):当天(本地自然日 00:00 起)已清仓的持仓默认显示(range='today' 恒显示层),「历史持仓」开关只控制今天之前的历史(历史持仓关≠当天清仓被藏起);层间按 holdingId 去重,计数不含已清仓行维持;零写路径变更维持**。详见 R-016.md | 老师指令(2026-09-07 优化功能需求讨论) | P1 | 已定稿 | 2026-09-07 | 14-策略tab历史持仓展示 | 已实现(待验收) |
## 渐进明细规划素材