# 更新记录

本文件记录已经合入 `main` 并完成生产验证的阶段性改动。策略研究证据和详细数据见
[docs/FINDINGS.md](docs/FINDINGS.md)，部署与恢复步骤见 [docs/OPS.md](docs/OPS.md)。

## 2026-08-10

### 暂停 Hold 新单，接入 WeatherNext 2 影子集合

- 完整候选流 3160 单 / 1033 事件上，当前 corr gate + $20 cap 为 -5.12% ROI，事件
  bootstrap 95% CI [-6.99%,-3.19%]；`enable_hold_entries=false`，存量继续管理。
- 首次暂停写入不可变 `hold_pause_v1_start`；每轮仍保存候选、snapshots、forecasts 并运行
  maker replay，避免因停止亏损下单而中断研究数据。
- 新增 `shadow_ensemble_models`，通过 Open-Meteo 采集 WeatherNext 2 的 64 成员并随
  forecast batch 落库；交易概率明确排除 shadow selector。
- 新增 `tools/backtest_weathernext.py`。固定 lead 中心值回测显示 WeatherNext 原始 MAE
  1.706°C（现有 1.254°C），30 日因果去偏后 0.980°C（现有 0.982°C），尚不足以恢复交易。
- 修复 `tools/replay_rules.py`，可直接从生产 snapshots 构造完整首次候选流，不再依赖临时
  `cand` 表；看板同步显示 Hold 暂停及候选仅用于研究的状态。

## 2026-07-31

### 全候选流回放：撤回 corr_gate_v1 的有效性依据，收紧单笔仓位

07-27~29 连续三天净 -159.61 / -128.44 / -184.51 触发复盘。结论见
[docs/FINDINGS.md 发现 25](docs/FINDINGS.md)，要点：

- 此前的反事实都跑在 `paper_orders` 上，而哪些候选变成订单由 `max_open_exposure_usd`
  腾出空间决定 —— 样本被要测量的那个东西选择过。新增 `tools/replay_rules.py`，在
  `snapshots` 的完整候选流上回放（1848 候选 / 573 事件），CI 按事件 bootstrap。
- 按此口径 corr_gate_v1 是 ROI 中性的（-6.87% vs 基线 -6.82%），**发现 22 之后那条
  "+9.4% vs -3.6%, p=0.0006" 撤回**。门禁实现无误（0 例违规），继续运行但不再作为证据。
- Hold 规则基线 -6.82%，95% CI [-8.88, -4.79]；每个价格档实际胜率都低于盘口隐含保本
  胜率 1.7-2.9pp。没有任何价格或 edge 区间存在 edge。
- `max_stake_usd` 50 → 20：撞上限的单占已结算单数 4.3%、本金 31%、净亏损 47%。回放
  ROI -6.87% → -5.70%，最差目标日 -511 → -238。
- `max_open_exposure_usd` 维持 1600，理由更换为"cap 绑定会把settlement 时序的选择偏差
  写进前瞻记录"，07-29 那条吞吐量+corr_gate 的论证作废。

### 看板：日收益柱按 ROI，edge 阶梯恢复顺序

每日柱长此前按美元，而同期每日本金从 $221 到 $757 差三倍，最长的两根柱子是下注最多的
两天而不是预报最差的两天（07-27 是 -159.61/$425 = -37.6%，07-29 是 -184.51/$652 =
-28.3%，柱状图把顺序画反了）。改为按当日 ROI 定长，美元与本金并列显示。

`hold_attribution` 中 edge 分层表误用了城市表的 `ORDER BY 净 P&L DESC`，档位渲染成
8–12% / 20–30% / 12–20%。城市表需要该排序（取最好最差各四个），edge 阶梯不需要；
修正后立刻显出单调性：-2.5% / -5.3% / -21.9%。

## 2026-07-28

### corr_gate_v1：开仓门槛与 Kelly 仓位改用站点去偏概率

`model_prob_corr` 此前只记录不参与决策。384 单已结算前瞻样本显示 raw ensemble 在
**每一个**概率分箱都过度自信，而 Kelly 按 edge 定仓，等于把最大的仓位压在模型最错的
地方：

| raw 概率区间 | n | raw 声称 | 实际胜率 | 均仓 | ROI |
|---|---|---|---|---|---|
| [0.70, 0.80) | 90 | 0.756 | 0.600 | $5.56 | +19.1% |
| [0.90, 0.99) | 97 | 0.939 | 0.753 | $6.49 | -17.3% |
| [0.99, 1.01) | 38 | 0.998 | **0.789** | **$9.72** | +1.3% |

反事实（同一批 384 单，只换门槛）：保留 286 单 +9.4%，拒掉 98 单 -27.3%，不筛为 -3.6%。
两组胜率几乎相同（0.682 vs 0.694）——**它不挑赢家，它只是不在过度自信处下重注**，被拒
组均仓 $9.31、保留组 $5.81。对照组「单纯提高 raw edge 门槛拒掉同样多的单」为 -4.8%，
方向相反，说明收益来自校正本身而非交易更少。置换检验 p = 0.0006。

前视核对：`calibration_observations` 16281 行中 `target_date >= verified_ts` 当天的
为 **0** 行，最小观测滞后 1 天；bias 用 ≤D-1 拟合、经 `BIAS_MAX_AGE_DAYS=7` 加载后
作用于 ≥D+1（`skip_same_day = true`），间隔至少 2 天。

实现要点：

- corr 门槛叠加在 raw band **之上**，不是替换。上面的估计只能测「raw 放行的单里 corr
  会拒掉哪些」，raw 拒掉的单从未进入样本，因此保持 raw 为必要条件，前瞻测的才是同一件事。
- `Signal` 新增 `raw_prob` / `raw_edge`；`paper_orders.model_prob`、`.edge` 和
  `snapshots.edge` 继续存 raw，跨分界点语义不变，corr 走 `model_prob_corr` 与 `net_edge`。
- `rank_candidates` 与 `priority_edge_cap` 仍按 raw edge 排序（该 band 是在 raw 上拟合的），
  避免同时改动排序与门槛而混淆归因。
- 无新鲜 bias 行时 `prob == raw_prob`，退化为 corr_gate_v1 之前的规则。
- 分界点 `corr_gate_v1_start` 写入 `bot_meta`；**前后 ROI 不得合并统计**。

### 每日收益分布图口径修正

图标注「已扣记录费用」，但 `fee_accounting_v1_start`(2026-07-20) 之前的行
`entry_fee = exit_fee = 0`，等于把毛收益按净收益展示；固定 14 行窗口还会随天数推移
静默移动起点，让开局亏损的一周滑出图外而 headline ROI 仍然计入。改为与归因区块同窗口
（`fee_accounting_v1_start` 起），去掉行数上限。

修正前后对同一份数据的读数差异：图上 14 天合计 +266.90，而完整 21 天为 +47.87
（被截掉的 07-07~07-13 合计 -219.03）。

### 敞口上限 800 → 1600

800 是当时唯一的绑定约束：101 单持仓占 $788.16，每轮 `exposure_cap_skipped` 77–86 对
92–105 个候选，126 轮里 98 轮零开仓。持仓至结算约 1.75 天，等于把新增本金限死在
约 $450/天，且谁能进场取决于哪个结算恰好释放了额度而非候选质量。`bankroll_usd` 刻意
不动（它只是 Kelly 定仓基数，改了会让单笔仓位跨分界点不可比）。

### 备份修复

`predit-backup.service` 自 2026-07-09 起连续失败 32 次，19 天无异地副本：全库 dump 即使
gzip 后仍有 188 MB，超 GitHub 100 MB blob 限制，失败信息埋在 git push 输出里无人查看。
`snapshots` 表及其两个索引占库体积 90%（1308 MB / 1455 MB），属原始行情流而非推导状态，
改为只导 13 张结果表 → **15.3 MB**，耗时从 2 分 18 秒 CPU 降到 8.5 秒。推送前加 90 MB
体积守卫，让下一次超限以明确报错出现而不是被拒的 push。

### 生产验证快照

- `cargo test --release`：67 passed / 0 failed（含 2 个新增 corr_gate 测试）；release build 通过。
- 重启后首轮：`candidate_count` 由 92–105 降至 69（≈27%，与预估的 25.5% 一致），
  `new_orders=23`，`exposure_cap_skipped` 由 77–86 降至 40，无 ERROR / panic。
- 新单逐行核对：`model_prob` 存 raw、`model_prob_corr` 存校正值；23 单中 corr 收窄 10 单、
  放大 8 单、持平 5 单。
- 备份端到端验证：从 GitHub 重新 fetch 还原，13 张表行数与生产库一致
  （`maker_sim_orders` 差 1 行为 observer 持续写入），`pragma integrity_check = ok`。

> 首轮均仓 $34.32 高于历史 $5–9，是敞口一次性放开后高排名候选集中入场的瞬时效应，
> 待敞口重新饱和后回落，不代表 corr_gate 放大了仓位。

## 2026-07-17

### 策略与数据质量

- 上线 allocation v2：优先给 raw edge 8–20% 的 NO 候选分配额度，每事件最多 2 单，
  同时记录 CLOB 顶档数量。交易准入、Kelly 与 taker 纸面成交口径不变。
- Open-Meteo 三个 ensemble 合并请求，增加完整批次门禁、SQLite 冷启动恢复、429 全局退避、
  6 小时缓存和稳定错峰；残缺 ensemble 不再产生信号或覆盖完整缓存。
- 固定 lead-time 影子校准改用 Previous Runs D+1/D+2/D+3 与 IEM 站点实测，输入和结果均可
  审计。生产最终批次为 13,065 条观测、294 条站点×kind×lead 结果；三档 walk-forward
  corrected MAE 均低于同样本 raw MAE，但 `model_prob_corr` 仍不参与开仓。

### Maker 执行研究

- 新增 `maker-observe`，通过 Polymarket 公共 market WebSocket 采集候选 token 的 top-5
  book 和成交，并进行保守队列回放；没有认证、EIP-712、私钥或真实下单代码。
- 高频 L2 独立写入 `weatherbot-maker.db`（WAL、7 天滚动、不备份），主策略库只保存低频
  `maker_sim_orders`，避免 collector 写入竞争阻塞 paper 循环。
- 撤单不减少 `queue_ahead`；只有 SELL 成交吃完同价可见队列和本单，或严格穿过虚拟 bid，
  才记整单 filled。启动期出现的少量成交只证明回放链路工作，不能外推真实 maker fill rate。

### 生产验证快照

- 三个常驻服务均为 active，maker observer 无重启；主库 `PRAGMA integrity_check=ok`。
- maker L2 隔离后，paper 循环正常完成，复查窗口内未再出现 `database is locked`。
- 最新策略快照：591 settled / 282 wins / +$128.07；13 笔 METAR 击穿退出 -$42.27；
  96 open / $798.11，14 pending / $100.83。影子 A 前瞻 29 单 / +16.4%，allocation v2
  尚无 settled 样本，因此阶段门槛与真实下单禁令不变。

### 验证与兼容性

- `cargo test`：38 tests passed；release build 通过。
- strict Clippy 仍只报告既有的风格/函数参数数量问题，本轮未扩大处理范围。
- 生产数据仍以 AWS `~/predit-bot/weatherbot.db` 为准；本机数据库不用于战绩结论。

## 2026-07-19

### Maker 执行研究

- 首个两日回放样本：逐单 fill rate 7.8%、市场×天覆盖 54–56%、成交比 taker 省 4.2c、
  成交后 60 分钟漂移 -1.5c；94.5% 过期单价位零成交，瓶颈是流量不是队列（发现 22）。
- 成交规则 v2（量守恒）：trade-through 不再整单瞬成（v1 下 84% 的 fill 来自该规则，
  撤单下移场景偏乐观），一笔打印最多按其 size 计入新增 `filled_shares`，到期保留
  部分成交。v1/v2 边界记入 `bot_meta.maker_fill_v2_start`，跨边界不可比。
- 新增 improve 对照臂（bid+1c、queue=0，实时 ask 防穿越），与 join 臂同规则 A/B；
  `maker_sim_orders` 重建为 `(source_snapshot_id, policy)` 唯一索引，历史行默认 join。
- `report` 新增 maker 结算对账：已 settle 市场上按 policy × 规则代际对比 maker 与
  同快照同数量 taker 的 P&L。

### 验证与兼容性

- `cargo test`：44 tests passed（新增迁移保真、量守恒、部分成交、双臂去重、防穿越 5 类）。
- Clippy 与上一版本基线一致，未引入新告警；模拟仍无认证、私钥或真实下单代码。

## 2026-07-20

### 费用后前瞻验证

- 从 CLOB condition market info 动态读取 Weather 协议费；用含入场费的有效价格重算
  net edge 与 fractional Kelly，保存 entry/exit fee。费率查询失败或 exponent 不支持时
  拒绝纸面下单，不再默认零费。
- 新增不可回拨的 `fee_accounting_v1_start`。旧 761 单仍按历史 gross 展示；Phase 门槛
  改看边界后的 fee-aware realized gross/fees/net，避免把事后估算费混入账本。
- 每张新单保存 raw/corrected/market probability；从 `prob_score_v1_start` 起报告三者
  Brier。v2 已有样本中市场中价 0.1998 优于 raw 0.2321 和 corrected 0.2385，校正概率
  暂不获准驱动下单。

### Shadow B 与提前退出裁定

- 新增独立 `shadow_orders` / Shadow B：NO、raw edge 8–20%、价格≥70¢、费用后 net
  edge≥8%，每事件只取最高 edge，固定含费成本 $5；边界 `shadow_b_start`，不占基线敞口。
- `report` 与 Web 看板新增 fee-aware 和 Shadow B 前瞻指标；结算循环同时处理两套订单。
- 新增 `tools/replay_exits.py`，用 10 分钟 CLOB 快照的首次触发 bid 回放固定止盈，计双边
  fee，默认要求顶层深度足以全平。Shadow B 历史代理 122 事件 hold +$50.32，5%–30%
  止盈全部更差；两日时间留出还出现训练改善、次日反向亏损，因此不部署自动止盈。

### 双向趋势 Shadow C

- 主动前瞻对照收敛为原策略 Hold 与 C3；Shadow B 停止新增，历史行继续结算和审计。
- C3 用同源 Gamma YES 中价的 30/60/180 分钟同向变化，同时捕捉 YES 与 NO；每事件只取
  最强 bucket。CLOB 只负责 spread、方向买卖价、动态双边 fee 和顶档深度门禁。
- 新增独立 `reference_bid/reference_ask` 和不可回拨的 `shadow_c_start`。生产不回填旧混源
  快照，先自然预热 180 分钟；30/60 分钟同时反转或 METAR 已击穿时才按可成交价全平。
- 每轮日志只输出 C3 signals/executable/opened/closed 聚合值，不记录被过滤 bucket 的逐条
  噪音；报告和 Web 只显示 C3 总体及 YES/NO 归因。

### 循环趋势 Shadow C4 与实验控制台

- 新增独立 `shadow_c4_start` 前瞻边界。C4 沿用 C3 的趋势、点差、深度、动态费用和退出
  门禁；首轮退出后连续 30 分钟无趋势才重新武装，每事件最多两轮。
- 新增通用 `experiment_orders` / `experiment_rearms`，每轮独立记账，同时报告事件数和重复
  入场数，避免把同事件多轮误当成独立天气样本。C3 数据表和一事件一单约束保持不变。
- Web 重构为 Hold/C3/C4 可展开实验矩阵，规则、样本、方向归因、持仓与 24h 活动集中呈现；
  当前持仓支持键盘可操作的实验筛选，移动端实验详情改为两列指标。
- 当前持仓查询改用 `(event_slug,bucket,id DESC)` 最新报价索引，避免对全量快照执行窗口排序。

### 验证与兼容性

- Web 看板升级为 Hold/C3 实验控制台：新增扣费每日收益图、主动策略对照、C3 YES/NO
  归因、Phase 1 门槛进度和滚动 24 小时覆盖/活动指标；停用策略不再占据主界面。生产数据
  视觉检查后，移动端把判断面板前置，持仓只首显 25 单、其余折叠，避免长表遮蔽关键状态。
- 修复 C3 未平仓仓位未出现在 Web 持仓表的问题；外部城市、bucket、方向和报价源在输出前
  统一 HTML 转义。页面继续使用服务端 HTML/CSS，无外部 CDN 或前端运行时依赖。
- Web 主收益口径统一为各自锁定边界后的扣费净收益；每日图与最近结算也扣除已记录的
  entry/exit fee，避免与旧全历史 gross 指标混淆。

- 生产库一致性副本完成 schema 迁移和完整 paper cycle：113 个事件、45 个候选，建立
  14 个 Shadow B，`PRAGMA integrity_check=ok`，历史报告数值保持不变。
- C3 部署后的生产首轮扫描 109 个事件、40 个原策略候选、新开 3 单；C3 在 180 分钟
  自然预热期内为 signals/executable/opened/closed = 0/0/0/0。边界后已正常写入同源
  参考报价，Shadow B 最后一单早于 `shadow_c_start`，确认不再新增。
- 首次同时重启 paper/Web 暴露 `ALTER TABLE` 检查与执行间的竞态；一个进程曾报一次
  duplicate column 后由 systemd 恢复。迁移现已在失败后复查 schema，若同列由另一进程
  创建则幂等成功；热修重启后三个服务 active、零重启，Web HTTP 200、`quick_check=ok`。
- `cargo test`：54 tests passed；清理 6 个既有 Clippy 告警和旧格式差异后，零豁免
  strict Clippy、`cargo fmt --check`、release build 与生产部署验证通过。
- 策略仍为纸面交易；没有新增认证、签名、私钥或真实下单路径。
