# Phase 1 验证记录

纸面交易期间的阶段性发现。只记结论和证据，方法可复现（SQL 见文末）。
判定标准见 README「验证 edge 的标准」；此处不做提前结论。

## 2026-07-08：首个结算日复盘（样本：29 单，1 个结算日——一切结论都是初步的）

数据快照（服务器库，起跑 2026-07-06）：
已结算 29 单 / $745.63，净 **-$72.99（-9.8%）**，另有 40 单 open。

### 发现 1：方向强不对称——YES 全灭

- YES：12 单全输，-$129.80（本金全灭）
- NO：17 单赢 14 单，+$56.81（+9.2%）

与 STRATEGY.md 预期的失败模式吻合：原始 ensemble 过度自信，给具体 bucket
塞过高概率 → 买入便宜 YES → 实际落在邻近 bucket。NO 赢钱一部分是
favorite-longshot bias 兑现，一部分是"赌单一 bucket 不中"天然容错。
亏损集中在 Ankara(-60)/Munich(-53)/Milan(-48)，Tokyo/Tel Aviv/Shanghai 为正
——站点级偏差特征，指向 Phase 2 按站点校正。

### 发现 2：浮动 P&L 与结算 P&L 的落差不是记账错误

07-07 11:40 UTC 看板浮盈 +235，当日最终结算 -73。回放 snapshots 报价路径：

- 赢家（全 NO）的浮盈峰值 ≈ 最终结算值（如 Tel Aviv 30°C NO：峰值 42.50 →
  结算 +42.59），早收敛、拿得住。
- +235 里输家贡献很小（Singapore 32°C NO 峰值仅 +4.55，Munich 30°C NO 仅
  +0.85，当时还没露败相）。午后 METAR 实测出来，市场重定价，四笔 $50 大单
  塌掉约 -200。

结论：看板浮盈（按 top-of-book 可平仓价计）与结算都没算错；落差 = 市场当天
下午"学到"真实温度。**不采用"按当日最高价结算"**——那是前视偏差，会把
上帝视角收益记成策略收益。

### 发现 3：止盈规则回放（初步，勿当结论）

事前规则"浮盈达到本金 t 倍时按当时 bid 卖出，否则拿到结算"，对 29 单回放：

| t | 触发单数 | 净 P&L |
|---|---|---|
| 0.2 | 17 | -13.93 |
| 0.5 | 9 | **+24.88** |
| 1.0 | 2 | -58.53 |
| 2.0 | 1 | -63.15 |
| 不止盈（现状） | — | -72.99 |

警示：t=0.5 的正收益几乎由 Milan 34°C YES 一单驱动（+25 卖出 vs -50 结算，
单笔摆动 $75）；阈值-收益非单调说明噪音主导；回放按 top-of-book 全额成交，
未计深度，是乐观上界。**29 单挑最优阈值 = 过拟合。**

值得跟踪的结构性迹象：赢家浮盈峰值≈结算值 → 止盈对赢家近乎无代价、只对
输家有救。若 100+ 单后不对称仍成立，止盈进策略候选。

### 决定

1. 结算口径不改（hold-to-settle 是 Phase 1 要测的东西）。
2. 止盈假设列为待验证项，样本 ≥100 单后用完整数据重跑回放再定
   （届时可固化为只读子命令，如 `weatherbot replay --take-profit`）。
3. 优先级：YES 端系统性亏损 > 止盈。方向错是出血点，止盈只是止血。

## 2026-07-10:三个结算日复盘(样本:69 单结算,数据 = data 分支备份 fe7cf04,截至 07-09 12:30 UTC)

已结算 69 单 / $1544.91,净 **-$128.03(-8.3%)**,另有 55 单 open。
按天:07-07 结算 -40.24,07-08 结算 -87.78。

### 发现 4:YES/NO 不对称在第二、三个结算日继续成立

- YES:21 单 1 胜,-$196.51(**-88.7%**)
- NO:48 单 36 胜,+$68.48(+5.2%)

两个独立结算周期同向,合计 33 单 YES 仅 1 胜。校准数据定位了病根:
model_prob ≥ 0.9 的 YES 单(模型均值 1.00,市价均值 0.24)实际胜率 **11%**;
NO 单同层(模型 0.99,市价 0.71)实际胜率 0.74——**市价比模型准**,
所谓 edge 主要是模型误差。与 STRATEGY.md"欠散布假象"预期一致。

### 发现 5:名义 edge 与实际收益反向

| edge 层 | n | ROI |
|---|---|---|
| <0.20 | 31 | +9.7% |
| 0.20-0.35 | 19 | -19.0% |
| ≥0.35 | 19 | -22.6% |

NO 端更陡:edge<0.20 → 22 单 21 胜 **+30.4%**;edge≥0.20 → 净亏。
解释:模型与市场分歧越大,越可能是模型错(粗网格站点偏差),
"大 edge"实为模型错误的信号而非机会。

### 发现 6:止盈回放(69 单)——只对 YES 有救

hold-to-settle 基线 -128.03;止盈(浮盈 ≥ t×本金 按 top-of-book 卖出):

| t | 0.1 | 0.2 | 0.3 | 0.5 | 0.75+ |
|---|---|---|---|---|---|
| 净 P&L | +51.8 | +32.6 | +91.3 | +19.9 | 负 |

按方向拆:止盈对 NO 无益(hold +68.5 ≥ 各阈值),对 YES 是急救
(-196.5 → +5~+35,t≤0.3)。输家 32 单持仓中合计出现过 +$163 浮盈峰值,
最终结算 -$559——"中途有得赚"是真的,但集中在 YES 输家身上。
最优阈值从上次的 0.5 移到 0.3,非单调依旧 → 阈值本身仍是噪音,
结构性结论只有一条:**若不开 YES,止盈基本无用**。

### 发现 7:移动止盈(trailing stop)全面差于固定止盈

用 snapshots 回放"浮盈从峰值回撤 dd×本金即卖出"(可选:浮盈超过 arm×本金才启动):
dd∈{0.1,0.2,0.3,0.5} × arm∈{0,0.1,0.2} 共 9 组,净 P&L 全部为负
(最好 -11.8,对比固定止盈 t=0.1~0.3 的 +33~+91,hold 基线 -128)。
机制:输家崩盘是午后 METAR 实测出来后的**跳空重定价**,不是阴跌;
回撤信号触发时价格已在低位,卖在崩盘后。固定止盈卖进强势,移动止盈追认弱势。
基础设施结论:不需要 redis/memcache——snapshots 表(10 分钟/轮)就是价格记录,
任何止盈逻辑只是 paper 循环里的内存变量。

### 发现 8:预报精度首次量化——系统性偏冷 1°C,原始精度不支持赌单一桶

对 31 个已结算事件,取结算日前一天最后一次 ensemble 共识中位数 vs 实际结算桶:

- **bias -1.01°C(26/31 天偏冷)**,MAE 1.34°C,|err|≤1°C 仅 **42%**
  ——桶宽 1°C,即原始预报大多数时候不落在正确桶,YES 全灭的直接原因。
- 全局 +1°C 修正(仅去均值):MAE → 0.95,|err|≤1 → **71%**。
  Phase 2 只做这一步就能翻倍命中率;按站点修正空间更大
  (Chengdu -3.0 / Seoul -3.0 / Taipei -2.0 / Ankara -2.0)。
- 按模型:icon MAE 1.14 最准,ecmwf 1.28,gfs 1.87,**cma 2.28 最差(bias -1.85)**
  ——CMA 权重需下调,与"中国站点重点验证 CMA"的 Phase 2 计划一致。
- Tokyo 是唯一显著偏暖站(+1.6),方向与此前实测(偏暖 2-6°C)一致。

### 发现 9:Phase 2 第一步完成——全站点 130 天偏差回测与站点白名单

不等 100 单门槛(偏差估计与交易样本无关),用 historical-forecast API
(4 模型共识中位数)× IEM ASOS 实测日最高温(METAR 同源),对 48 站
回测 2026-03-01 ~ 07-08,滚动 30 天去均值校正(严格 out-of-sample,
窗口 45 天无增益)。判据 = Wenth 信息论死线:校正后 MAE 须 < 桶宽(1°C)。

汇总(试点 4 站):原始 bias -1.32 / MAE 1.56 → 校正后 MAE 0.84,
±1°C 命中 49% → 67%。与 3 天实盘估计(bias -1.0)同向,偏冷是普遍现象
(几乎全部站点 raw bias < 0)。

站点分层(校正后 MAE):

- **白名单 ≤0.8(34 站)**,前列:Warsaw .46 / Miami .47 / Atlanta .50 /
  Tel Aviv .51 / Madrid .51 / Amsterdam .53 / London .53 / Houston .54 /
  Paris .55 / Austin .55 / Shenzhen .59 / Dallas .62 / Istanbul .63 /
  Ankara .65(raw 1.35→.65,校正收益最大类型)/ Manila .66 / Milan .66 /
  Munich .67 / Singapore .67 / Tokyo .70(raw 已 .70,无需校正)/
  Zhengzhou .71 / Shanghai .77 / NYC .77 / LA .77 …
  美国站结算桶宽 2°F(≈1.11°C),白名单内美国站余量更足。
- **边缘 0.8-1.0(8 站)**:Helsinki .80 / Qingdao .84 / Lucknow .91(唯一显著
  偏暖站,raw +1.06)/ Beijing .91 / Wuhan .92 / SF .93 / Chengdu .96 / Moscow .96
- **剔除 >1.0(6 站)**:Guangzhou 1.01 / Chongqing 1.03 / Taipei 1.11 /
  Jeddah 1.16 / Seoul 1.19(raw bias **-3.35**,仁川沿海站,网格完全失真)/
  Denver 1.19(高原)
- 无数据:Wellington、香港(HKO 非机场站)、济南(IEM 样本不足)

对 STRATEGY.md §B"中国站点差异化"假设的打击:中国站校正后普遍中偏差
(广州/重庆剔除,北京/成都/武汉/青岛边缘),**校正得最干净的是欧美主流站**
——差异化赌注方向需要重新评估。

注意:±0.5°C(=单桶精确命中)最好的站也只有 ~60%,校正后赌单桶 YES
仍然不到六成胜率,NO 侧/多桶结构还是主用法。历史预报 API 拼接的是
短 lead(0-1 天)预报,实盘 lead-1 的 MAE 会略差于此。

### 发现 10:"中国盘是洼地"说法核实——部分成立,但洼地不在盘口价,edge 也不是预报

Grok 深搜 X(35 源)+ 自库点差验证:

- **上海不是洼地**:全球最高成交量天气盘之一(单日 $100K-$500K),算法玩家密集,
  定价效率高。真正低关注的是二线(成都/武汉/重庆/深圳)。
- **实锤盈利者存在,但打法是当日盘**:cmcbrown 钱包 3 个月 ~540 笔全部中国城市,
  +$12K,月命中率 93-97%——交易集中在 4am-12pm UTC(中国午后,当日最高温
  锁定期),买 24-87¢ 的 near-certain band。**这是实测驱动的当日盘打法
  (Wenth 说的 latency edge),不是预报打法**。另有用 CMA+卫星者 +$14.9K。
- **自库证伪"定价粗糙"**:snapshots 16 万条有效报价,top-of-book 点差
  中国盘 0.024 vs 其他 0.025,无差别;成都/重庆/深圳 0.023 反而全场最窄。
  洼地的实质 = **深度薄**(bot 代码注释 FAK 常被拒、须 GTC 挂单)+
  当日实测反应慢,不是盘口价懒。
- **结算源风险实锤(直接影响我们)**:深圳 ZGSZ 曾发生 Wunderground feed
  错拉香港流浮山站数据(与 METAR 差 2°C),有人 99.8¢ 的 NO 亏 $7.8K;
  Polymarket 多次在 WU↔NOAA 间切换结算源。深圳是我们白名单里最好的中国站
  (0.59),**入场前必须核对该市场 rules 当前指定的结算源**。
- bot 已大规模覆盖中国城市(PolyWeather 52 城、StormBot 67 城),
  非无人区,但结合本地源的 niche 未被吃干净。

结论:对"预报流"的我们,中国站没有额外 edge(发现 9:校正后中国站 MAE
反而偏差),二线中国盘的真实机会属于当日盘 obs 打法(Phase 3+ 议题)+
薄深度下的 maker 挂单(Phase 3 议题)。

### 发现 11:CMA 消融与散布量化——两个"待办"一个划掉一个定参

- **CMA 不用动**:12 站消融(6 中国 + 6 对照),滚动校正后 4 模型 vs 无 CMA
  的 MAE 无差别(中国站 0.86 vs 0.87,其他 0.63 vs 0.64)。中位数共识对
  单个坏模型鲁棒,去偏又吸收了它的系统偏差。"下调 CMA 权重"从待办划掉。
- **散布放大系数 ≈1.2x,不是主要问题**:31 个结算事件的 PIT 分析,原始
  ensemble 两端溢出 35%(理想 10%),但去掉全局 -1°C 偏差后,纯散布系数
  只剩 1.1-1.3x。**model_prob=1.00 的"过自信"主因是偏差,不是散布**。
  Phase 2 配方定型:站点级滚动去偏(主修正)+ 散布 ×~1.2(辅修正,
  样本 n=31 偏小,随结算数增长复核)。

### 发现 12:影子校正 3 日回测——概率变准了,但仍不如市场

对 47 个已结算事件重构校正概率(偏差严格 OOS:窗口截止 07-06,不含评估日;
散布 ×1.2),事件级 Brier(越低越好):

| 原始 ensemble | 影子校正 | 市场 mid(归一) |
|---|---|---|
| 0.0769 | **0.0696** | 0.0576 |

校正把概率质量提升 ~9.5%,方向正确;但**市场仍显著更准**——校正后
相对市场的 edge 依然为负。订单级反事实(117 单已结算,按"校正 edge ≥0.08"
过滤):保留的 37 单 -6.4%,砍掉的 69 单 -4.1%——**校正概率当交易过滤器
在本样本上不能止损**,留下的单甚至更差。

解读:去偏+散布修正让模型往市场靠(分歧收窄),但收窄的终点是"和市场
一致"而不是"超过市场"。与信息论判据自洽:校正后 MAE ≈0.85 仍贴着桶宽。
**仅靠(站点×kind)去均值,Phase 2 不过关**;要么上条件化维度
(风向/lead time/状态,husky 路线),要么接受"次日预报流无正 edge"并
转向当日盘/maker 方向。样本仅 3 个结算日、事件间相关,勿过度反应;
影子记录继续攒,每个结算日自动加样本。

### 发现 13:止盈回放 ≥100 单复验(兑现发现 3 的决定)——0.1~0.3 平台成型

117 单已结算(hold 基线 **-176.41**;NO +29.6 / YES -206.0),固定止盈回放:

| t | 0.1 | 0.2 | 0.3 | 0.5 | 0.75 |
|---|---|---|---|---|---|
| 净 P&L | +95.6 | +85.8 | +87.5 | -18.6 | -136.1 |

相比 69 单时的非单调噪音,0.1~0.3 现在是**平坦台面(~+90)**,阈值不敏感;
且两侧都受益(t=0.2:NO +50.7 > hold +29.6,YES +35.1 > hold -206)。
止盈从"噪音"升级为**严肃候选**。但两个折扣不变:回放按 top-of-book
全额成交 = 乐观上界;Wenth 实盘证据(profit-lock paradox)方向相反。
决定:纸面循环仍 hold-to-settle(对照基线不动摇);止盈任何变体都可从
snapshots 免费重放,无需改码,真实决定推迟到 Phase 3 实盘设计时
(实盘退出吃点差,纸面测不出来)。

### 决定(候选,待 100 单门槛确认)

1. 候选策略 A:**只开 NO + edge<0.20 过滤**。在本样本 = 22 单 21 胜 +30.4%,
   但这是事后过滤,有选择偏差;不改代码、不改现有循环,
   继续按现规则攒样本,分析时按 A 口径前瞻跟踪(纸面全记录,SQL 过滤即影子策略)。
2. YES 端:等 100 单时若仍 <20% 胜率,Phase 2 校正前直接禁开。
3. 止盈:降级为 YES 专属议题(固定阈值;移动止盈已否决,见发现 7)。
4. 发现 8 把 Phase 2 的第一步锁定为"去均值偏差修正"(全局 -1°C 起步,
   按站点细化),不用等 100 单——偏差估计用的是 forecasts×settlements,
   与交易样本无关,每个结算日都在自动加样本。

## 2026-07-12：215 单复盘与执行层修复（发现 14）

生产库截至 03:43 UTC：已结算 215 单 / 87 个事件 / 投入 $3779.28，净
**-$90.61（-2.4%）**。07-10 +$78.86、07-11 +$6.93，使累计亏损从前三个
结算日的 -$176.40 收窄，但最新 74 笔可报价持仓仍浮亏 -$47.14（-6.3%），
所以只能称反弹，不能称 edge 已恢复。

方向分层继续稳定：NO 142 单 +$71.22（+2.1%），YES 73 单 -$161.84
（-35.9%）。候选策略 A 更新为 58 单 / $1243.62 / +$192.27
（**+15.5%**）：其中 8-12% edge 仅 +0.7%，收益集中在 12-20%（+20.9%）；
且 07-11 单日 A 为 -12.7%，仍非无条件稳健。该组合此前是事后筛选，本次开始由
`bot_meta.shadow_no_08_20_start` 固定生产前瞻边界，report 分开显示 history 和
forward-only；基线下单规则不变。

同时发现两个执行问题并修复：

1. 8 笔香港过期未结算仓位锁住 $86.04；其中已无历史预报小时，循环每 10 分钟
   重试 Open-Meteo 只产生噪音。新逻辑仍把它们计入敞口并轮询 Gamma 结算，但不再
   请求过去日期的预报；报告/看板单列 pending resolution。
2. 原逻辑在扫描过程中立即落单，达到 $800 上限后，Gamma 返回顺序会决定哪些信号
   入选。新逻辑先记录全市场 snapshots、收齐候选，再按 Phase 1 raw edge 排序统一
   分配额度并作稳定 tie-break。注意这只是消除扫描顺序偏差，不推翻“raw edge ≥20%
   历史更差”的统计事实；校正概率继续只做 shadow。

阶段裁定：数量门槛虽已超过 100 单，但总 ROI -2.4% 未达到 +3%，且独立事件仅 87，
**仍不进入 Phase 3**。maker 只做数据准备，不把假设成交计入收益。

### 复现方法

服务器库处于 WAL 写入时不要直接 `cp` 单个 db 文件；使用 Python `sqlite3.Connection.backup`
生成一致性快照后再查，并以 `PRAGMA integrity_check` 验证。直接复制曾产生可传输但损坏的
分析文件，容易把快照问题误判成生产库损坏。
回放核心：paper_orders 按 `event_slug + bucket` join snapshots（ts ≥ 下单时刻），
退出价 YES = best_bid、NO = 1 - best_ask（与 src/store.rs `exit_price()` 同口径），
浮盈 = shares × exit_p - usd，按订单取峰值 / 按首次触发阈值时刻模拟卖出。

发现 9 偏差回测（可独立重跑）：
- 预报：`historical-forecast-api.open-meteo.com/v1/forecast?latitude=..&longitude=..
  &daily=temperature_2m_max&models=ecmwf_ifs025,gfs_seamless,icon_seamless,
  cma_grapes_global&start_date=..&end_date=..&timezone=auto`，取 4 模型中位数
- 实测：`mesonet.agron.iastate.edu/api/1/daily.json?station=<ICAO>&network=<CC>__ASOS
  &year=..&month=..` 的 max_tmpf（美国站 id 去 K 前缀、network 为州级如 NY_ASOS）
- 校正：第 t 天用 [t-30, t-1] 窗口内（共识−实测）均值（≥15 样本才生效），
  校正误差 = 原始误差 − 窗口均值；坐标/时区取 stations.toml

## 2026-07-14：335 单复盘，YES 停开 + 三过滤器上线（发现 15）；METAR 击穿退出（发现 16）

样本：07-06 分配修复重置后一周，335 单结算（50% 胜率，净 -178.59）。

发现 15 —— 亏损是结构性的，全部指向"原始 ensemble 过度自信"：

- **方向**：NO 210 单 +102.0（+2.5% ROI）；YES 125 单 -280.6（-41.1%），且 YES
  在每个 edge 区间都亏（胜率 15%）。model_prob≈1.0 的 YES 单实际命中率仅 17%。
- **edge 上限**：edge ∈ [0.05,0.30) 共 144 单 +169.0；edge ≥0.30 共 191 单
  -347.6（胜率 31%）。分歧越大越是模型错，市场是对的。
- **价格下限**：入场价 <0.10 共 52 单，胜率 4%（-60% ROI）；0.75+ 共 92 单
  +175.0（胜率 90%）。
- **城市**：Ankara -137 / Munich -104 / Wellington -81 为慢性偏差重灾区；
  Chongqing +129 / Paris +62 / Tel Aviv +58 稳定盈利。
- 影子校正当否决器已有正贡献：能匹配 model_prob_corr 的单中，校正否决的
  32 张 YES 亏 -66.7（识别成功），误杀 NO 仅 11 张 +12.1；但覆盖率 42%，
  且校正后仍保留的 YES 也亏 → 直接停 YES 更稳。

反事实：只做 NO + edge<0.30 = +293.1（+12.5% ROI，胜率 87%）。仅一周样本，
"卖彩票"式高胜率的尾部风险未暴露，**继续纸面 2-3 周再评估 Phase 1 门槛**。

落地（config 可回调，不用改码）：`enable_yes=false`、`edge_cap=0.30`、
`min_entry_price=0.10`、`cities_blacklist=["Ankara","Munich","Wellington"]`
（黑名单只挡新开仓，持仓仍 quote-only 刷价）。

发现 16 —— METAR 击穿退出（src/metar.rs + prob::bucket_decided）：

持仓进入测量日后，结算站运行极值单调（highest 只升、lowest 只降），一旦已
决定某 bucket 输赢（如运行最高温越过所持 NO 的 "X or above" 界），死仓立即
按 CLOB 现价吃单抢救残值，不再扛到归零。只在 quote_source=clob 时成交，
Gamma 陈价只等下轮。锁定赢的仓位不提前卖（结算拿全额）。提前平仓单
status='closed'，P&L 与结算净值分开统计（report/看板单列），保持 Phase 1
门槛口径可比。HKO 无 METAR，跳过。

## 2026-07-15：Open-Meteo 限流与残缺 ensemble 门禁（发现 17）

07-14 生产检查发现：活跃缓存键约 147 个，原 60 分钟 TTL × 4 模型的理论请求量
约 14,112 次/日，超过 Open-Meteo 免费接口 10,000 次/日限制。最近一小时实测
432 次 HTTP 429；ECMWF/GFS/ICON 最后成功停在 07:42 UTC，而 CMA 仍继续返回。

旧逻辑只要求“至少一个模型成功”，导致三个 ensemble 失败时，单成员 CMA 被缓存
并当作完整概率分布。08:31 UTC 后已有多笔订单记录 `model_prob=1.0`，这不是有效的
ensemble edge，而是数据完整性错误。

修复原则：

- 三个配置的 ensemble 都成功才算完整批次；确定性 CMA 只作可选补充，不能单独
  维持概率输出。
- 刷新失败时仅复用不超过 12 小时的上一个完整批次，绝不让残缺批次覆盖缓存或
  写入 forecasts；没有完整缓存则 fail closed，不产生信号。
- HTTP 429 触发全局 30 分钟退避，其他单键失败同样退避，避免 10 分钟循环放大故障。
- TTL 从 60 分钟调至 360 分钟，与全球 ensemble 6-12 小时更新频率对齐，理论请求量
  降至约 2,352 次/日。历史 forecasts 不删除，保留审计与校准原料。

## 2026-07-17：588 单复盘与 allocation v2（发现 18）

生产一致性快照截至约 01:49 UTC：588 单 settled、279 胜，结算净 P&L
**+$122.72**；另有 13 笔 METAR 击穿退出，$60.38 本金实现 -$42.27，但抢救回
**$18.11（30%）**，所以不能只看退出 P&L 就判断该规则有害。当前 97 单 open、
$797.48/$800 敞口已满，其中 17 笔过期未 resolve 锁住 $110.60；循环每轮仍发现
33-42 个候选但无法新开。

影子 A（NO、raw edge 8-20%）全历史 109 单 / $1566.06 / +$226.20
（**+14.4% ROI**），固定边界后的前瞻样本 28 单 / $86.85 / +$13.95
（**+16.1%**）。但旧 allocator 按 raw edge 降序，当前 open 资金只有 $162.28
在 8-20%，另有 **$635.20 在 20-30%**；这会让要验证的前瞻组合长期缺样本。

raw edge 不是单调质量分数：NO 历史 8-12% +3.7%、12-16% +20.0%、16-20%
+18.4%、20-24% **-16.4%**、24-30% +13.5%、30%+ **-12.0%**。因此 allocation
v2 不再让最大 raw edge 自动先占满总额度，而是优先 8-20% 验证层，再在层内按 edge
降序，交易准入仍保持 NO、edge [0.08,0.30)、price≥0.10；这是资金分配实验，不把
影子校正概率提前用于交易。

事件集中度也有风险信号：在 NO、edge<0.30 历史中，每事件 1 单为 +13.7% ROI、
2 单 +11.9%、3 单 -1.1%；4+ 虽为 +19.6%，但只有 3 个事件，不能据此放大集中度。
allocation v2 对新仓设置每事件最多 2 单；已有仓不强平。

执行层抽样显示，新过滤器下 8-20% 订单入场平均 YES spread 约 2.93¢，20-30%
约 2.16¢；12 小时后两层 mid 相对入场分别约 +2.75¢、+1.52¢，说明 maker 研究
可能有价值，但 10 分钟 top-of-book 触价不能证明排队成交。官方 WebSocket market
channel 才提供实时 book/price/trade 事件，hftbacktest 也明确要求队列模型并警告 replay
不会产生真实市场冲击。因此本轮只新增 `best_bid_size`/`best_ask_size` 采集，不改 Phase 1
taker 成交口径；完整 L2/队列回放仍属于 Phase 3 前验证。

allocation v2 继续沿用发现 17 已验证并写入 `config.toml` 的 360 分钟 forecast TTL，
部署时不得用旧的 60 分钟配置覆盖生产门禁。

## 2026-07-17：forecast 冷启动恢复与请求合并（发现 19）

allocation v2 部署后的首轮扫描在服务重启约 87 秒后遇到 Open-Meteo HTTP 429。
发现 17 的 fail-closed 门禁工作正常：没有完整内存缓存的站点全部跳过，没有用残缺
ensemble 开单；但生产 `forecasts` 表明这些键在 12 小时内已有完整批次，纯内存缓存
使重启无谓地重新请求上游。

本轮把最近完整批次作为可恢复运行状态：新批次以同一时间戳事务写入；冷启动按
（station、target_date、kind）寻找 5 秒窗口内同时含 ECMWF/GFS/ICON 的最新批次，
残缺的新批次不能遮蔽旧的完整批次。恢复数据仍保留原始 fetched time，6 小时 TTL
和 12 小时最大陈旧门禁不会因重启重新计时。

Open-Meteo 官方接口与实测均支持 `models` 列表。ECMWF/GFS/ICON 现合并为一个
ensemble HTTP 请求，CMA 保持一个可选确定性请求，每键由 4 次降为 2 次；GEFS
响应使用 `ncep_gefs_seamless` 后缀，解析器显式映射回配置名 `gfs_seamless`。
此外按缓存键加入最多 60 分钟稳定刷新错峰、请求间隔和累计缓存/429 指标。该改动
不改变概率、edge 或成交口径，只降低冷启动和同步过期造成的上游压力。

## 2026-07-17：固定 lead-time 影子校准（发现 20）

旧 `calibrate` 从 Historical Forecast API 读取各模型短时片段拼成的 daily extreme，
它适合站点总体偏差，却不保留“这次预测提前了多久”，因此不能支撑策略要求的
（站点×lead time）校准。Open-Meteo 官方 Previous Runs API 明确定义
`previous_day1/2/3` 为有效时刻前 24/48/72 小时的预测，本轮实测也确认
ECMWF/GFS/ICON/CMA 可在一个请求中返回这些固定提前量的小时温度。

新链路对每个模型先计算站点本地日最高/最低温，再取跨模型中位数，与 IEM ASOS
的结算站 METAR 日极值配对。输入写入 `calibration_observations`，主键为
station×kind×lead_days×target_date，避免把 10 分钟 paper 循环产生的重复预报当成
独立样本。最近 30 个目标日达到 n≥15 后写入 `station_lead_bias`；除拟合 bias、
raw MAE、残差标准差外，还保存严格 walk-forward 的同日期 raw/corrected MAE 和
validation_n，防止用训练集 MAE 宣称校正有效。

重试完成后的生产全量运行写入 13,065 条唯一观测和 294 条 lead 行；按行平均的同样本
walk-forward MAE 分别为 D+1 1.239→0.947、D+2 1.310→1.048、D+3
1.367→1.107°C，98 行中分别有 72/75/77 行改善。IEM 在数百次请求中出现三次
瞬时连接失败，因此校准专用 HTTP 读取增加三次有限退避重试；持续失败仍跳过该组，
不会沿用不完整响应或伪造观测。

paper/edge 的 `model_prob_corr` 优先选当前站点本地日期对应的 D+1/D+2/D+3 行；
精确行不足时回退 D+1 站点偏差，仍沿用保守的 1.2 倍 ensemble spread。raw 概率、
信号、Kelly、allocation v2 和 taker 纸面成交完全不变。下一道门槛是生产
walk-forward corrected MAE 稳定低于同样本 raw MAE，再评估风向/风速条件化与
是否允许 corrected probability 影响交易。

## 2026-07-17：公共 L2 与保守 maker 队列回放（发现 21）

Polymarket 官方 market WebSocket 以 asset ID 订阅，初始/成交后给 `book`，挂单或撤单
给 `price_change`（size=0 表示价位删除），撮合给 `last_trade_price`，并要求客户端每
10 秒发送 `PING`。本轮新增独立 `maker-observe`：只订阅最新策略候选涉及的
YES/NO token，每 10 分钟刷新集合；book/trade 写入 `clob_l2_events`，高频
price_change 只更新内存盘口，book 落盘前截为两侧各 top-5。模块没有认证、
EIP-712、私钥或订单端点，生产服务只能读取公共市场数据和写本地模拟表。

首次生产接入 194 个 asset 后 7 秒即收到 3,429 条事件；若与 paper 共用主 SQLite，
高频单行写会让主循环出现 `database is locked`。因此原始流改写独立
`weatherbot-maker.db`（WAL、7 天滚动、不进灾备），主 `weatherbot.db` 只保留低频
虚拟单状态。collector 故障或 L2 库锁不能再阻塞策略扫描、预报落库或纸面订单。

隔离与压缩版生产复验：订阅约 200 个候选 outcome assets，首批 281 条持久事件
（256 book、25 trade）平均 payload 587 bytes；主 paper 同期正常完成 cycle、数据库
integrity=ok，collector 无重启。建立 104 个 open 模拟单后出现 3 个 full fill，三笔均为
SELL trade 严格穿过虚拟 bid（不是撤单推测），符合保守规则。随后短时复查为 5 filled /
103 open；这仍只是启动期快照，不是可引用 fill rate。至少积累 24–72 小时并等 30 分钟
订单自然 expired 后，才比较
不同 queue_ahead/price/spread 桶的成交率和成交后 adverse selection。

每个最新策略候选最多保持一个 30 分钟虚拟买单，价格为对应 outcome token 的实时
best bid，数量沿用 signal 的 Kelly 美元仓位。`maker_sim_orders.queue_ahead` 从下单时
可见同价 size 初始化；为避免乐观偏差，撤单永不减少队列，BUY trades 不算消耗，
只有同价 SELL 成交累计达到 queue_ahead+本单 shares，或出现严格低于挂单价的 SELL
trade-through，才记整单 filled。该 fill rate 是回放下界，不并入 taker 纸面 P&L；
真实 maker 概率最终必须用 user channel 的 order/`size_matched` 与小额 post-only 单校准。

## 2026-07-19：maker 回放首个两日样本与量守恒成交规则 v2（发现 22）

7/17–7/19 生产回放共 13,614 笔虚拟单：逐单 fill rate 7.8%（逐日 7.5/7.7/9.0%），
按市场×天口径 54–56% 的报价市场每天至少成交一次；成交平均等待 12.2 分钟。
成交价平均比同快照 taker 成本（`signal_price`）省 4.2c（0.620 vs 0.663），成交后
60 分钟内成交价平均漂移 -1.5c、62% 低于成交价——逆向选择存在但不吞掉点差节省。
94.5% 的过期单在 30 分钟窗口内该价位零成交：瓶颈是市场流量，不是排队位置
（队列 <10 股成交率 11.4%，≥200 股 4.7%）。NO <0.30 档成交率 29% 远高于 ≥0.85 档的
3.8%，但便宜 NO 恰是被抛售方向，高成交率是逆向选择信号，不得当作机会。

复盘发现 84%（913/1,082）的 fill 由 v1 trade-through 规则判定：任意一笔严格低于挂单价
的成交打印，无论 size 多小都记整单成交。盘口因撤单（而非扫单）下移时这是乐观高估，
即上述 fill rate 主要建立在最松的假设上。成交规则改为 v2 量守恒：同价 SELL 先吃
`queue_ahead`、溢出按量计入新增 `filled_shares`；低于挂单价的 SELL 视为先打到我们
更优的 bid，只按该笔 size 计入；`filled_shares` 达到 shares 才记 filled，到期时留下
部分成交量。v1/v2 边界写入 `bot_meta.maker_fill_v2_start`，跨边界的 fill rate 不可比。

同时上线 improve 对照臂：同一候选并行模拟 bid+1c、queue=0 的挂单，仅当实时
best ask 高于加价后价位（不穿越）时才挂，与 join 臂在同一成交判定下 A/B，用于
Phase 3"排队 vs 加价插队"选型。`report` 新增结算对账段：已 settle 市场上的 maker
成交按 policy × 成交规则代际分组，对比同快照同数量 taker 进场的 P&L。schema 迁移
将 `maker_sim_orders` 的单列 UNIQUE 重建为 `(source_snapshot_id, policy)` 唯一索引，
历史行保留并默认 policy='join'。

## 2026-07-20：两日前瞻裁定、费用口径与止盈复验（发现 23）

截至上线前一致性快照，761 单 settled / 402 胜，历史结算 gross P&L +$253.20；最近
两个目标日分别 -$110.62、+$49.41。单日反弹没有扭转前瞻样本：allocation v2 上线后
82 单 / $675.31 / gross -$47.06（-7.0%）。按地区拆分的四种口径如下：

| 统计口径 | 中国大陆 ROI | 欧美 ROI |
|---|---:|---:|
| 全历史原始订单 | +22.5% | -6.0% |
| 按当前规则事后重算 | +2.0% | +8.3% |
| 事先锁定 Shadow A 前瞻 | -8.5% | -8.9% |
| allocation v2 后真实订单 | -16.6% | -9.7% |

因此不能得出“中国更适合”或“欧美更适合”：全历史中国优势没有在两个独立前瞻口径
复现；当前规则事后重算又是欧美更高，存在筛选偏差。能下的结论只有两条：两区都可能
产生候选，但**两区目前都没有证明费用后前瞻 edge**；地域不应继续作为主分流条件。
v2 也不能解释为确定地“让策略变差”——它只有两个结算日且首日恰逢大亏，但它至少
证明“优先分配 8–20% NO”尚未改善实现收益，不能晋级为实盘依据。

概率质量给出更直接的否定证据。v2 后可匹配的 80 个 settled 信号，Brier（越低越好）
为 raw 0.2321、固定 lead corrected 0.2385、同期市场中价 0.1998。校正概率不仅未击败
市场，还略差于 raw；ROI 波动不能掩盖“概率源没有信息优势”。后续报告从
`prob_score_v1_start` 起前瞻保存 raw/corrected/market 三列，避免事后补市场价格。

另一个遗漏是协议费。Polymarket CLOB market info 对当前 Weather condition 返回
`fd={r:0.05,e:1,to:true}`，taker fee = shares × 0.05 × p × (1−p)。旧订单只按 ask
记 gross，未保存当时费率；按当前曲线估算，v2 的 -$47.06 会变成约 -$57.47（-8.5%）。
不能把该反推值混入账本，所以新增 `fee_accounting_v1_start`：此后每单动态读取费率、
用含费有效价格重算 net edge 与 Kelly、保存 entry/exit fee；未知曲线直接拒单。

新的独立前瞻臂 Shadow B 由这些证据预注册：只做 NO、8%≤raw edge<20%、价格≥70¢、
费用后 net edge≥8%，每事件只取最高 raw edge，固定含费成本 $5。它写独立
`shadow_orders`，不占基线敞口、不与 Shadow A 历史拼接，边界为 `shadow_b_start`。
这不是宣称新规则已经盈利，而是降低单日/单事件相关性后重新取证。

### 10 分钟快照的提前退出回放

累计快照足够回放，但“按事后最高 bid 平仓”是未来函数。新增只读
`tools/replay_exits.py`：每单只用入场后**首次**达到阈值的 CLOB 可卖 bid，计当前曲线的
entry+exit fee；默认还要求顶层 size 足以一次卖完整仓。最接近 Shadow B 的历史代理
（122 事件、每事件一单、统一 $5）结果：

| 规则 | Hold | TP 5% | TP 10% | TP 15% | TP 20% | TP 30% |
|---|---:|---:|---:|---:|---:|---:|
| 扣费净 P&L | **+$50.32** | +$41.92 | +$34.87 | +$43.37 | +$43.76 | +$47.30 |

最近 v2 两日的 38 个 Shadow B 代理事件，hold +$1.46；上述全部阈值均低于 hold。
更重要的是，7/18 训练日会选 5% 止盈（相对 hold +$8.52），同一固定规则到 7/19
留出日却相对 hold **-$20.82**，是典型阈值过拟合。忽略深度的乐观 top-of-book 回放
结论也相同。结合发现 7 的 trailing-stop 失败，本轮裁定：**不上线价格止盈/移动止盈**；
仅保留测量日 METAR 已数学决定 bucket 输赢后的 knockout salvage。Shadow B 积累足够
前瞻样本后再免费重放，不为了“锁住历史最高利润”牺牲 hold 的已实现优势。

## 2026-07-20：双向趋势 Shadow C 预注册（发现 24）

固定止盈和 trailing stop 的历史回放都不支持自动上线，但这不排除“价格吸收新信息较慢”
这一不同假设。预测市场的异质信念模型可产生先低反应、后动量；时间序列动量文献则给出
可检验的趋势框架。不过它们不是天气市场小时级 edge 的直接证据，所以本轮没有把趋势
写入原策略，而是建立独立 `shadow_c` 前瞻臂。

C3 同时捕捉两边：Gamma YES 中价 30/60/180 分钟变化同为正时买 YES，同为负时买 NO；
60/180 分钟最小变化分别 3¢/5¢，每事件只取 logit 强度最大的 bucket。真实 CLOB 必须
满足 spread≤4¢、方向价格 10–90¢、顶档可一次成交固定含费 $5，且 60 分钟移动覆盖点差
与双边费用。30/60 分钟同时反转且 60 分钟反转≥3¢ 才全平；METAR knockout 保留。

为避免旧快照在 Gamma/CLOB 两种来源间切换制造假趋势，新增独立
`reference_bid/reference_ask`，CLOB 列仍只代表可执行报价。`shadow_c_start` 之前不回填，
生产升级后自然预热 180 分钟。因此当前没有合法的 C3 历史 ROI，任何用旧混源快照算出的
“漂亮回测”都不作为上线证据。Shadow B 停止新增但历史订单继续结算；主动比较只剩原策略
Hold 与 C3，减少小样本多重比较噪音。

## 2026-07-31：全候选流回放推翻 corr_gate 依据，Hold 规则被证伪（发现 25）

07-27 至 07-29 三天净 -159.61 / -128.44 / -184.51，触发复盘。表面看是集中度：三天里
单笔 $49 的满仓单吃掉了绝大部分（07-27 的 -152.8 里 3 单占 -138.6）。但真正的结论比
"运气差"严重得多。

### 反事实必须跑候选流，不能跑 paper_orders（方法论）

此前所有反事实（含 corr_gate_v1 上线依据）都是在 `paper_orders` 上过滤。哪些候选变成
订单由 `max_open_exposure_usd` 腾出空间决定，**样本被"要测量的那个东西"选择过**。
`tools/replay_rules.py` 改在 `snapshots` 的完整候选流上回放（每个 market×side 的首个
signal，1848 候选 / 573 已结算事件），置信区间按**事件** bootstrap —— 同一站点日的
bucket 互斥且共用一次预报误差，按订单重采样会把有效样本量高估约 3 倍。

| 规则 | n | 净额 | ROI | 95% CI | 最差目标日 |
|---|---|---|---|---|---|
| 原样（基线） | 1848 | -3889.9 | -6.82% | [-8.88, -4.79] | -619.8 |
| + corr gate | 1187 | -2301.0 | -6.87% | [-10.29, -3.45] | -511.1 |
| + corr gate + cap $20 | 1187 | -997.5 | -5.70% | [-8.80, -2.59] | -237.9 |
| + corr gate + 固定 $8 | 1187 | -375.1 | -3.95% | [-6.62, -1.18] | -97.1 |
| + corr gate + price≥0.50 + cap $20 | 1097 | -694.5 | -4.18% | [-7.36, -1.33] | -198.5 |

**corr_gate_v1 在全候选流上是 ROI 中性的**（-6.87% vs -6.82%）。发现 22 之后那条
"+9.4% vs -3.6%，permutation p=0.0006"就此撤回：它测的是 exposure cap 的选择效应。
门禁实现本身无误（0 例违规），保留运行，但不再作为有效性证据。

### 每个价格档、每个 edge 档都没有优势

| NO 买入价 | 候选 | 实际胜率 | 盘口隐含保本胜率 | 差 |
|---|---|---|---|---|
| 0.40–0.50 | 58 | 34.5% | 45.3% | **-10.8pp** |
| 0.50–0.60 | 181 | 56.4% | 55.2% | +1.2pp |
| 0.60–0.70 | 369 | 62.3% | 65.3% | -2.9pp |
| 0.70–0.80 | 593 | 72.2% | 74.1% | -1.9pp |
| 0.80–0.95 | 608 | 84.0% | 85.8% | -1.7pp |

raw edge 与结果无正相关，已实现口径下甚至反向（8–12% 档 -2.5%、12–20% -5.3%、
20–30% -21.9%），而 Kelly 正是按这个 edge 定仓。预报侧对得上：D+1 `highest` MAE
1.1–1.5°C 仍大于桶宽 1°C（Wenth 判据未过），且 `error = forecast - actual` 连续十天
稳定在 -0.5 ~ -0.7°C，高温系统性低估 —— 07-27~29 被打穿的 12 笔大亏单**全部**是高侧桶
（London 34°C、Madrid 39°C、Houston 94-95°F、Miami/Denver 90-91°F、Shenzhen 28°C）。

结论：**市场价比原始 ensemble 准，没有任何价格或 edge 区间存在 edge**。Phase 1 的
≥3% 门槛在这条规则上不可能达到，靠加过滤器调不出来。

### 本轮改动与未采纳项

`max_stake_usd` 50 → 20：撞上限的单只占已结算单数的 4.3%，却持有 31% 的本金、贡献
47% 的净亏损。它们的胜率与其余部分无差异，只是单独决定了当天的数字。

`max_open_exposure_usd` 维持 1600，但理由更换（见 config.toml）：cap 绑定时进场由
"哪个仓恰好结算"决定，会把上面那个选择偏差写进前瞻记录本身。

未采纳（记录以免重复讨论）：去掉 Kelly 改固定注在回放里最好（-3.95%），但会切断
Phase 1 的对照基线，用户选择先只降集中度攒样本。**追溯改写已开仓位金额或按当前策略
重跑历史订单被明确否决** —— 那会得到"入场用规则 A、仓位用规则 B"的混合记录，并让
看板上的前瞻 ROI 变成不可证伪的数字。"当前策略在历史上会怎样"由回放回答，不写回库。

## 2026-08-10：Hold 暂停与 WeatherNext 2 影子采集（发现 26）

截至 06:04 UTC 一致性生产快照，fee-aware Hold 已实现 1268 单 / $12941.62，净
**-$1109.96（-8.58%）**；raw/corrected/market Brier 分别为
0.2502/0.2517/0.2134。保守 maker v2 虽相对同快照 taker 节省约 6 个点，但 join 与
improve 的已结算回放仍为 -3.93%/-3.58%；有成交组胜率显著低于未成交组，符合 maker
adverse selection，不能靠执行层把负信号翻正。

修复 `tools/replay_rules.py` 直接从 snapshots 取每个 market×side 首次信号后，完整候选流
3160 单 / 1033 事件；当前 corr gate + $20 cap 为 **-5.12% ROI，事件 bootstrap 95% CI
[-6.99%, -3.19%]**。最高温 -5.27%（CI [-7.32,-3.23]）；最低温 -4.05%，CI
[-9.96,+1.15]，因此 paper_orders 上最低温的正收益是敞口释放顺序造成的选择偏差，不能
作为新规则。

裁定：`enable_hold_entries=false`，停止新增已被证伪的 Hold 仓位；已有仓位继续报价、
METAR knockout 和结算，完整 forecasts/snapshots 候选流及 maker replay 继续运行。
首次启用时写不可变 `bot_meta.hold_pause_v1_start`。

WeatherNext 2 官方/开放接口是 0.25°、6 小时、64 成员集合。Open-Meteo 固定 lead 历史
目前只暴露 ensemble mean，不能伪装成概率回测。用 49 个结算站、18383 个
站点×kind×lead 日样本核验：未校正 WeatherNext mean MAE 1.706°C，差于现有 1.254°C；
30 日纯历史滚动去偏后为 0.980°C，与现有 0.982°C 相当。最高温 D+1 仍较差
(0.964 vs 0.911)，最低温 D+1/D+2/D+3 略好 (0.891/0.932/0.963 vs
0.897/0.963/0.995)，但这只是中心值 MAE，不是 bucket Brier 或收益证据。

因此 `google_weathernext2_ensemble` 只作为 `shadow_ensemble_models` 获取并随不可变
forecast batch 落库；明确排除在 live probability、corr gate、排序和 Kelly 外。至少积累
100 个有市场中价的已结算前瞻事件后，再比较 WeatherNext 独立/混合 bucket Brier 与市场，
未同时击败当前模型和市场前不得恢复 Hold。
