---
name: Pinnacle fair-value anchor VERIFIED calibrated (pooled z=+0.45) — and the reusable per-league test
description: First-ever check of the assumption the whole strategy rests on. Across 1,202 fixtures Pinnacle implies 25.0% draws / 44.3% homes vs actual 25.5% / 44.5% -- calibrated to under 0.5pp. No league is structurally mis-calibrated. Per-league deviations at n=30-50 are large but randomly signed = noise. Re-run research/pin_calibration_by_league.py whenever a league "looks broken".
type: project
---

Built 2026-07-25 when the user asked whether BSA's 0-for-12 was a structural
problem with Brazilian markets, and — the better question — **how we would know**.

## The load-bearing result

xlow measures CLV against Pinnacle fair. If Pinnacle were mis-calibrated, that
signal would be meaningless and no amount of bet-level sample size would reveal
it (the bets inherit the broken anchor). **This assumption had never been tested.**

**Pooled across 1,202 fixtures: draws implied 25.0% / actual 25.5% (z=+0.45);
homes implied 44.3% / actual 44.5% (z=+0.12).** The anchor is calibrated to under
half a percentage point. That is a genuine, load-bearing validation of the whole
approach — worth much more than any single league's record.

## Why per-league records can't be read

The test also shows why league-level ROI is unreadable at current samples: every
league deviates substantially at n=30-50, with **randomly signed** direction —
E0 +9.6pp draws, P1 +8.9, N1 +8.5 on one side; E2 -6.3, T1 -6.1, SC0 -4.7 on the
other. Random signs at small n is the signature of noise. A real structural bias
would be consistent across comparable leagues, not coin-flip scattered.

**BSA specifically** (the league that prompted this): n=32, implied 47.6%H/26.7%D
vs actual 56.2%H/15.6%D. Largest deviation in the table and adverse to us (BSA
bets skew AWAY; 6 of the 12 bet fixtures ended home, only 3 away). But home
z=+0.99, draw z=-1.42 — noise. **No structural issue detectable.**

## How to use it later (the point of saving this)

`python research\pin_calibration_by_league.py [min_n]`

It uses EVERY fixture with Pinnacle odds + a result, not just bets — roughly 40x
more data per league (BSA: 32 fixtures vs 12 bets), so calibration becomes
testable long before bet ROI does. It auto-flags a league `STRUCTURAL?` at
|z| > 2 with n >= 100.

**A flagged league is the ONE legitimate reason to drop a league** — its CLV
signal genuinely isn't trustworthy. This is categorically different from the
hindsight league-culling that [[project_league_filter_study]] already killed
(cutting cold leagues on ROI = fitting noise). Calibration failure is a
mechanism; a cold streak is not.

Sample sizes needed to detect a calibration error (95%): 5pp -> 383 fixtures,
8.6pp -> 130, 10pp -> 96, 15pp -> 43. So BSA needs ~130 fixtures (4x current,
about a full season) before its deviation could be called real.

**Minor caveat:** an earlier ad-hoc version of this analysis loaded 1,212
fixtures vs the script's 1,202 (difference is all MLS); cause not chased since no
conclusion changes. The committed script is canonical.

Related: [[project_xlow_rejection_criteria]], [[project_league_filter_study]],
[[project_xlow_test_segment_decomp]].
