tasks.task_safe_zone_load_demo

tasks.task_safe_zone_load_demo

Task demo: four-zone bottom-up total-load forecast vs. a direct aggregate.

This task demonstrates the four-German-TSO-zone forecasting design: fit one model per control-zone load series (Amprion, TenneT, TransnetBW, 50Hertz) and sum the four forecasts into the total-German-load forecast (bottom-up aggregation), then compare it against a single model trained on the aggregate load directly. The bottom-up combination reuses the existing multi-target machinery – the four zones become ConfigMulti.targets and the per-target forecasts are summed via the MultiTask aggregation with agg_weights=[1.0, ...].

Data source. With data_path pointing at the assembled four-column interim file (see spotforecast2_safe.downloader.entsoe.assemble_zone_loads), the task runs on real ENTSO-E control-zone load. With data_path=None (the default) it builds a deterministic, seeded synthetic four-zone dataset so the demo and its smoke test run offline without an ENTSO-E API key.

The comparison uses the project’s own backtesting engine (backtesting_forecaster + TimeSeriesFold) over a 24-hour horizon and reports MAE / RMSE / MAPE for both methods.

Per-zone weather (--per_zone_weather). When enabled, each zone model receives weather from its own TSO control-area cities instead of the shared single-point baseline. The pipeline uses on_weather_failure="skip" so the smoke test stays network-free: if Open-Meteo is unreachable the per-zone weather degrades to no-weather rather than failing. The default path (per_zone_weather=False) is exactly the pre-feature baseline (use_exogenous_features=False).

Examples

# Shell commands; they cannot run inside a Python kernel.
# Synthetic offline demo (no API key needed):
#   uv run spotforecast-safe-zone-load-demo
# Run on assembled real ENTSO-E zone data:
#   uv run spotforecast-safe-zone-load-demo     #       --data_path ~/spotforecast2_data/interim/energy_load_zones.csv
# Enable per-zone weather (requires Open-Meteo access; degrades gracefully):
#   uv run spotforecast-safe-zone-load-demo --per_zone_weather true

Functions

Name Description
cli Parse command-line arguments and run the zone-load demo.
main Run the four-zone bottom-up load demo. Returns 0 on success, 1 on failure.

cli

tasks.task_safe_zone_load_demo.cli(argv=None)

Parse command-line arguments and run the zone-load demo.

Parameters

Name Type Description Default
argv Optional[List[str]] Arguments without the executable name. None reads arguments from sys.argv, as required by the installed console script. None

Returns

Name Type Description
int The exit status returned by main.

main

tasks.task_safe_zone_load_demo.main(
    synthetic=True,
    data_path=None,
    predict_size=24,
    history_hours=24 * 100,
    random_seed=314159,
    logging_enabled=False,
    per_zone_weather=False,
)

Run the four-zone bottom-up load demo. Returns 0 on success, 1 on failure.

Parameters

Name Type Description Default
synthetic bool If True (and data_path is None), use seeded synthetic data. Ignored when data_path is provided. True
data_path Optional[Path] Path to an assembled four-column zone-load CSV. When given, real data is used and synthetic is ignored. None
predict_size int Forecast horizon in hours (also the backtest fold size). 24
history_hours int Length of the synthetic series in hours. 24 * 100
random_seed int Seed for the synthetic data and the estimators. 314159
logging_enabled bool If True, attach the dual console/file handlers. False
per_zone_weather bool If True, each zone model fetches weather from its own TSO control-area cities (config.per_zone_weather=True, on_weather_failure="skip"). Requires Open-Meteo access; if unreachable the pipeline degrades to no-weather. Default False keeps the pipeline byte-identical to the pre-feature baseline. False

Examples

from spotforecast2_safe.tasks.task_safe_zone_load_demo import main

# Fail-fast: a non-existent data_path returns 1 without computing.
from pathlib import Path
rc = main(data_path=Path("/nonexistent/zones.csv"))
print(f"Return code (missing data): {rc}")
assert rc == 1
Return code (missing data): 1