chore(task): archive 08-27-onechartlab-research

This commit is contained in:
yuxuanhui
2026-09-01 11:16:57 +08:00
parent 5f34be5395
commit ff028912e6
9 changed files with 2 additions and 2 deletions
@@ -0,0 +1,11 @@
{"file":"CONTEXT.md","reason":"检查两份报告对历史可复现、选股信号、数据时点和投资建议边界的措辞是否一致。"}
{"file":"docs/adr/0003-postgresql-as-market-data-store.md","reason":"检查复现建议是否清楚区分外部页面数据与本仓库已有市场数据事实源。"}
{"file":"docs/adr/0004-tushare-six-year-snapshot-sync.md","reason":"检查时间窗口、数据修订和前视风险说明是否足以支持历史复现。"}
{"file":"docs/adr/0005-selection-formula-semantics-and-independent-subsignals.md","reason":"检查报告是否区分规则语义、实现证据、作者自述和推断。"}
{"file":".trellis/tasks/08-27-onechartlab-research/prd.md","reason":"逐条核对两份独立报告、复现深度、证据定位和范围边界的验收条件。"}
{"file":".trellis/tasks/08-27-onechartlab-research/research/sector-capital-radar-evidence.md","reason":"核对板块报告的已确认事实、推断边界和排名复算结果。"}
{"file":".trellis/tasks/08-27-onechartlab-research/research/macro-timing-evidence.md","reason":"核对宏观报告的阈值、状态、贡献恒等式和核心公式缺口。"}
{"file": ".trellis/spec/frontend/index.md", "reason": "核对本轮前端实现是否符合项目分层和门禁。"}
{"file": ".trellis/spec/frontend/hook-guidelines.md", "reason": "核对无限查询、query key、取消信号和服务器状态归属。"}
{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "核对滚动表格、状态提示、语义和可访问性。"}
{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "核对测试覆盖以及 format、lint、typecheck、test、build 结果。"}
@@ -0,0 +1,42 @@
# OneChartLab 技术调研设计
## 边界与交付
本任务分析公开可访问的 OneChartLab 页面、前端资源和浏览器请求,不修改产品代码,也不绕过任何访问控制。最终产出两份独立报告:`docs/research/onechartlab-sector-capital-radar.md` 与 `docs/research/onechartlab-macro-timing.md`。原始观察、接口样本和推断过程写入 `.trellis/tasks/08-27-onechartlab-research/research/`,作为报告的工作底稿。作者视频证据待用户提供可访问环境后补充。
## 调研分流
本轮调研拆成两个可并行证据流:板块资金雷达页面和宏观择时页面。每个证据流由一次性研究子代理形成一份 Markdown 底稿;主会话负责浏览器交互核验、关键出处抽查、跨来源冲突处理、技术判断和两份最终报告写作。子代理只做探索,不负责最终结论。作者视频作为后续独立证据流,待用户提供可访问环境后再执行。
## 证据模型
每条关键结论按以下状态标注:
1. `已确认`:可由页面文本、公开脚本、接口响应或可重复交互直接验证。
2. `作者自述`:来自作者视频或其他第一方表达,但未必等同于当前实现。
3. `合理推断`:由多个公开事实推导,必须写出推断链并给出高、中、低置信度。
4. `无法确认`:公开证据不足,说明缺口与最小验证办法,不补造参数。
页面当前行为优先于视频中的历史描述;公开实现证据优先于营销文案;不同来源冲突时并列呈现,不强行合并。
## 数据与分析链路
对每个模块沿同一条复现链路分析:用户问题与输出语义、页面状态与交互、数据来源与请求结构、字段和时间粒度、预处理与派生指标、排序/打分/阈值或状态机、信号刷新与历史切换、异常和缺失数据处理。能确认公式时给出公式或等价伪代码;只能确认输入输出时给出候选机制、排除依据和验证实验。
板块资金雷达重点检查板块分类口径、资金/价格/成交活跃度输入、横截面归一化与象限或雷达映射、排名变化和时间窗口。宏观择时重点检查宏观/市场输入、风险状态定义、信号切换阈值、滞后与确认机制、资产映射和发布日期前视风险。
## 取证方式与兼容边界
优先使用真实浏览器观察 DOM、交互和网络请求,再检查公开静态资源及必要的只读 HTTP 响应。作者视频当前明确暂缓,本轮不继续尝试访问或转述。不得提交 cookie、token、个人账号信息或大体积媒体文件。
## 验证与回滚
最终检查逐条核对 PRD 验收标准、报告内引用的可访问性、事实/推断分级、两模块的一致术语和复现说明完整性。报告是新增 Markdown 文件,回滚只需移除新增报告和任务底稿,不影响运行时系统。
## 板块排名页交互迭代
排名接口继续沿用现有 `page` / `page_size` 服务端契约,前端 query 层新增无限查询封装,以首屏页为起点,根据已加载条数和响应 `total` 推导下一页。页面只消费 React Query 管理的分页集合,不把服务端响应复制到 Zustand 或组件本地状态;筛选条件参与 query key,条件变化自然切换到新的首批数据。
表格自身保持唯一纵向滚动容器和 sticky 表头,在滚动位置接近底部时调用 `fetchNextPage`。加载下一批时在表格底部提供紧凑状态,加载失败时保留已加载行并提供可重试操作,全部加载后不显示传统页码或每页条数控制。
移除 `RadarStatusSummary` 及其静态标题、免责声明、版本和发布元数据块。部分发布、后台刷新、刷新失败、首次加载失败和无数据仍属于操作性状态,继续以紧凑提示或状态容器呈现,不删除关键异常反馈。
@@ -0,0 +1,11 @@
{"file":"CONTEXT.md","reason":"保持历史可复现分析、信号解释和非收益承诺等现有领域语义,并识别潜在前视偏差。"}
{"file":"docs/adr/0003-postgresql-as-market-data-store.md","reason":"理解本仓库日线数据、qfq 口径和当前股票池边界,避免把外部模块假设直接当成本项目事实。"}
{"file":"docs/adr/0004-tushare-six-year-snapshot-sync.md","reason":"核对日频数据、历史修订、覆盖率和时间窗口对后续复现的约束。"}
{"file":"docs/adr/0005-selection-formula-semantics-and-independent-subsignals.md","reason":"报告应区分公式语义、实现证据和独立信号,不把旧输出或作者表述当作当前算法。"}
{"file":".trellis/tasks/08-27-onechartlab-research/design.md","reason":"提供证据等级、两路页面调研分工、视频暂缓边界、复现链路和访问限制。"}
{"file":".trellis/tasks/08-27-onechartlab-research/research/sector-capital-radar-evidence.md","reason":"提供板块页面、公开分片、排名算法、失败边界和主会话复算证据。"}
{"file":".trellis/tasks/08-27-onechartlab-research/research/macro-timing-evidence.md","reason":"提供宏观页面、状态/贡献协议、阈值、证据缺口和主会话复算证据。"}
{"file": ".trellis/spec/frontend/index.md", "reason": "板块资金雷达页面是 React/TanStack Query 前端改动,需遵守前端目录、交互和质量门禁。"}
{"file": ".trellis/spec/frontend/hook-guidelines.md", "reason": "无限列表继续由 TanStack Query 管理服务端分页和取消信号。"}
{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "表格滚动、状态提示和控件需遵守现有组件、Tailwind 与可访问性约定。"}
{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "实现后需更新行为测试并通过前端质量命令。"}
@@ -0,0 +1,45 @@
# OneChartLab 技术调研执行计划
## 执行清单
- [x] 建立 `research/` 工作底稿目录,分别派发板块资金雷达和宏观择时两个一次性研究子代理;每个子代理只写自己的证据文件,并返回 URL、资源名、字段或关键原文。
- [x] 尝试使用真实浏览器核验两个页面;连接被目标站点关闭后,按风险边界改用公开 HTML、脚本和 JSON 响应核验可见控件、图表逻辑、时间切换与加载/错误行为,并在报告中记录限制。
- [x] 只读检查页面 HTML、公开 JavaScript、静态资源和网络请求,识别接口、字段、数据粒度、更新频率以及前后端计算边界;保存最小必要样本,不保存凭据或无关个人数据。
- [x] 在两份报告中记录作者视频证据暂缓及其影响,不在用户提供可访问环境前继续尝试该路径。
- [x] 对两路页面底稿进行出处抽查和交叉验证,建立事实、作者自述、合理推断、无法确认四级证据表,并显式记录冲突。
- [x] 编写 `docs/research/onechartlab-sector-capital-radar.md`,覆盖输入、加工链路、排序/打分/映射、输出信号、更新和异常边界、复现伪代码及证据置信度。
- [x] 编写 `docs/research/onechartlab-macro-timing.md`,覆盖输入、状态定义、阈值/状态机、滞后与前视风险、资产解释、复现伪代码及证据置信度。
- [x] 执行最终内容检查,确认每条关键技术结论有出处或推断标签,两份报告可以独立阅读且不包含收益承诺或未经确认的精确参数。
- [x] 在 sector radar query 层加入基于现有分页接口的无限查询,并用单元测试覆盖 query key、取消信号和下一页判定。
- [x] 将板块排名表改为滚动接近底部时加载下一页,移除共享分页器接入,确保筛选变化时列表重置且下一批失败不会清空已加载行。
- [x] 删除 `RadarStatusSummary` 大块描述内容,把部分发布等必要状态保留为紧凑提示,并更新页面行为测试。
- [x] 运行前端 format、lint、typecheck、相关 Vitest、完整测试与 build,随后进行可见页面检查。
## 验证命令与人工检查
```bash
test -s docs/research/onechartlab-sector-capital-radar.md
test -s docs/research/onechartlab-macro-timing.md
rg -n "已确认|作者自述|合理推断|无法确认" docs/research/onechartlab-*.md
rg -n "https?://|时间点|接口|字段|伪代码|局限" docs/research/onechartlab-*.md
git diff --check
```
人工核对报告中的关键 URL 和公开请求字段,检查证据等级是否与正文措辞一致,并确认视频暂缓状态及其影响已写清楚。
页面迭代额外执行:
```bash
cd zhixing-web
pnpm exec vitest run src/features/sector-radar/api/sector-radar.query.test.ts src/features/sector-radar/pages/sector-radar-page.test.tsx
pnpm check
pnpm build
```
## 风险与停止条件
如果网站需要绕过登录、付费、验证码、地域限制或反爬机制才能继续,停止该取证路径并记录缺口。若压缩/混淆脚本只能支持候选实现而不能证明算法,降级为推断。若公开数据只给出最终分值,报告提供可实施的验证实验,而不虚构原始公式。
## 回滚点
本任务不改产品代码。任何过程性抓取文件都限制在任务 `research/` 下;最终报告写入 `docs/research/`。出现敏感信息或无关个人数据时立即停止使用并从交付物中剔除。
@@ -0,0 +1,48 @@
# OneChartLab 板块资金雷达与宏观择时技术调研
## Goal
基于公开可访问的页面、网络请求、前端资源及作者公开视频,分别还原 OneChartLab「板块资金雷达」和「宏观择时」模块的产品逻辑与可验证技术机制,并进一步整理复现所需的 Tushare 数据采购与采集契约,形成三份证据可追溯、能够指导后续复现实现的中文技术调研报告。
调研的用户价值是区分页面明确展示的事实、可由公开证据推导的实现逻辑和仍无法确认的假设,避免把界面观感或作者观点误写成已证实的算法细节。
## Background
- 调研对象为 `https://onechartlab.com/`(板块资金雷达)和 `https://onechartlab.com/macro/`(宏观择时)。
- 补充材料为作者发布在 `https://b23.tv/IJRk8y2` 的视频;页面与公开音视频流现已可访问,视频没有公开字幕,本轮使用音轨转写与画面抽帧补充作者自述证据。
- 交付物为两份模块技术调研报告和一份 Tushare 数据需求研究文档,而不是产品代码、投资策略实现或投资建议。
## Requirements
- 分别描述每个模块的目标用户问题、界面信息架构、指标或信号含义、状态变化、交互流程和结果解读方式。
- 检查公开页面的 HTML、脚本、静态资源和浏览器网络请求,在不绕过登录、付费、验证码或访问控制的前提下,识别前端数据结构、接口、更新频率及计算发生位置。
- 分析指标构造、分层/排序/打分、阈值、择时状态机、信号确认与切换等核心逻辑;无法从公开证据确认时,明确标注为推测并给出推断链和置信度。
- 补充作者对设计目标、市场假设、指标选择、使用方法和限制的观点,并把视频自述与页面代码、公开数据复算结果分开标注和交叉验证。
- 每份报告独立成篇,包含结论摘要、模块拆解、数据与计算链路、信号逻辑、证据与置信度、局限及可复现建议。
- 复现说明应尽量覆盖输入字段、数据粒度、时间窗口、指标公式或伪代码、归一化/排序/打分、阈值、状态机、更新时点和异常边界;证据不足时不得伪造精确参数。
- 引用可定位到 URL、资源名、请求字段、页面文本、视频时间点或仓库文件的证据;不得将未验证信息陈述为事实。
- 报告使用简体中文,代码标识符、字段名、接口和路径保持原样。
- 新增 Tushare 数据需求文档,按模块列出必需、推荐和可选接口,覆盖用途、调用粒度、输入参数、输出字段、业务主键、更新频率、历史深度、积分/权限、落库与 point-in-time 要求,并把作者/页面暴露的接口事实与官方文档能力分开标注。
- 最终交付路径为 `docs/research/onechartlab-sector-capital-radar.md`、`docs/research/onechartlab-macro-timing.md` 和 `docs/research/onechartlab-tushare-data-requirements.md`;过程证据保存在本任务的 `research/` 目录。
## Acceptance Criteria
- [x] 生成两份独立的 Markdown 技术调研报告,分别覆盖「板块资金雷达」和「宏观择时」。
- [x] 每份报告都明确回答模块解决什么问题、输入数据是什么、如何加工、输出信号是什么、用户如何解释以及有哪些已知限制。
- [x] 关键结论附有可追溯证据,并区分“页面/代码/请求已确认”“作者自述”“合理推断”“无法确认”四类来源状态。
- [x] 对公开可见的接口、数据字段、前端算法或状态机给出足以指导后续复现验证的技术说明;若无法获得,则记录尝试路径和证据缺口。
- [x] 视频观点已按时间点补充,并明确区分作者自述、页面实现和仍无法确认的算法细节。
- [x] 两份报告不存在投资收益承诺,并明确其用途是技术与产品逻辑研究,不构成投资建议。
- [x] 生成一份 Tushare 数据需求研究文档,能够作为后续采集、落库和独立重算的接口清单与实施边界。
- [x] Tushare 文档明确区分页面已暴露的确定接口、为复现建议补充的接口和仍需实测/开通权限确认的接口;关键字段及权限信息引用官方来源。
- [x] 板块资金雷达排名页取消底部分页器,首批数据展示后可在表格滚动区接近底部时继续加载下一批,直到当前筛选条件下全部结果加载完成。
- [x] 切换交易日、板块类型、指标视角、榜单范围或搜索条件后,无限列表从首批结果重新开始,不混入旧筛选条件的数据。
- [x] 移除排名表上方包含标题、免责声明、实现标签、版本号和发布元数据的整块描述性卡片,不再用大面积静态说明挤占榜单空间。
- [x] 刷新失败、后台刷新、部分发布、加载失败和无数据等操作性状态仍能以紧凑且可访问的方式向用户表达。
## Out of Scope
- 绕过登录、会员、验证码、地域限制、反爬机制或其他访问控制。
- 对未公开的后端源码、私有数据源或专有算法作确定性归因。
- 开发、回测或上线等价策略,评估真实交易收益,或提供个性化投资建议;本轮仅迭代既有板块资金雷达页面的列表交互与信息密度。
- 修改 OneChartLab 网站或向其作者、用户发送消息。
@@ -0,0 +1,39 @@
# 作者视频证据:OneChartLab 四个网页工具
## 视频身份与取证方式
- 标题:《我把自己的交易系统,做成了4个网页工具》
- 作者:知行图表交易
- Bilibili:`BV16Hur6rEq2`,`aid=117077738265338`,`cid=40820081505`
- 页面发布时间:2026-08-12 00:13:10;时长:14:32
- 页面地址:<https://www.bilibili.com/video/BV16Hur6rEq2/>
- 页面简介:网站数据每日下午约 17:10—17:40 更新,受 Tushare 数据同步节奏限制。
视频没有公开字幕。本记录使用公开音轨经 `faster-whisper small` 中文模型转写,并用每 10 秒画面抽帧校对模块切换和页面位置。以下内容是按语义整理的作者自述,不把自动转写中的同音字当作精确原话;涉及关键公式时仍以页面代码和公开数据复算为最高证据。
## 板块资金雷达
- `00:00—01:15`:作者说明视频用于概览四个网页及近期更新;两个域名都可访问同一网站,新域名 `onechartlab.com` 主要改善国内连接性。四个页面统一了视觉外观,新增深色模式并调大字体。
- `01:17—01:36`:板块资金雷达不仅展示概念/行业的单日主力净流入,也展示单日流入率和多日波段流入率。
- `01:36—01:58`:作者把单日流入率解释为“主力流入相对当天成交额的比例”。比例越高,主力资金占比越高;但成分股过少、交易不活跃或成交量过低的板块可能出现失真的高比例。
- `01:58—02:23`:作者把波段流入率解释为“统计 3—10 天加权的单日流入率并排名”。在三百多个行业和概念中排名越靠前,表示主力资金在板块内“留存下来的比例”越高,后续行情的延续性可能相对更好。作者使用了概率性表述,没有承诺必然延续。
- `02:23—02:56`:作者以仪器仪表、元件、PCB/印刷电路板等为例,说明相近板块若波段流入率同时靠前,可辅助识别同一主题的资金持续性。
- `02:56—03:49`:页面新增板块成分股解释层,可查看涨跌幅、主力净额和主买净额的前后标的。作者认为它既能解释陌生行业包含哪些股票,也能帮助理解板块排名由哪些成分驱动。
- `03:49—04:13`:成分股支持复制、单板块导出和多板块勾选批量导出。作者明确说网页数据已公开,用户也可以让 Agent 工具每日定时抓取并分析。
## 宏观择时 / 高切低指标
- `04:13—04:27`:宏观择时页目前只放入一个“高切低指标”,未来可能继续加入作者认为有价值的指标。
- `04:27—04:42`:作者说明该指标参考国投证券的同名指标,并建议查看相关研报。视频没有声称复刻原版公式;页面同时明确标注“非原版算法”。
- `04:42—05:13`:作者把指标输入解释为申万一百多个二级行业近 90 天涨跌幅的横截面分布。行业涨跌幅差异越大,指标数值越大;高值意味着少数行业显著跑赢,甚至后排行业反向运行,形成结构性上涨或抱团行情。
- `05:23—05:39`:作者给出的状态解释是:`30—70` 为正常区间,`70—120` 代表结构性抱团,超过 `120` 代表极致化抱团,可视为拥挤或过热。视频没有补充滞回、连续确认或仓位规则。
- `05:41—06:27`:作者以 2007、2015、2021 年及近期行情为例说明极值。视频称近期六月底一度达到 `119.19`,抱团瓦解后指标快速回落;高位板块回调、低位板块均值回归会共同降低横截面离散度。
- `06:29—06:40`:第一种用途是宏观层面的择时/风险识别,通过是否超过 `70` 或 `120` 判断市场是否处于极致抱团甚至过热环境。
- `06:40—07:27`:第二种用途是判断市场风格是普涨还是结构化。作者以“924”行情为例:初期指数上涨但离散度没有同步大升,代表普涨;后期离散度上升,代表只有少数行业上涨。作者进一步把它解释为主线识别,希望持仓行业处于主线、贡献正向离散度,而非位于主线对立面。
- `07:27—07:58`:第三种用途是观察由高离散度转向低离散度时可能出现的“高切低”,即资金从高风险/高位板块切向低风险/低位板块。作者强调低位板块出现小行情不等于它一定会成为新主线,只能说明资金存在高切低趋势。
## 与页面证据的交叉结论
视频补足了两项设计语义。其一,单日流入率的概念分母是当日成交额,并明确提示小样本与低流动性会造成比例失真;但视频仍未公开精确字段、聚合顺序、异常值处理和 score 标准化。其二,高切低指标明确基于申万二级行业近 90 日涨跌幅差异,阈值用于解释拥挤与市场结构;但视频仍未公开离散度统计量、行业相对基准、历史校准、贡献 `C/O` 的上游公式或任何可执行仓位规则。
因此,视频适合用来确认产品意图、指标语义、使用边界和风险提示,不能替代页面代码与公开数据对精确公式的验证。
@@ -0,0 +1,48 @@
# OneChartLab「宏观择时」公开实现证据
核验日期:2026-08-27(只读请求;未使用登录、验证码、cookie/token,也未分析视频)。主页面:<https://onechartlab.com/macro/>。
## 已确认
1. **产品目标和公开界面。** 页面标题为“宏观择时”,副标题是“观察市场趋势与拥挤程度,判断中长期多空方向”;唯一指标页签为“高切低指标”,并明确写“参考国投证券同名指标,非原版算法”(HTML 原文及出处:`https://onechartlab.com/macro/`,抓取 HTML `51-66` 行)。页面显示今日离散度、十年历史百分位、较昨日、近5日,并叠加行情离散度与指数累计表现图(HTML `70-114`)。
2. **算法公开到什么程度。** 页面原文是“以申万二级行业的相对收益分布衡量行情分化程度,并通过平滑处理形成离散度序列”,且声明“仅供历史研究学习使用,不构成投资建议”(HTML `121-126`)。因此行业层级和“相对收益分布”是确认事实,但分布统计量、归一化方式、平滑窗口及权重没有在公开页面说明;不能把它复现为某个特定公式。
3. **阈值/状态机。** 前端 `assets/app.js?v=a4a0a7155f44` 的 `dispersionZone(value)` 明确实现:`value<30` → `低位趋同`;`30<=value<70` → `正常区间范围内`;`70<=value<120` → `中高位 · 潜在高切低动力`;否则 → `极致化抱团 · 谨慎`(该 JS 为单行压缩资源,函数位置可按符号检索;等价源码行号见本底稿 `file:line` 说明)。页面可见的数值区间文案为“30—70 趋同发展 | 70—120 结构抱团 | 120+ 极致化”(HTML `83-87`)。
4. **百分位、变化量和发布日期。** 同一 JS 的 `tenYearPercentile(values,last)` 取 `last` 日期往前十年的样本,只保留当前日期以前且为有限值的观测,百分位为 `100 * count(value <= current) / sample.length`;`updateStats()` 使用最后一个有限值,计算当日值、百分位、1日差和 `last-5` 差,并把对应日期写入 `#as-of`(`assets/app.js` 函数 `tenYearPercentile` / `updateStats`)。这意味着百分位包含当前观测(并非严格“之前”的样本),页面的“数据日期”是序列最后一个有效交易日。
5. **实际公开数据接口和当前快照。** `assets/app.js` 的 `init()` 请求 `state.json`,读取 `state.current.manifest.series_path`,再请求该路径;当前公开响应 `https://onechartlab.com/macro/state.json` 为 `schema_version: onechart_macro_daily_bundle_v3`、`release_status: production`、`revision_watermark: 21`,`current.as_of_date: 20260826`、`current.batch_id: batch-20260826-r21-c8768898f3`,系列路径为 `batches/batch-20260826-r21-c8768898f3/series.json`。该系列响应的 schema 为 `onechart_macro_v1`,日期从 `20000601` 到 `20260826`,字段包括 `dates`、`precise`、`smooth`、`indices`;当前摘要中 `precise=42.1781`、`value(smooth)=42.551`、`change_1d=-1.7363`、`change_5d=-15.5529`、`precise_percentile_10y=38.4`、`smooth_percentile_10y=38.6`。出处:`https://onechartlab.com/macro/state.json`、`https://onechartlab.com/macro/batches/batch-20260826-r21-c8768898f3/series.json`。
6. **指数输入和图表交互。** JS 的 `TAG_ORDER` 固定包含 `000001.SH`、`399006.SZ`、`000688.SH`、`000016.SH`、`000300.SH`、`000852.SH`、`932000.CSI`,标签分别为上证、创业、科创、50、300、1000、2000;指数曲线以选定时间范围起点价格做 `100*log(price/base)` 的累计表现,tooltip 再将其转成 `100*(price/base-1)` 的区间涨跌幅。默认展示平滑序列和上证曲线;可切换精准、显示/隐藏曲线、拖动时间范围、双击恢复、选择曲线后上下拖动改变显示缩放(`assets/app.js`:`normalized`、`tooltip`、`setupSeriesTags`、`setupVerticalScaleInteraction`)。页面操作提示原文在 HTML `116-119`。
7. **离散度贡献模块的数据契约。** 页面嵌入“离散度贡献”区块,文案写“正贡献表示相对状态增强,负贡献表示相对状态减弱”,并称行业贡献按公开归一化数据构建、支持固定90日窗口(HTML `131-135`)。`assets/dispersion-store.js` 的 `DataStore` 公开校验:schema `dispersion-public-v2`;manifest 要求 `industry_count===124`、`index_count===7`、日期序列严格递增且至少91个;每行字段严格为 `date,D,MA3,K,K_MA5,industries,indices`;行业字段为 `code,name,normalized,return90,C,O`,指数字段为 `code,name,normalized`。`view(end)` 明确返回所选结束日及其前90个交易日共91行的 C/O/normalized 序列。出处:`https://onechartlab.com/macro/assets/dispersion-store.js`,函数 `validManifest`、`validBlock`、`view`。
8. **贡献模块的窗口、排序和状态映射。** `assets/dispersion-contribution.js` 以 `DATA.values`(行业 C)做逐行业前缀和;1/3/5/10/90 日贡献分别是截至日最近 N 个交易日的累计和,正负两侧各取10个行业排序。页面/脚本显示“固定90日窗口(虚线为MA5)”,每日柱状贡献正值代表扩大分化、负值代表缩小分化;后续 V31 逻辑使用 `O` 计算“方向性”、使用 C 判断结构扩大/缩小,状态函数 `state18` / `effect18` 的完整阈值未在可读页面文案中公开。该资源为压缩单行,出处 URL:`https://onechartlab.com/macro/assets/dispersion-contribution.js?v=05aeb6c74aaf`,符号 `sum`、`metric`、`pool`、`curve18`、`state18`、`effect18`。
9. **更新、缓存和异常边界。** `DataStore.bytes` 所有请求都用 `cache:'no-store'`,若 manifest 给出 hash 则 SHA-256 校验;`choose` 对 current 构建超过 `maxAgeDays=30` 视为 `stale-current`,失败后回退 `last_good`;若回退构建也失败,状态为 `unavailable`。`ensureWindow` 要求窗口正好91个交易日,缺块时按年份文件懒加载,缺行/范围不匹配/字段形状错误都会失败。贡献模块失败时页面明确显示“离散度贡献暂不可用,高切低指标保持正常”(HTML `134`,JS 主 IIFE catch)。
10. **成分股详情接口(补充模块)。** 贡献排行点击行业后,脚本懒加载 `../sector_rankings/manifest.json`,按 `systems.macro.current.date_files[date]` 读取日期文件;字段契约声明宏观输入来自 Tushare:`daily.pct_chg`、`moneyflow.net_mf_amount`、`moneyflow_dc.net_amount`、`index_member_all`、`suspend_d`、`suspend`、`stock_basic`。公开 payload 只给 top/bottom 派生排名;主买净额单位从万元转展示亿元,且明确“不等同主力净额”。出处:`https://onechartlab.com/sector_rankings/manifest.json` 及 `dispersion-contribution.js` 的 lazy-detail `open()`。
## 合理推断(注明链条与置信度)
- **前端只消费预计算序列,核心算法在后端/构建流程。** 证据链:`init()` 仅 fetch `series.json` 并直接使用 `precise`/`smooth`;页面和 JS 没有根据行业原始收益计算离散度的代码,而贡献模块消费 `D/MA3/K/K_MA5/C/O`。置信度高;但构建端未公开,无法确认具体服务/脚本。
- **存在至少一个“平滑确认”层。** 证据链:接口同时提供 `precise` 和 `smooth`,UI 默认 smooth,贡献数据行又提供 `MA3`;可以合理推断平滑用于减少日噪声或确认,但不能确认平滑是3日移动平均、是否居中、是否有信号滞后。置信度中。
- **历史数据可能发生修订,且当前页面存在版本/口径并行。** `state.json` 记录 `accepted_input_hash`、`bundle_id`、`revision_watermark` 和 `last_good`;dispersion manifest 的 `identity.daily_contract` 为 `macro-bundle-v10-public-0644-private-0600-round4-percentile-closure-round10-seed-latest-names`,说明构建链会版本化并接受输入链。由此可推断历史序列不是不可变真值;但公开接口没有修订日志或逐日版本对照,无法量化修订频率。
- **回测前视偏差风险主要来自发布日期/可见时点未公开。** 数据有交易日 `as_of=20260826`,但没有公开生成时间、Tushare 各输入实际返回时间或“次日可用”规则。因而使用当日收盘构建的指标去解释当日盘中/收盘前决策会有潜在前视;这是复现时必须保守处理的风险,不是已证实的泄漏。
## 无法确认 / 失败尝试与证据缺口
- 未找到公开的核心公式:没有确认相对收益分布采用标准差、分位距、极差、熵或其他统计量,也没有确认 `K`、`K_MA5` 的定义;不能据此声称原版“高切低”算法。
- 未确认资产/风险状态映射:页面只把阈值文案映射为“趋同/抱团/极致化”和“潜在高切低动力/谨慎”,没有公开仓位比例、具体资产切换或风险预算映射。
- 未确认发布日期/交易时点和历史修订策略:只有 `as_of_date`、bundle/hash/watermark,没有公开 release timestamp、修订差分、输入快照或 point-in-time 数据协议。
- 只读尝试 `https://onechartlab.com/macro/dispersion/state.json` 返回板块资金雷达 HTML(非 JSON,HTTP 200);页面脚本仍以相对路径 `dispersion/state.json` 请求。这是当前公开部署路径异常的证据,不能据此判断后端接口不存在,且不要用主页 fallback 内容当作数据。
- `latest180.json`(manifest 路径 `https://onechartlab.com/macro/dispersion/builds/dispersion-20260826-6186c256680b/latest180.json`)响应体较大,当前 curl 超时/截断,未将不完整响应当作数据证据;manifest 本身成功核验到 `date_index` 2326 个、124 行业、7 指数、V31 renderer、`as_of=20260826`。
## 供抽查的定位
外部 HTML(下载后 `nl -ba`):`/tmp/oc_macro.html:51-66,70-87,90-119,121-145`;外部 JS 原文件均为压缩单行,应用资源名和关键符号可直接用 `rg`:`/tmp/oc_app.js:1`(`dispersionZone`、`tenYearPercentile`、`updateStats`、`init`)、`/tmp/oc_store.js:7-21`(`DataStore`)、`/tmp/oc_contrib.js:1-124`(`sum`、`pool`、`curve18`、`state18`、`open`)。数据响应:`https://onechartlab.com/macro/state.json`、`https://onechartlab.com/macro/batches/batch-20260826-r21-c8768898f3/series.json`、`https://onechartlab.com/macro/dispersion/builds/dispersion-20260826-6186c256680b/manifest.json`、`https://onechartlab.com/sector_rankings/manifest.json`。
## 主会话复核补充
主会话随后成功完整读取 `latest180.json`,SHA-256 为 `b0f2821c9f72f9d7b583f748b0759b5c0a1cc72f92edc66162418d2bc9b3add3`,与 manifest 一致。对 180 行、22320 个行业观测复算确认:`MA3=mean(D_t..D_{t-2})`、`D_t-D_{t-1}=ΣC_i,t`、`K_t=ΣO_i,t`、`K_MA5=mean(K_t..K_{t-4})`,并且所有观测满足 `abs(O)=abs(C)`。当前 V31 脚本最终使用窗口内 `ΣO` 排贡献方向、`ΣC` 判结构扩大/收敛,再映射进攻/走弱/回落/修复四象限。
@@ -0,0 +1,43 @@
# OneChartLab「板块资金雷达」公开实现证据
核查日期:2026-08-27。范围是无需登录的 `https://onechartlab.com/` HTML、其公开 JSON 静态资源和前端内嵌 JavaScript;没有绕过访问控制,也未保存 cookie/token/个人数据。
## 已确认
1. **用户目标与主界面。** 页面 title/description 是“板块资金雷达”和“观察板块资金流向、强弱变化与市场主线”;正文副标题为“识别主线资金流向与趋势,对比板块强弱”。页面可选数据日期、概念/行业类型、搜索板块名称或代码,并支持“波段流入率、单日流入率、单日净额、排名变化”四种排序指标(`https://onechartlab.com/`,HTML `file:line`:`:6-7`, `:641-671`)。
2. **公开数据协议与粒度。** 首页首先只读请求 `radar_manifest.json`,校验 `schema_version===1`、`AVAILABLE_DATES`、日期 shard 路径,再请求 `radar_data/dates/2026-08-26.f49c721846fb.json`(manifest 当前文件名来自 `https://onechartlab.com/radar_manifest.json`)。manifest 给出 `LATEST_DATE=2026-08-26`,可用日期为 2026-07-16 至 2026-08-26 的 30 个交易日;最新 shard 实测为 JSON 数组 791 条,概念板块 414、行业板块 377。实现证据:HTML `:1894-1972`;响应字段/路径证据:`https://onechartlab.com/radar_manifest.json` 的 `AVAILABLE_DATES`、`LATEST_DATE`、`files.dates`,最新 shard URL 上述路径。
3. **单条板块字段。** 最新 shard 的记录含 `trade_date`, `type`, `index_name`, `ts_code`, `lead_stock`, `pct_change`, `pct_change_stock`,以及 `Swing/Ratio/Amount` 三类的 raw 值、分数、排名位置、排名百分位、近 30 日在榜计数和 1/2/3 日排名变化字段:如 `Swing_Ratio_Val`, `Swing_Amount_Val`, `Swing_Score`, `Swing_RankPos`, `Swing_RankPct`, `Swing_Top30d`, `Swing_Bot30d`,对应 `Ratio_*`、`Amount_*`。实测示例 `2026一季报扭亏 (概念)`(ts_code `BK1682.DC`)在 2026-08-26 的 `Amount_Raw_BN=-5.59969136`, `Amount_RankPos=353`, `Ratio_Raw_Pct=-0.06896072719626979`, `Swing_Ratio_Val=-0.03308411781204722`。来源:`https://onechartlab.com/radar_data/dates/2026-08-26.f49c721846fb.json`,响应记录键集合。
4. **榜单筛选和排名。** 非“排名变化”时,前榜取 `activeTab_RankPct >= 90`,后榜取 `<= 10`;默认前榜按 `Amount_Raw_BN`(单日净额)或相应 `*_Score` 降序,后榜升序。“排名变化”时按所选基准 `Swing/Ratio/Amount` 的 `*_Rank_Chg` 排序,各取 `ceil(板块数*0.1)` 且至少 1 条。代码还明确页面文案为 `TOP 10%` / `BOTTOM 10%`。HTML `:1292-1314`, `:695-718`。
5. **排名变化的时间窗口。** 排名变化基准可选波段率、单日率、单日额;统计天数 UI 提供近 1 至近 5 天。1–3 天直接读取记录中的 `Swing/Ratio/Amount_Rank_Chg_1d/2d/3d`;超过 3 天时读取 rank-history,并以 `pastRank - currRank` 计算变化,过去日期超出范围时钳制到最早可用日期。HTML `:676-691`, `:1260-1289`。
6. **数值显示与单位映射。** `Swing_Ratio_Val` 和 `Ratio_Raw_Pct` 在显示时乘 100 并格式化为百分比;`Amount_Raw_BN` 直接按亿元显示;分数显示 1 位小数,净额显示 1 位小数,排名变化显示整数。HTML `:1453-1467`, `:1482-1500`;详情文字也明确“波段均值”“占比”“主力净流入 … 亿”,`:1072-1092`。
7. **历史轨迹和详情交互。** 榜单的“在榜”按钮读取公开 `radar_data/rank_history.3674d0a1cecf.json`,结构为 `Amount`, `Ratio`, `Swing` 三个 map,每个包含约 799 个板块名到日期→排名的映射;详情图使用可用日期反转后的 30 个点,缺失历史排名以总池大小代替,并把排名限制到 `[1,maxRank]`。HTML `:1522-1539`, `:1564-1571`, `:1794-1815`;资源 URL:`https://onechartlab.com/radar_data/rank_history.3674d0a1cecf.json`。
8. **成分股数据、字段和异常边界。** 详情通过 `sector_rankings/manifest.json`(schema `onechart_sector_stock_rankings_v2`)定位日期文档 `sector_rankings/radar/dates/20260826.bacc5d9e1581.json`,再按 `sectors[ts_code]['1']` 读取 `metrics.pct_change/main_net_amount/active_buy_net_amount` 的 `top`、`bottom`、`sample_size`、`status` 和 `value`。实测日期文档含 `date=20260826`, `system=radar`, `sectors` 791 个板块;示例 `BK0420.DC` 的三指标均为 `status=available`, `sample_size=13`。HTML `:1667-1704`;资源 URL:`https://onechartlab.com/sector_rankings/manifest.json`、`https://onechartlab.com/sector_rankings/radar/dates/20260826.bacc5d9e1581.json`。
9. **数据源、口径和更新时点(页面公开原文)。** 页脚写明“数据源: Tushare + 东财板块日线资金流数据”“更新频率: 交易日 17:00 ~ 17:30 自动同步”“参数说明: 波段周期取 3-10 个交易日多周期协同加权”。页面也提示“本日板块数据由个股本地聚合计算,涨跌幅暂不显示(\"-\")”。HTML `:636-639`, `:1028-1035`。`radar_manifest.json` 当前 `DATA_SOURCE` 为空,因此“本地聚合”提示在当前公开 payload 不会因该字段自动出现;提示逻辑为 HTML `:1187`。
10. **前后端计算边界和失败处理。** 公开 JSON 已提供 raw、score、rank 等派生字段,浏览器端只做筛选、排序、格式化、排名变化(超过 3 日)、Jaccard 近似板块计算和 SVG 轨迹绘制;manifest/日期 shard/rank-history 请求失败会回退到 `radar_data_latest.json`,仍失败则显示“数据加载失败”和“重新加载”按钮。HTML `:1905-1972`, `:1771-1792`。旧接口是 `https://onechartlab.com/radar_data_latest.json`,实测可公开读取但约 20 MB,含 `RADAR_DATA`, `AVAILABLE_DATES`, `LATEST_DATE`, `RANK_HISTORY_MAP`, `CONSTITUENT_MAP`。
## 合理推断
- **“波段”口径是服务端预计算的多周期指标。** 依据:页脚原文称“3-10 个交易日多周期协同加权”,记录同时暴露 `Swing_Ratio_Val`、`Swing_Amount_Val` 与 `Swing_Score`,但前端没有生成这些字段的公式。置信度:高(页面口径明确),具体权重未知。
- **榜单主数据主要在服务端生成。** 依据:前端直接消费 `*_Score`, `*_RankPct`, `*_RankPos`, `*_Rank_Chg_1d..3d`,只在 4/5 日排名变化时用公开历史 map 做差;因此原始资金聚合、打分、排名应已在静态数据发布前完成。置信度:高;无法据此确定后端具体语言或作业实现。
- **排名池是东财板块宇宙,当前 791 个板块。** 依据:`sector_rankings/manifest.json` 的 radar `universe_id="eastmoney-dc-v1"`, `sector_count=791`,与最新日期 shard 数量一致。置信度:高。
- **近似板块“重合度”是 Jaccard。** 依据:浏览器端计算 `intersection / (setA.size + codes.length - intersection)`,排序取前 4(HTML `:1781-1792`);不是后端评分。置信度:高。
## 无法确认 / 证据缺口
- 未在公开 HTML/JS/JSON 找到 `Swing_Score`、`Ratio_Score`、`Amount_Score` 的具体公式、权重、标准化方式、并列排名规则,也无法从响应反推出“TOP 10%”之外的完整排序 universe 计算细节。
- 页脚只给出 Tushare 与东财来源名;未公开 API token、抓取 SQL、任务代码、实际同步失败重试策略或时区说明。`sector_rankings/manifest.json` 的 contract 能确认 radar 输入字段映射:`tushare.moneyflow.net_mf_amount`, `tushare.moneyflow_dc.net_amount`, `tushare.dc_member`, `tushare.daily.pct_chg` 等,但不能证明上游响应在本次发布中的每一行具体值。
- “本日板块数据由个股本地聚合计算”是页面条件提示文本;当前 `radar_manifest.json` 的 `DATA_SOURCE` 为空,实际页面是否显示该提示取决于运行时 payload/旧回退数据,未用交互浏览器截图确认。
- 未分析视频;未访问需要登录、验证码、付费或绕过反爬的资源。对不存在的后端 API,实际仅检索 HTML 中 `fetch(`/api`/axios` 等关键词和内嵌请求路径;发现的公开请求路径限于 `radar_manifest.json`、日期 shard、`radar_data/rank_history...json`、`radar_data_latest.json` 和 `sector_rankings/...`,未发现 XHR API。
## 主会话复核补充
主会话对 2026-08-26 全部 791 条记录复算确认:概念和行业两个排名池内,`Swing_RankPos` 与 `Swing_Score` 降序、`Ratio_RankPos` 与 `Ratio_Score` 降序、`Amount_RankPos` 与 `Amount_Raw_BN` 降序均为零不匹配;三个 `RankPct` 字段均满足 `100 * (N - RankPos + 1) / N`,最大浮点误差约 `1.42e-14`。这使排名外层逻辑可以精确复现,但不能反推出三个 score 的服务端构造公式。
@@ -0,0 +1,26 @@
{
"id": "onechartlab-research",
"name": "onechartlab-research",
"title": "OneChartLab 板块资金雷达与宏观择时技术调研",
"description": "",
"status": "completed",
"dev_type": null,
"scope": null,
"package": null,
"priority": "P2",
"creator": "yuxuanhui",
"assignee": "yuxuanhui",
"createdAt": "2026-08-27",
"completedAt": "2026-09-01",
"branch": null,
"base_branch": "main",
"worktree_path": null,
"commit": null,
"pr_url": null,
"subtasks": [],
"children": [],
"parent": null,
"relatedFiles": [],
"notes": "",
"meta": {}
}