processing.shape_check.check_forecast_level( y, reference,*, statistic='median', tol=0.02, min_overlap=12,)
Measure the systematic level offset between a forecast and its reference.
Complements check_forecast_shape: a forecast can track the daily profile perfectly (high correlation, good range ratio) yet sit at the wrong level — a flat over- or under-prediction. This returns the signed offset of the forecast’s central level against the reference’s, in absolute and relative terms, and flags it as biased when the relative offset exceeds tol.
Like check_forecast_shape, this function is pure: no logging, no warning, no raising on a biased result. Only invalid inputs raise.
When y or reference is empty, or statistic is not "median" / "mean".
Examples
import pandas as pdfrom spotforecast2_safe.processing.shape_check import check_forecast_levelidx = pd.date_range("2026-06-13 00:00", periods=24, freq="h", tz="UTC")actual = pd.Series([43_000.0+3_000.0* (i %12) /12for i inrange(24)], index=idx)# Forecast that sits a flat 1_800 MW too high -> biased.high = actual +1_800.0rep = check_forecast_level(high, actual, tol=0.02)print(f"offset={rep.offset:.0f} MW rel={rep.rel_offset:.3f} biased={rep.biased}")assert rep.biased and rep.offset >0# A well-centred forecast -> not biased.ok = actual +50.0print("small offset biased:", check_forecast_level(ok, actual).biased)
offset=1800 MW rel=0.041 biased=True
small offset biased: False