A pre-registered, paper-only test of whether an LLM can out-forecast the market's own price. Nothing here places real orders.
| Category | n | Brier ours | Brier mkt | edge | hit |
|---|---|---|---|---|---|
| Climate and Weather | 349 | 0.258 | 0.139 | -0.119 | 60% |
| Commodities | 289 | 0.216 | 0.183 | -0.033 | 64% |
| Economics | 198 | 0.224 | 0.099 | -0.125 | 69% |
| Financials | 64 | 0.215 | 0.196 | -0.018 | 59% |
| Politics | 100 | 0.182 | 0.061 | -0.120 | 73% |
| Science and Technology | 35 | 0.183 | 0.061 | -0.122 | 66% |
| World | 2 | 0.041 | 0.000 | -0.041 | 100% |
| Context kind | n | Brier ours | Brier mkt | edge | hit |
|---|---|---|---|---|---|
| fred | 87 | 0.194 | 0.121 | -0.074 | 71% |
| news | 171 | 0.196 | 0.078 | -0.118 | 72% |
| none | 168 | 0.239 | 0.138 | -0.101 | 58% |
| nws | 326 | 0.255 | 0.134 | -0.122 | 61% |
| prices | 285 | 0.216 | 0.180 | -0.035 | 64% |
| Band | n | Said % | Actual % |
|---|---|---|---|
| 0.5-0.6 | 203 | 53% | 47% |
| 0.6-0.7 | 211 | 63% | 58% |
| 0.7-0.8 | 173 | 74% | 66% |
| 0.8-0.9 | 216 | 84% | 63% |
| 0.9-1.0 | 234 | 94% | 84% |
n_trades=530 total_pnl=$-2576.87 total_fees=$1164.45 win_rate=27%
| Ticker | Category | Our p | Mkt p | Close time | Rationale |
|---|---|---|---|---|---|
| KXDEEPSHARE-26SEP28-25.2 | Science and Technology | 0.50 | 0.02 | 2026-09-28T03:59:00Z | DeepSeek's share plausibly near this level given past dominance in cheap inference. |
| KXBABASHARE-26SEP28-6.2 | Science and Technology | 0.50 | 0.89 | 2026-09-28T03:59:00Z | Qwen's OpenRouter share plausibly near this level. |
| KXBABASHARE-26SEP28-6.5 | Science and Technology | 0.45 | 0.39 | 2026-09-28T03:59:00Z | Qwen's OpenRouter share plausibly near this level. |
| KXTOPUSAGEAI-26SEP21-ANTH | Science and Technology | 0.04 | 0.01 | 2026-09-28T03:59:00Z | Anthropic rarely leads OpenRouter weekly usage vs DeepSeek/Google. |
| KXXIAOMISHARE-26SEP28-1.9 | Science and Technology | 0.50 | 0.98 | 2026-09-28T03:59:00Z | Xiaomi is a newer OpenRouter entrant; share plausibly near this level. |
| KXXIAOMISHARE-26SEP28-2.5 | Science and Technology | 0.28 | 0.35 | 2026-09-28T03:59:00Z | Xiaomi's share reaching 2.5%+ is less likely for a newer entrant. |
| KXTENCENTSHARE-26SEP28-4.9 | Science and Technology | 0.25 | 0.01 | 2026-09-28T03:59:00Z | Tencent reaching near 5% OpenRouter share is a higher bar. |
| KXOPENSHARE-26SEP28-19.3 | Science and Technology | 0.32 | 0.01 | 2026-09-28T03:59:00Z | OpenAI exceeding ~19% OpenRouter share is less typical. |
| KXGOOGSHARE-26SEP28-18.3 | Science and Technology | 0.35 | 0.99 | 2026-09-28T03:59:00Z | Google's share growing but 18.3% is on the higher end of typical range. |
| KXGOOGSHARE-26SEP28-16.7 | Science and Technology | 0.55 | 0.99 | 2026-09-28T03:59:00Z | Google's OpenRouter share plausibly near mid-teens to high-teens. |
| KXDEEPSHARE-26SEP28-28.1 | Science and Technology | 0.35 | 0.01 | 2026-09-28T03:59:00Z | DeepSeek historically a top OpenRouter provider but 28%+ is a high bar. |
| KXANTHSHARE-26SEP28-2.5 | Science and Technology | 0.55 | 0.99 | 2026-09-28T03:59:00Z | Anthropic's OpenRouter share is typically low single digits. |
| KXANTHSHARE-26SEP28-3.1 | Science and Technology | 0.30 | 0.01 | 2026-09-28T03:59:00Z | Anthropic's OpenRouter share rarely exceeds low-3% range. |
| KXTRUMPAPPROVE-26SEP27-E38.6 | Politics | 0.05 | 0.24 | 2026-09-27T16:59:00Z | Exact tenth-point RCP average unlikely among many possible values. |
| KXIPHONERELEASE-IPHONE18PRO-26SEP28 | Financials | 0.96 | 0.50 | 2026-09-28T03:59:00Z | Apple debuted iPhone 18 Pro Sep 9; retail launch typically ~2-3 weeks later. |
| KXTENCENTSHARE-26SEP28-3.5 | Science and Technology | 0.50 | 0.01 | 2026-09-28T03:59:00Z | Tencent's OpenRouter share plausibly near this level; no exact figure available. |
| KXOPENSHARE-26SEP28-14.0 | Science and Technology | 0.65 | 0.99 | 2026-09-28T03:59:00Z | OpenAI historically holds a mid-teens OpenRouter share. |
| KXTRUMPACT-26SEP20-T10 | Politics | 0.30 | 0.01 | 2026-09-27T14:00:00Z | Ten+ actions in one week is a high bar vs typical pace. |
| KXTRUMPNOMNUM-26SEP20-T1 | Politics | 0.85 | 0.01 | 2026-09-27T14:00:00Z | Presidents almost always send at least one nomination weekly. |
| KXTRUMPAPPROVE-26SEP27-E38.7 | Politics | 0.05 | 0.64 | 2026-09-27T16:59:00Z | Exact tenth-point RCP average unlikely among many possible values. |
| KXTEMPMIAH-26SEP2706-T73.99 | Climate and Weather | 0.92 | 0.50 | 2026-09-27T10:00:00Z | NWS overnight low forecast 75F, well above 74 threshold at 6am. |
| KXTEMPMIAH-26SEP2706-T74.99 | Climate and Weather | 0.60 | 0.03 | 2026-09-27T10:00:00Z | Overnight low forecast exactly 75F; 6am likely near but not certainly below low. |
| KXTEMPCHIHS-26SEP2706-T48.99 | Climate and Weather | 0.95 | 0.14 | 2026-09-27T10:00:00Z | Chicago overnight low forecast 55F, far above 49 threshold. |
| KXTRUMPNOMNUM-26SEP20-T10 | Politics | 0.35 | 0.01 | 2026-09-27T14:00:00Z | Ten+ nominations in one week is above typical weekly pace. |
| KXTRUMPACT-26SEP20-T4 | Politics | 0.70 | 0.01 | 2026-09-27T14:00:00Z | Admin typically issues several actions weekly; 4+ plausible baseline. |
| KXLOWTCHI-26SEP26-T55 | Climate and Weather | 0.25 | 0.01 | 2026-09-27T06:00:00Z | NWS lows 55F overnight and Saturday night; min above 55 unlikely. |
| KXLOWTAUS-26SEP26-B66.5 | Climate and Weather | 0.02 | 0.03 | 2026-09-27T06:00:00Z | NWS lows 74-75F; 66-67 very unlikely. |
| KXLOWTAUS-26SEP26-T66 | Climate and Weather | 0.01 | 0.02 | 2026-09-27T06:00:00Z | NWS lows 74-75F; below 66 very unlikely. |
| KXHIGHTSATX-26SEP26-B94.5 | Climate and Weather | 0.28 | 0.59 | 2026-09-27T06:00:00Z | NWS Saturday high 93F, mostly cloudy; 94-95 plausible. |
| KXHIGHMIA-26SEP26-B87.5 | Climate and Weather | 0.40 | 0.24 | 2026-09-27T05:00:00Z | NWS Saturday high 87F, sunny then showers. |
| KXLOWTOKC-26SEP26-T70 | Climate and Weather | 0.45 | 0.01 | 2026-09-27T06:00:00Z | NWS lows 71F overnight, 70F Saturday night; storms may cool. |
| KXLOWTMIN-26SEP26-T58 | Climate and Weather | 0.15 | 0.01 | 2026-09-27T06:00:00Z | NWS lows 58F and 56F with rain; minimum above 58 unlikely. |
| KXLOWTDAL-26SEP26-T73 | Climate and Weather | 0.40 | 0.01 | 2026-09-27T06:00:00Z | NWS overnight low 73F, Saturday night 75F; min near threshold. |
| KXHIGHPHIL-26SEP26-B67.5 | Climate and Weather | 0.04 | 0.92 | 2026-09-27T05:00:00Z | NWS Saturday high 63F with rain showers. |
| KXHIGHPHIL-26SEP26-T68 | Climate and Weather | 0.02 | 0.06 | 2026-09-27T05:00:00Z | NWS high 63F with rain; 69+ very unlikely. |
| KXHIGHNY-26SEP26-B62.5 | Climate and Weather | 0.35 | 0.27 | 2026-09-27T05:00:00Z | NWS Saturday high 63F, light rain. |
| KXHIGHNY-26SEP26-T62 | Climate and Weather | 0.35 | 0.74 | 2026-09-27T05:00:00Z | NWS high 63F; rain may hold it to 61 or below. |
| KXHIGHMIA-26SEP26-B89.5 | Climate and Weather | 0.15 | 0.54 | 2026-09-27T05:00:00Z | NWS high 87F; 89-90 needs upside miss. |
| KXHIGHTBOS-26SEP26-B61.5 | Climate and Weather | 0.30 | 0.84 | 2026-09-27T05:00:00Z | NWS Saturday high 60F, patchy fog; 61-62 plausible upside. |
| KXHIGHTBOS-26SEP26-B63.5 | Climate and Weather | 0.08 | 0.15 | 2026-09-27T05:00:00Z | NWS high 60F; 63-64 needs notable upside miss. |
| Ticker | Our p | Mkt p | Outcome |
|---|---|---|---|
| KXTRUMPENDORSEMENTS-26SEP25-A5 | 0.70 | 0.01 | No |
| KXTEMPMIAH-26SEP2606-T73.99 | 0.85 | 0.98 | Yes |
| KXTEMPMIAH-26SEP2606-T75.99 | 0.15 | 0.01 | No |
| KXEOWEEK-26SEP12-0 | 0.90 | 0.50 | Yes |
| KXTEMPNYCHS-26SEP2606-T56.99 | 0.40 | 0.06 | No |
| KXTEMPMIAH-26SEP2506-T75.99 | 0.75 | 0.96 | Yes |
| KXTEMPMIAH-26SEP2506-T76.99 | 0.50 | 0.86 | Yes |
| KXGOLDD-26SEP2417-T4268 | 0.74 | 0.39 | Yes |
| KXBRENTD-26SEP2417-T100 | 0.40 | 0.49 | Yes |
| KXBRENTD-26SEP2417-T100.50 | 0.35 | 0.40 | No |
| KXWTI-26SEP2414-T88.99 | 0.96 | 0.98 | Yes |
| KXCBDECISIONMEXICO-26SEP24-H25P | 0.05 | 0.12 | No |
| KXCBDECISIONMEXICO-26SEP24-C50P | 0.05 | 0.03 | No |
| KXGOLDD-26SEP2417-T4258 | 0.82 | 0.48 | Yes |
| KXJOBLESSCLAIMS-26SEP24-205000 | 0.32 | 0.17 | No |
| KX30YMORTW-26SEP24-T7.08 | 0.15 | 0.01 | No |
| KX30YMORTW-26SEP24-T6.98 | 0.55 | 0.89 | Yes |
| KXWTI-26SEP2414-T90.99 | 0.92 | 0.94 | Yes |
| KXTEMPMIAH-26SEP2406-T70.99 | 0.97 | 0.99 | Yes |
| KXTEMPCHIHS-26SEP2406-T58.99 | 0.62 | 0.90 | Yes |
# PREREG.md — pre-registration of the gold-standard Kalshi forecaster
**Registered 2026-07-28 (America/Chicago), before any `source='ai'` forecast row exists.**
The git history is the proof: this file is committed at Phase 5, and the first production
(`source='ai'`) forecast is not created until Phase 7, after this commit. Any change to the rules
below requires a dated amendment appended to the "Amendments" section AND the owner's sign-off — the
original rules above the amendment line are never edited in place.
This is a paper-only research instrument. Nothing here places real orders. Educational / hypothetical.
---
## The pre-registered rules (copied verbatim from PLAN.md "LOCKED decisions")
1. **The model never sees the market price** in its prompt. We are testing independent skill;
showing the price lets the model echo the crowd and fakes calibration. Log `mkt_p` separately
at call time. (A later "sees-price" variant may be added as a separate scored segment. Not v1.)
2. **Question selection:** status open, `close_time` ≤ 30 days out, `volume_fp` ≥ 500, bid-ask
spread ≤ $0.10, category in: Economics, Financials, Commodities, Climate and Weather, Politics,
Science and Technology, World. Excluded: Sports, Entertainment, Mentions, Crypto, Elections,
Companies, Social, Health. Max **2 markets per event** (for ladders pick the 2 strikes nearest
$0.50 mid = nearest the money). Max **40 new forecasts per night**.
3. **One forecast per market**, made at first qualifying sighting, never revised. The model may
**skip** any question (no informational basis); skips are logged and cost nothing.
4. **Paper trade rule:** fills at the **ask** (not mid). Buy YES if `our_p − yes_ask − fee(yes_ask)
> 0.02`; buy NO if `(1 − our_p) − no_ask − fee(no_ask) > 0.02`. Kalshi fee per $1 contract:
`fee(p) = ceil_to_cent(0.07 · p · (1 − p))`. Flat $10 notional per trade, max 1 trade per event.
5. **Scoring:** Brier of `our_p` vs Brier of `mkt_p` (mid at call time) on identical resolved sets,
segmented by category and by context kind (fred / nws / prices / news / none), plus calibration
buckets. Voided/unresolvable markets are excluded. Only rows with `source='ai'` count
(`source='dev'` = build-time tests, never scored).
6. **Gates (evaluate at ≥150 resolved AI forecasts):** skill gate = our Brier < market Brier;
money gate = paper P&L > 0 net of fees over ≥100 trades. Both pass → owner may fund a real
bankroll ($500–2k, allowed to go to zero; separate authorization, separate build). Either fails
→ kill, write the post-mortem, keep the track record. Interim peeks fine; no action before n.
7. **Prompt discipline:** `PROMPT_VER` constant logged on every forecast; any prompt change bumps
it. LOUD failures only: a failed/malformed LLM call writes a `runs` row and stderr; **never**
silently fall back (market-radar's silent-fallback bug is the cautionary tale).
---
## Exact prompt text (PROMPT_VER = "v1")
The nightly batched call (`brain.py`, `--model sonnet`) emits ONE prompt built from a fixed
preamble plus one block per question. The preamble is **verbatim**:
> You are a calibrated event forecaster. For each question output a probability 0-1 that it
> resolves YES. You have NO market price and must not guess one - reason only from the evidence
> given. If you have no informational basis, set skip=true (this costs nothing and is better than
> a blind guess). Today is {UTC date} (UTC). Output STRICT JSON ONLY: an object mapping each
> ticker to {"p":<0..1>,"why":"<=20 words","skip":<bool>}. No prose outside the JSON.
Each per-question block that follows the preamble contains ONLY: the ticker, the question title,
its sub-title, its resolution rules, and the Phase-2 context pack (external evidence — FRED / NWS /
prices / news — which is itself price-free by construction; `context.py` contains zero Kalshi price
fields). **No market price, bid, ask, or implied probability is ever placed in the prompt.** This is
enforced structurally: `build_prompt()` is a separate pure function and the price fetch lives in
`_fetch_mid()`; a grep proves the string `_dollars` never appears in the prompt path.
If v1 is ever changed, `PROMPT_VER` is bumped (e.g. "v2") and forecasts made under different
versions are scored as separate segments — v1's track record is never retroactively altered.
---
## Gate arithmetic (exactly what `score.py` computes)
Scored set = resolved `forecasts` rows with `source='ai'`, `outcome ∈ {0,1}` (void `-1` and
unresolved `NULL` excluded), and both `our_p` and `mkt_p` populated.
- `brier_ours = mean((our_p − outcome)²)` over the scored set.
- `brier_mkt = mean((mkt_p − outcome)²)` over the identical set (the crowd's mid at call time).
- `edge = brier_mkt − brier_ours` (positive ⇒ we beat the market; lower Brier is better).
- Paper P&L: over settled `paper_trades` (`pnl` not NULL), `total_pnl = Σ pnl`, `n_trades = count`.
Per-trade P&L (LOCKED #4 `$1`-contract math, `contracts = $10 / entry_p`,
`total_fee = contracts · fee(entry_p)`): WIN `pnl = 10·(1/entry_p − 1) − total_fee`;
LOSS `pnl = −10 − total_fee`; VOID `pnl = 0`.
**Decision (only at `n_resolved ≥ 150`):**
- **skill_gate_pass** ⟺ `n_resolved ≥ 150` AND `brier_ours < brier_mkt`.
- **money_gate_pass** ⟺ `n_trades ≥ 100` AND `total_pnl > 0`.
- **Both pass** → the forecaster has earned a real-bankroll funding decision ($500–2k, may go to
zero; separate authorization + separate build). **Either fails** → kill it, write the post-mortem,
keep the documented track record as the durable asset.
- Before `n_resolved = 150`: interim peeks are allowed but **no action is taken** — `score.py`'s
verdict reads "accruing — N of 150 resolved; no decision yet".
---
## Note on the fee example in PLAN.md
PLAN.md's Phase-4 acceptance line ("fee(0.50) on 20 contracts = $0.70") is an arithmetic slip that
contradicts the LOCKED 0.07 coefficient. The **coefficient is unchanged** (`fee(p) =
ceil_to_cent(0.07·p·(1−p))`, i.e. $0.02/contract at p=0.50). The implemented order fee is
`contracts × fee(entry_p)` = 20 × $0.02 = **$0.40** at the example point. This clarification does not
alter any pre-registered rule; it records the correct arithmetic under the LOCKED formula.
---
## Amendments
(none — the rules above are the original registration. Append dated, owner-signed amendments below
this line; never edit the original rules in place.)