---
name: The price-derived feature space is EXHAUSTED — a model predicts line movement, and the movement lives where spreads are widest
description: 2026-07-25 systematic mine. 57 slices + a grouped-CV gradient booster against net = close_mid - entry_ask. Every slice negative; best -0.43c. The model WORKS (OOF corr +0.15, monotone deciles, top decile moves +0.44c) but corr(predicted movement, half-spread) = +0.143, so its edge sits exactly where the toll is highest. Best configuration anywhere = -0.418c. Run research/edge_mine.py.
metadata:
  type: project
---

Run after [[project_xlow_spread_verdict]] killed xlow, when the user asked to
"data mine and use some models to find an edge that is profitable."

## Why the objective was net cents, not win rate

Mining for outcome prediction is the trap that produced every dead end of
2026-07-25. It is maximally noisy (1 bit/fixture, per-bet SD 1.99u) AND it ignores
the binding constraint. So the target was

    net = close_mid - entry_ask     (cents)

"the market's final valuation minus what I actually paid." Continuous, needs no
result, ~50x the power of outcome testing, and positive mean = genuinely
tradeable. **Any future search should use this target.**

## Result 1 — the scan

57 slices over book, side, price level, CLV band, spread width, cross-book
disagreement, entry timing, and two-way combos, on 7,478 records / 956 fixtures.
**Every single slice negative.** Best −0.43c. Family-wise |t| threshold via
permutation shuffled WITHIN fixture (the three outcomes are not independent —
they sum to 1, so naive t-tests overstate significance).

## Result 2 — the model, and the reason it cannot help

HistGradientBoosting, 5-fold GroupKFold by fixture (no leakage). It genuinely
predicts line movement: **OOF corr +0.15**, cleanly monotone deciles, top decile
moves **+0.436c** — bigger than xlow's whole edge.

| decile | actual move | half-spread | net |
|---|---|---|---|
| 1 | +0.436c | **1.018c** | −0.581c |
| 4 | +0.104c | 0.612c | −0.509c |
| 10 | −0.040c | 0.978c | −1.018c |

**corr(predicted movement, half-spread) = +0.143.** The predictable movement is
concentrated exactly where market makers charge most. Restricting to tight
spreads (<=0.5c) leaves only 286 of 7,478 records and the model cannot rank
within them at all — best quintile **−0.418c**, the best configuration in the
entire dataset.

## The generalisable lesson

**Edge and cost are the same variable, not independent ones.** Where there is
more repricing to capture, makers widen the spread to protect themselves from
whoever is trying to capture it. That is market making working correctly, and it
is why no slicing of price-derived features can win. Do not re-run this search
hoping for a better split — the null is structural.

## What this does NOT rule out

1. **Tighter spreads** — need half-spread ~0.3c vs 0.67c today. Nothing to build;
   just re-measure. This is what makes the existing work pay off.
2. **Non-price information** (lineups, xG, injuries) — a genuinely different
   hypothesis, untouched here. But it competes with professionals and still pays
   the same toll.
3. **Market making** — collecting the 0.67c instead of paying it is the
   profitable side of this exact trade. Different business; [[project_no_subask_limits]]
   shows adverse selection is the thing that would kill it.

Related: [[project_xlow_spread_verdict]], [[project_clv_spread_finding]],
[[project_no_subask_limits]], [[project_league_filter_study]].
