# E017-R Rest/Layoff Bounce — Execution Summary & Results **Request:** [racing5-additional-experiments-1.md](racing5-additional-experiments-1.md) · **Plan:** [racing5-additional-experiments-1_plan.md](racing5-additional-experiments-1_plan.md) · **Registered as:** [EXP-0027](artifacts/experiments/EXP-0027/report.md) (2026-07-03) ## What was done **Recon.** Four parallel readers mapped prior findings, the feature layer, the analysis/registry infrastructure, and the data layer. Key discovery: the "second-run-after-layoff bounce" was already pre-registered in racing5-plan.md's E017 Rest/recovery family but never tested (only the gear slice ran, EXP-0022), and the D1 residual miner's attribute set never included rest bands — a legitimate open angle, not a retired one. **Plan.** Drafted with pre-registered definitions (RSL = completed runs since the most recent ≥90.0-day gap; groups debut / no-layoff-history / RSL 1/2/3 vs reference RSL ≥ 4), then adversarially reviewed by independent statistics and code/protocol critics. Their confirmed findings were folded in before implementation: two-sided verdicts (contrary-direction mispricing still counts), the β(rsl2)−β(rsl1) contrast as the hypothesis's own decision test, a COVID-2020 nuisance dummy + ex-COVID sensitivity refit (the 2020 shutdown is a forced-layoff wave sitting entirely in the second date-half), cluster-robust SEs by race (RSL dummies are race-correlated; pooled inverse-Hessian t-stats are anti-conservative), an exact computable place% definition (`PaysPlaces(nonScratched, 0, TabGold)`), DNF-guarded normalized finish `(pos−0.5)/finishers`, and a decomposed reference group. **Implementation** (build clean, 90/90 tests green): - [FormState.cs](src/Racing5.Features/FormState.cs): `RunsSinceLayoff` (int?, null for debutants/continuous campaigns) and `LastLayoffDays` (double?) derived point-in-time from the existing per-horse fold history — no new accumulator state, no Parquet re-extract, and **not** added to the 34-feature model vector, so the frozen candidate (EXP-0016) is bit-identical. - [LogisticRegression.cs](src/Racing5.Modeling/LogisticRegression.cs): exposed the full inverse-Hessian covariance and added CR0 cluster-robust (sandwich) SEs with G/(G−1) correction via an optional `clusterIds` parameter — additive, all existing call sites unaffected. - [AnalyzeRestCommand.cs](src/Racing5.Cli/Commands/AnalyzeRestCommand.cs) (`analyze rest`): chronological replay 2009→2022 (2009–2015 warms the fold only), Tier A rows clamped to [2016-03-01, 2023-01-01) with the EXP-0009 filter (ActiveAtCutoff, consensus > 0, BestFixedWin, FinishPosition ≠ 0). Runs the whole pre-registered family in one registered execution: Fit A (market-blind) and Fit B (+ lnConsensus + lnConsensus²), full window + date-halves + ex-COVID refits, the rsl2−rsl1 contrast with covariance degeneracy guards, descriptive tables (incl. severity bands and per-year RSL 1 share), a within-horse difference-in-differences with attrition accounting, a market-blind 2009–2022 supplementary table, and diagnostics (DNF-in-gap contamination 0.07%; RSL1→RSL2 gap p50 = 25d). Hypothesis, grid, pass rule (cluster |t| ≥ 3 ∧ sign-stable across halves ∧ ≥1,000 cell rows/half, two-sided) and the enumerated verdict are hardcoded in source — that is the pre-registration. - 12 new unit tests: RSL boundary/progression/reset/scratch-DNF/debut/cap semantics, and a duplication-invariance test proving cluster SEs see through within-cluster duplication while model SEs falsely shrink by √2. **Pre-run verification.** A second adversarial pass (plan-fidelity, math/logic, leakage/protocol reviewers) verified the implementation against the plan before spending the registry evaluation. It caught one blocker — the attrition tracker lost "campaign ended" cases because a campaign-ending run is itself RSL 1 and overwrote its own pending entry — plus four reporting deviations (MDE for underpowered terms, missing SE columns, field-size vs finisher-count, lost-pair counts). All fixed; suite re-run green; then the single registered run executed (registry N: 26 → 27). **Bookkeeping.** results.md §Session 2 + retired-angles row appended; INDEX.md regenerated via `report index`; plan status updated to EXECUTED. --- ## The answer to the hypothesis **EXP-0027 verdict: the pattern is real, but the market already prices it.** The hypothesized shape genuinely exists in the data (240,037 Tier A runner rows, 2016–2022, cluster-robust by race): | Test (market-blind) | β | t | Sign-stable | Result | |---|--:|--:|:--:|---| | 1st run after ≥90d rest underperforms | −0.186 | −6.3 | yes | **CONFIRMED** | | 2nd run back improves vs 1st (the "bounce") | +0.133 | +3.4 | yes | **CONFIRMED** | | 2nd run back beats normal runners | −0.053 | −1.8 | yes | not confirmed | | 3rd run back beats normal runners | +0.051 | +1.6 | no | not confirmed | Two nuances against the literal hypothesis: the improvement is a **recovery toward normal, not a dramatic overshoot** (2nd-run-back horses are still slightly *worse* than reference), and the third run is simply back to baseline. But once you control for the market price (ln + ln² of consensus), **every coefficient collapses** — rsl1 t = +0.3, rsl2 t = −1.3, bounce contrast t = −1.2. The descriptive table says it plainly: first-up horses win 8.0% of the time and the market prices them at 7.9%; even ≥365-day layoffs are priced within noise. The within-horse difference-in-differences confirms the same split: the raw bounce is strong (t = −7.9) with zero market-relative content (t = −1.2). So there is **no exploitable edge** — consistent with EXP-0015's finding that SA books price public form patterns efficiently. The full tables (severity bands, COVID-2020 layoff wave, attrition, supplementary 2009–2022) are in [EXP-0027/report.md](artifacts/experiments/EXP-0027/report.md). Given the market-conditional result there is no case for a model-integration follow-up; the angle is retired as a mispricing source. The rest-band × trainer-strike interaction slice of E017 remains the only untested rest-related angle on the backlog.