diff --git a/flexmeasures/data/models/forecasting/pipelines/train.py b/flexmeasures/data/models/forecasting/pipelines/train.py index eacde33137..7a086f9543 100644 --- a/flexmeasures/data/models/forecasting/pipelines/train.py +++ b/flexmeasures/data/models/forecasting/pipelines/train.py @@ -27,6 +27,7 @@ def __init__( forecast_frequency: int = 1, event_starts_after: datetime | None = None, event_ends_before: datetime | None = None, + save_belief_time: datetime | None = None, probabilistic: bool = False, ensure_positive: bool = False, missing_threshold: float = 1.0, @@ -62,6 +63,7 @@ def __init__( max_forecast_horizon=max_forecast_horizon, event_starts_after=event_starts_after, event_ends_before=event_ends_before, + save_belief_time=save_belief_time, forecast_frequency=forecast_frequency, missing_threshold=missing_threshold, ) diff --git a/flexmeasures/data/models/forecasting/pipelines/train_predict.py b/flexmeasures/data/models/forecasting/pipelines/train_predict.py index 7da3a98ffd..1d52bfd401 100644 --- a/flexmeasures/data/models/forecasting/pipelines/train_predict.py +++ b/flexmeasures/data/models/forecasting/pipelines/train_predict.py @@ -81,6 +81,7 @@ def run_cycle( // self._parameters["sensor"].event_resolution, event_starts_after=train_start, event_ends_before=train_end, + save_belief_time=self._parameters["save_belief_time"], probabilistic=self._parameters["probabilistic"], ensure_positive=self._config["ensure_positive"], missing_threshold=self._config.get("missing_threshold"), diff --git a/flexmeasures/data/schemas/forecasting/pipeline.py b/flexmeasures/data/schemas/forecasting/pipeline.py index 72371fc39a..80d1d8aec7 100644 --- a/flexmeasures/data/schemas/forecasting/pipeline.py +++ b/flexmeasures/data/schemas/forecasting/pipeline.py @@ -17,6 +17,7 @@ from flexmeasures.data.schemas import SensorIdField from flexmeasures.data.schemas.times import ( + AwareDateTimeField, AwareDateTimeOrDateField, DurationField, PlanningDurationField, @@ -285,6 +286,18 @@ class ForecasterParametersSchema(Schema): }, ), ) + belief_time = AwareDateTimeField( + format="iso", + data_key="prior", + metadata={ + "description": "The forecaster is only allowed to take into account sensor data that has been recorded prior to this [belief time](https://flexmeasures.readthedocs.io/latest/api/notation.html#tracking-the-recording-time-of-beliefs). " + "By default, the most recent sensor data is used. This field is especially useful for running simulations.", + "example": "2026-01-15T10:00+01:00", + "cli": { + "option": "--prior", + }, + }, + ) max_forecast_horizon = DurationField( data_key="max-forecast-horizon", required=False, @@ -419,7 +432,10 @@ def resolve_config( # noqa: C901 else: predict_start = data["start"] - save_belief_time = now if data.get("start") is None else predict_start + save_belief_time = data.get( + "belief_time", + now if data.get("start") is None else predict_start, + ) if data.get("end") is None: data["end"] = predict_start + data["duration"]