mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-10-10 00:16:39 +00:00
fix(elecprice): do not shorten the forecast by the source's own lag
The price series went flat towards the end of the horizon: a constant value repeated for the last hours, exactly as long as the day-ahead source was behind. The ETS extrapolation is appended after the last known price, but its length was computed as `prediction.hours * slots_per_hour - covered_slots`, and covered_slots is zero once the last known price lies before the run start. The forecast therefore spanned prediction.hours measured from the last known price rather than from now, and ended that much too early. Callers reading past that point got the last record held constant. With SMARD published up to 2026-09-08 23:45 and a run at 2026-09-09 13:00, the forecast covered 09-09 00:00 to 09-12 00:00 while the horizon needed 09-12 13:00: 52 quarter-hour slots of flat price, right inside the trailing window the terminal value curve is derived from. The length is now measured from the last known value through to `ems_start + prediction.hours`, which reduces to the previous formula whenever the source is current. Both the electricity price and the feed-in tariff provider had the same calculation.
This commit is contained in:
@@ -435,3 +435,32 @@ def test_energycharts_development_forecast_data(provider):
|
||||
"w", encoding="utf-8", newline="\n"
|
||||
) as f_out:
|
||||
json.dump(energy_charts_data, f_out, indent=4)
|
||||
|
||||
|
||||
@patch("requests.get")
|
||||
def test_forecast_covers_the_horizon_when_the_source_lags(
|
||||
mock_get, provider, sample_energycharts_json, cache_store
|
||||
):
|
||||
"""A lagging source must not shorten the forecast by its own lag.
|
||||
|
||||
The extrapolation is appended after the last known price, so measuring its
|
||||
length from now leaves exactly the lag uncovered at the end of the horizon -
|
||||
where callers then see the last value held constant.
|
||||
"""
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.content = json.dumps(sample_energycharts_json)
|
||||
mock_get.return_value = mock_response
|
||||
cache_store.clear(clear_all=True)
|
||||
|
||||
# The sample ends at 2024-12-11 23:00; start the run more than a day later.
|
||||
start = to_datetime("2024-12-12 13:00:00", in_timezone="Europe/Berlin")
|
||||
get_ems().set_start_datetime(start)
|
||||
provider.highest_orig_datetime = None
|
||||
provider.update_data(force_enable=True, force_update=True)
|
||||
|
||||
assert provider.highest_orig_datetime < start
|
||||
|
||||
horizon_end = start.add(hours=provider.config.prediction.hours)
|
||||
series = provider.key_to_series(key="elecprice_marketprice_wh")
|
||||
assert series.index.max() >= horizon_end.subtract(hours=1)
|
||||
|
||||
Reference in New Issue
Block a user