# Corrected v3 T60 candidate, 7 September 2026

This is a retrospective temporal evaluation with an explicit legacy-plan approximation. It is not evidence of forecasts actually emitted before departure. No production model was replaced by this run.

Training contains 353,023 mature departure estimates from 2026-08-01T00:00:00+00:00 through 2026-08-31T23:56:00+00:00. The split cutoff is 2026-08-31 23:59:00+00:00. The test contains 70,161 estimates in [2026-09-01T00:04:00+00:00, 2026-09-06T00:00:00+00:00) UTC. The final five training days form the temporal calibration slice; all metrics use the later holdout.

We used August plus the first five completed September days to keep a recent temporal comparison within a practical warehouse-only training budget. Feature extraction covers July 31 through September 6 for boundary padding. Training command bounds remain August 1 00:00 UTC through September 5 23:59 UTC. The label maturity reference is September 7 12:30 UTC, with a 24-hour grace period. This reference is not an archived database snapshot; source corrections made before the read transaction are included.

## Correctness and remaining limits

- v3 excludes mutable message code/type features, post-hoc weather/events, final-state priors, line-name aggregates, route position, inferred platform predecessors and hardcoded closures. Only station/network delay observations, earlier stops of the same run, calendar fields and plan categories are used.
- Original legacy /plan rows require plan_fetched_at before T. They remain an approximation because per-field plan history did not exist. Backfilled or late plans are excluded. New prospective predictions require recorded plan history.
- A departure cancellation requires dp_status=c. Arrival-only cancellation does not remove a known departure estimate. Ambiguous legacy cancellation sides remain unobserved. Missing estimates are never converted to punctuality. IRIS changed times are mature estimates, not independently confirmed physical departures.
- Cancellation model available: False. No departure-warning gate is validated by this historical sample; legacy OR flags no longer train a departure-cancellation classifier.
- Cache metadata embeds feature version, horizon, plan-availability mode, source watermarks and an integrity sidecar. The model manifest hashes all model artifacts and the cache. Evaluation and benchmark hash exact stop identities and assessed labels; a different model, cache, population or label set cannot silently become the public fixture.
- Feature extraction began before the new source-bound replication state was visible in its snapshot; its empty source binding/cursor fields are retained honestly. Label snapshot provenance is stored separately. Prospective watermarks preserve actual source bindings, completed/ongoing source cursors and timestamp extrema, without treating warehouse maximum IDs as freshness.

## Same-population Bahn comparison

Effective Bahn baseline uses the last estimate observed at or before T; where none exists it explicitly assumes zero minutes. Strict comparison includes only stops with a Bahn estimate at T. Neither comparison is an uncertainty-adjusted significance claim.

| Population | n | Model MAE, min | Bahn MAE, min | Bahn coverage |
|---|---:|---:|---:|---:|
| All eligible estimates, effective | 70,161 | 2.866 | 3.188 | 43.6% |
| With Bahn estimate at T, strict | 30,582 | 3.771 | 4.079 | 100% |
| Original 11 Tier-0 hubs, effective | 12,647 | 3.857 | 4.146 | 41.8% |
| Substations added August 7, effective | 21,068 | 1.727 | 2.175 | 25.0% |
| All non-substation EVAs (includes original 11), effective | 49,093 | 3.354 | 3.623 | 51.6% |

The effective MAE reduction is 10.1% on this exact window and population; the strict reduction is 7.5%. Earlier 4.96-minute reports and the withdrawn H candidate have different feature/label contracts and are not a direct improvement comparison.

The original-11 cohort is fixed by the initial collector Tier-0 membership. The main_eva_panel cohort is its own broader set: all EVAs excluding the August 7 substations; it is not a fixed historical panel. Cohort EVA lists are recorded in benchmark.json. No holdout EVA is unseen in training, so this test provides no evidence for generalization to completely new stations. Reopened-route comparison is unavailable until effective-dated route history exists; no reopening labels are fabricated.

## Validation and reproduction

40 feature rows were recomputed directly from observation logs, zero mismatches (features.log). 18 focused tests pass (validation.log); the real landing renderer produced /tmp/railcast-v3-index.html successfully (render-smoke.log). The cancellation gate correctly exits 2 with NOT VALIDATED (precancel-gate.log). Tests cover UTC minutes/DST, at-T plan availability, departure-side/legacy uncertainty, cache provenance/tampering, model hashes/horizon, immutable archives, calibrated forecast values and actual generation deadlines. Forecasts generated after T are explicitly late, and runs beyond the allowed late window are skipped.

```bash
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=4 .venv/bin/python ml/features_at_t.py --db /mnt/hotdata/railcast-dwh/railcast.db --start 2026-07-31 --end 2026-09-06 --horizon 60 --availability-mode legacy_plan --out /mnt/hotdata/railcast-dwh/features/features_corrected_v3_2026-08_t60.parquet --selftest 40
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=4 .venv/bin/python train_baseline.py --db /mnt/hotdata/railcast-dwh/railcast.db --features-view ml_features_at_t --at-t-parquet /mnt/hotdata/railcast-dwh/features/features_corrected_v3_2026-08_t60.parquet --horizon 60 --availability-mode legacy_plan --min-date 2026-08-01T00:00:00Z --max-date 2026-09-05T23:59:00Z --as-of 2026-09-07T12:30:00Z --output-dir ml-runs/I-corrected-v3-t60-2026-09-07
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=4 .venv/bin/python ml/benchmark_db.py --db /mnt/hotdata/railcast-dwh/railcast.db --at-t-parquet /mnt/hotdata/railcast-dwh/features/features_corrected_v3_2026-08_t60.parquet --models-dir ml-runs/I-corrected-v3-t60-2026-09-07/models --model-horizon 60 --horizons 60 --out ml-runs/I-corrected-v3-t60-2026-09-07/benchmark.json
```

Use a fresh output directory for a rerun: training refuses to overwrite a directory containing model artifacts. The source DWH is live, so later corrections can change a rerun. This candidate does not provide a current ablation, a multi-horizon validation, a reopening effect estimate or an actual prospective performance score.

# RailCast Baseline — Auto-Report
_Generiert: 2026-09-07T13:35:27.899127+00:00_

- **DB:** `/mnt/hotdata/railcast-dwh/railcast.db`
- **Availability:** legacy_plan; retrospective replay
- **Outcome:** mature_estimate_24h; not confirmed departure
- **Horizon:** T minus 60 minutes
- **Train-Cutoff:** 2026-08-31 23:59:00+00:00
- **Train rows:** 353,023
- **Test rows (letzte 5 Tage):** 70,161

## 1. Regression — `delay_dep` (Minuten)
- Train: 353,023 | Test: 70,161
- **Modell**: MAE = 2.87 min · MedianAE = 1.00 · R² = 0.245
- Baseline (Mittelwert): MAE = 4.09 min
- Baseline (Median): MAE = 3.31 min

**Quantil-Modelle** (loss=quantile · Coverage = Anteil y ≤ Vorhersage, Soll ≈ Quantil):
- q50: Pinball = 1.433 · Coverage = 51.1% (Soll 50%)
- q80: Pinball = 1.563 · Coverage = 79.6% (Soll 80%)
- q90: Pinball = 1.287 · Coverage = 89.5% (Soll 90%)

**MAE je train_type** (Test, n ≥ 50):

| Typ | n | MAE | MedianAE |
|---|---|---|---|
| S | 30,777 | 2.04 | 0.99 |
| RB | 9,592 | 2.27 | 0.99 |
| RE | 9,143 | 3.12 | 1.01 |
| ICE | 4,590 | 6.60 | 2.23 |
| NX | 3,212 | 4.93 | 2.14 |
| ERB | 1,661 | 3.71 | 1.19 |
| VIA | 1,495 | 5.13 | 1.96 |
| HLB | 864 | 2.85 | 1.05 |
| ARV | 760 | 2.40 | 0.95 |
| BRB | 740 | 1.58 | 0.65 |
| ME | 580 | 2.69 | 1.11 |
| vlx | 553 | 3.10 | 0.87 |
| ag | 539 | 1.80 | 0.94 |
| IC | 494 | 6.07 | 2.26 |
| SBH | 480 | 2.08 | 0.47 |
| Bus | 389 | 2.02 | 0.04 |
| RTB | 385 | 0.81 | 0.01 |
| RRB | 360 | 2.21 | 0.85 |
| ABR | 349 | 3.52 | 1.46 |
| R | 316 | 3.47 | 1.12 |
| erx | 289 | 1.22 | 0.43 |
| TR | 276 | 4.91 | 1.91 |
| NBE | 242 | 0.61 | 0.00 |
| SWE | 218 | 1.93 | 0.95 |
| RT | 190 | 2.88 | 1.53 |
| CAN | 181 | 2.82 | 0.71 |
| MRB | 181 | 0.89 | 0.06 |
| OE | 176 | 1.89 | 0.46 |
| FLX | 158 | 20.10 | 5.51 |
| TL | 123 | 1.04 | 0.86 |
| TLX | 111 | 1.32 | 0.59 |
| RJ | 108 | 5.93 | 1.27 |
| ENO | 103 | 1.53 | 0.72 |
| OPB | 95 | 0.57 | 0.00 |
| WFB | 74 | 1.87 | 0.46 |
| EN | 65 | 10.09 | 3.08 |
| NJ | 63 | 10.58 | 4.13 |
| ALX | 52 | 1.10 | 0.79 |

**Top Features:**
- `run_minutes_since_last_obs` — 0.763
- `run_last_known_delay_at_t` — 0.534
- `run_max_delay_at_t` — 0.374
- `eva` — 0.372
- `train_type` — 0.217
- `station_share_delayed6_60m` — 0.175
- `station_obs_n_60m` — 0.154
- `station_mean_delay_60m` — 0.147
- `plan_hour` — 0.146
- `hour_bucket` — 0.142

## 2. Classification — `delayed >= 6 min`
- Train: 353,023 (17.1% positive) · davon Fit: 280,045
- Test: 70,161 (16.9% positive)
- **AUC**: 0.755
- Majority-baseline accuracy: 83.1%
- **Brier**: roh 0.1191 → isotonic 0.1192 (Kalibrier-Slice: letzte 5 Train-Tage, n=72,978)
- **Recall@Precision≥0.5**: 26.7% (P=0.52 bei Cutoff 0.388)

| Cutoff | Precision | Recall | F1 |
|---|---|---|---|
| 0.10 | 0.245 | 0.877 | 0.382 |
| 0.15 | 0.283 | 0.763 | 0.413 |
| 0.20 | 0.324 | 0.620 | 0.426 |
| 0.25 | 0.351 | 0.533 | 0.423 |
| 0.30 | 0.396 | 0.423 | 0.409 |
| 0.40 | 0.570 | 0.228 | 0.326 |
| 0.50 | 0.670 | 0.177 | 0.280 |
| 0.60 | 0.748 | 0.148 | 0.247 |
| 0.70 | 0.809 | 0.121 | 0.210 |

**Positivrate je train_type** (Test, n ≥ 50): S 12.2% (n=30,777) · RB 14.3% (n=9,592) · RE 17.9% (n=9,143) · ICE 38.8% (n=4,590) · NX 30.4% (n=3,212) · ERB 22.6% (n=1,661) · VIA 35.9% (n=1,495) · HLB 18.2% (n=864) · ARV 12.4% (n=760) · BRB 5.0% (n=740)

**Top Features:**
- `eva` — 0.072
- `train_type` — 0.034
- `station_share_delayed6_60m` — 0.019
- `run_minutes_since_last_obs` — 0.012
- `run_max_delay_at_t` — 0.006
- `run_last_known_delay_at_t` — 0.001
- `station_obs_n_60m` — 0.001
- `plan_hour` — -0.002
- `station_mean_delay_60m` — -0.002
- `plan_dow` — -0.003

## 2. Classification — `cancelled`
⚠️ single-class split

Die [Prüfsummen der verwendeten Quelltexte](/model_sources.json) verbinden diesen Modellstand mit Trainings-, Merkmals- und Prognosecode.
