Score a forecast only when the relay matched its plan in time, not just in share

Reproduced: a forecast planning 15 minutes of heat was scored although the
relay was on for 12 (the 0.4.1 rule allowed 20 % per 15-minute block), and
the same on-time placed elsewhere in a block passed as well.

- The relay's on-time per poll interval, integrated at its own switch
  times, is compared with the plan block by block up to each horizon: the
  deviation is the time the relay spent in another state than planned.
  Unobserved relay time counts as possible deviation.
- Matched (at most 2 minutes, worst case): Forecast Error figures.
  Approximate (at most 5 minutes, at most 2 of them unobserved): separate
  approximate_stats. Counterfactual (more than 5 minutes seen): counted, not
  scored. Incomplete otherwise, by reason: relay history, assumed inputs at
  forecast time (an unknown window or electrical heat), no poll near the
  due time, or a missing reading.
- 2 minutes of unplanned boiler heat move a room by roughly half a 0.1 °C
  sensor step for the learned heat coefficients (0.05-0.12 °C per 5
  minutes); 5 minutes by about one step.
- Stored ledger statistics are versioned (2); 0.4.1 statistics used the
  looser rule and are dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
buzeraandClaude Opus 5.5 committed 2026-10-27 04:50:58 +02:00
1 parent 2cfba024ff
commit 0b82a8e26c
5 files changed
+267 -83

No files matched your search

+2 -1
View File
@@ -229,7 +229,8 @@ class MPCOperationalForecastError(CoordinatorEntity, SensorEntity):
horizons[f"{horizon}_min"] = {**{k: v for k, v in stats.items() if k != "zones"},
"zones": {names.get(z, z): v for z, v in stats.get("zones", {}).items()}}
return {
"kind": "forecast accuracy: published forecasts, scored only where the relay followed the plan",
"kind": ("forecast accuracy: published forecasts, scored only where the relay matched the plan "
"(at most 2 minutes in another state); approximate matches (up to 5 minutes) apart"),
"horizons": horizons,
"window_days": WINDOW_DAYS,
"unit_of_attributes": "°C",