Files
zhixing-system/.zcode/plans/plan-sess_55e3d246-e875-4283-bdfc-929f8f26a73f.md
T
yuxuanhui 7f93d6b0f5 feat(sector_radar): enhance sector radar functionality with active moneyflow and detailed metrics
- Introduced ActiveMoneyflowSource to fetch optional active-order flow, enhancing the sector radar's data capabilities.
- Updated StockFactRecord and DailyAggregateRecord to include pct_change and active_buy_net_amount_yuan for improved financial insights.
- Modified the build process to incorporate active moneyflow data without invalidating main rankings on failure.
- Enhanced the HTTP API to return detailed sector history and metrics, including pct_change and active buy metrics for members.
- Updated tests to validate the new functionality and ensure data integrity across various scenarios.
2026-09-06 16:06:17 +08:00

5.3 KiB
Raw Blame History

选股页面迭代:上搜索 + 左列表/右详情布局 & 板块筛选

现状与关键结论

  • 布局:selection-results-workbench.tsx 目前是左右两栏 grid(左 320px 筛选+列表 / 右详情),筛选栏嵌在左栏顶部。
  • 板块数据:选股结果表(selection_run_item)没有板块字段;板块归属在 sector_radar_membership 表,现有 membership 接口只支持单股查询。板块聚合必须由后端新增(前端逐股请求既慢又只覆盖已加载分页,计数不准)。
  • 已确认口径(用户未答,按推荐执行):概念板块(sector_type='concept',与详情面板"板块"标签一致),单选;接口保留 sector_type 参数,后续扩展行业零成本。排序 = 按 stock_count 倒序(选项旁展示数量)。

一、后端(zhixing-server)

遵循 bounded-context-first(ADR 0001):selection 不直接 join sector_radar 表,通过应用层端口调用 sector_radar 的读服务。

  1. sector_radar 模块(application/read.py + infrastructure/postgres.py):
    • 仓储新增两个只读方法(复用已有的 get_last_good_publication 解析快照日):
      • load_sector_counts(stock_codes, snapshot_date, sector_type):SELECT sector_code, sector_name, COUNT(*) FROM sector_radar_membership WHERE stock_code = ANY(%s) AND trade_date = %s AND sector_type = %s AND membership_status='available' GROUP BY 1,2
      • load_sector_member_codes(snapshot_date, sector_code, sector_type):返回该板块成员股票代码列表
    • 读服务 ReadSectorRadar 新增:sector_counts(stock_codes, trade_date, sector_type)(内部解析 last-good publication,返回按 stock_count 降序、名称升序)和 sector_member_codes(trade_date, sector_code, sector_type)。
  2. selection 模块:
    • domain/runs.py:SelectionResultQuery 增加 sector: str | None;新增 SelectionSectorCount(sector_code, sector_name, stock_count) 值对象;定义端口协议 SectorMembershipReader(sector_counts / sector_member_codes 两个方法)。
    • application/run.py:新增 list_sector_counts(strategy, target_trade_date, sector_type) —— 取 latest run,收集 status='selected' AND signal_count>0 的 ts_code,调端口聚合;get_latest/get 结果查询在 query.sector 有值时先调端口取成员代码,空则直接返回空页,否则把代码数组传入仓储。
    • infrastructure/postgres_runs.py:_stock_filter 增加子句 item.ts_code = ANY(%s)(参数由应用层传入)。
    • presentation/http.py:
      • 新端点 GET /api/v1/selection/sectors?strategy=&target_trade_date=&sector_type= → { sector_type, snapshot_trade_date, sectors: [{sector_code, sector_name, stock_count}] }
      • GET /results 与 GET /runs/{id} 增加 sector query 参数校验(去空格、限长)。
    • 组合根(router/依赖装配处)把 sector_radar 的读服务适配为 selection 的端口注入。
  3. 测试:tests/unit/sector_radar/(新仓储方法)、tests/unit/selection/test_postgres_runs.py(sector 过滤、ANY 数组、空成员空页)、tests/test_selection_http.py(新端点契约 + results 带 sector)。跑 ./dev.sh check(ruff/pyright/pytest)。

二、前端(zhixing-web)

  1. 布局重构 selection-results-workbench.tsx:
    • 外层改为 flex flex-col:顶部一个全宽 section 放搜索栏(关键词 / 信号分类 / 板块(新增) / 排序 / 筛选结果计数),带 rounded-md border bg-card 与现有一致;
    • 下方 md:grid md:grid-cols-[320px_minmax(0,1fr)] 左列表右详情;移动端纵向堆叠为 搜索 → 列表 → 详情。
  2. 类型与 API(selection.types.ts / selection.api.ts):新增 SelectionSectorAggregate;SelectionResultsQuery 加 sector?;getSelectionResultSectors();buildSelectionQueryParams 带 sector。
  3. 查询层(selection.query.ts):useSelectionResultSectors(key:strategy+date,结果就绪后启用);selectionResultsQueryKey/selectionRunQueryKey 加入 sector 使筛选变化触发重新请求。
  4. 路由(routes/route-tree.tsx):selectionRoute validateSearch 增加 sector(string,限长,默认 undefined)。
  5. 页面接线(selection-results-page.tsx):把 URL 中的 sector 传入 useSelectionResults;页面层调用 useSelectionResultSectors 并把聚合结果传给 workbench。
  6. workbench 板块下拉:选项 = "全部板块" + 聚合数据,item 渲染 名称 + 数量徽标(数量 tabular-nums,倒序由后端保证);选择写 URL;聚合加载后若当前 sector 不在列表中(如切换策略/日期)自动重置为全部;板块无数据时下拉仅剩"全部板块"并禁用。

三、执行方式

  • 按仓库 Trellis 工作流建任务目录并加载 .trellis/spec/backend(selection.md 契约:查询不触发重算、错误矩阵等)与前端规范后再动手;先后端(接口+测试)再前端接线,最后 ./dev.sh check + 前端 lint/tsc 全量质量门禁。
  • 语义说明:板块数量 = 当次 run 全部选中股票中归属该板块的数量(不随关键词/信号分类变化);列表"筛选结果 N 只" = 包含板块在内的全部过滤叠加后的 stocks_total。