---
name: project-mm-logging-fields
description: Fields added to mm_paper_quotes.csv on 2026-07-28 to predict which legs sell — queue depth, market age, OI/volume, NO side, league-local hour, fill timing
metadata:
  type: project
---

Added 2026-07-28 to `main/mm_quoter.py`. All are LOGGING ONLY — nothing gates on
them yet, by design: gate thresholds should come from the data, not from a number
picked in advance.

| column | meaning | why |
|---|---|---|
| `ask_size` | size resting AT our ask | the queue ahead of us. THE variable every unresolved fill question turns on |
| `bid_size` | size at the bid | imbalance `bid/ask` is a classic short-horizon direction predictor |
| `volume` / `volume_24h` / `open_interest` | flow + positions | separates "deep queue in an ACTIVE market" from "deep queue in a DEAD one" |
| `open_time` / `mkt_age_h` | market age | the strategy rests on edge living in a market's first volume decile; we had been proxying that with hours-to-kickoff, a different quantity |
| `no_bid` / `no_ask` | NO-side book | selling YES == buying NO, so a deeper NO book would be a free queue upgrade |
| `local_hour` | hour of day in the LEAGUE's timezone (`LEAGUE_TZ`, 43 leagues, DST-aware via zoneinfo) | an Argentine book quoted into Buenos Aires overnight is dead regardless of queue |
| `filled_at` / `fill_secs` / `fill_kind` | in `mm_paper_state.json` | TIME-to-fill, not just whether |

**These had been fetched and discarded all along.** `yes_ask_size_fp` etc. were
in every Kalshi market response the quoter already pulled; they were simply never
written. Second time in two days a variable turned out to be present-but-dropped
(the other: the settler's truncated trade fetch). Worth auditing API payloads for
what else is being thrown away.

**Backfill status — matters when analysing:**
- `local_hour` is FULLY backfilled (60,458 rows) because it is reconstructable
  from `ts` + `div`.
- Queue/OI/volume/NO fields start **2026-07-28 17:17Z** and are NOT recoverable.
  Kalshi serves historical trades and candlesticks, but resting book depth is a
  point-in-time snapshot of orders that no longer exist. The ~54k older rows are
  permanently depth-blind.
- `filled_at` starts from the next fresh fill; legs already filled show blank
  rather than a fabricated timestamp.

**Modelling guidance for when there is enough data:**
- Target **time-to-fill** with kickoff as a CENSORING point (survival analysis),
  not fill/no-fill. A duration carries far more power than a binary — same
  argument that made [[project-edge-mine-exhausted]] target net cents.
- Leading candidate feature, physically motivated rather than fitted:
  `clearance = (volume / mkt_age_h) x hours_to_ko / ask_size`
  = "how many times over will the queue ahead of me clear before kickoff".
  First look (n=15, heavily confounded by arm and book age): filled median 2.34
  vs unfilled 0.68. Directional only — do not act on it.
- **Start with one interpretable ratio, not a classifier.** Project history is
  emphatic: when signal was absent, every increase in model capacity made results
  significantly worse (GBM depth 6, t=-5.71).

Related: [[project-mm-charge-more-ab]] (the price ladder that supplies the price
axis), [[project-mm-gross-margin-gate]].
