Files
zhixing-system/.trellis/tasks/08-27-onechartlab-research/research/macro-timing-evidence.md
T

49 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` 判结构扩大/收敛,再映射进攻/走弱/回落/修复四象限。