Quick Start
This guide shows you how to download electricity data and run a simple forecast in just a few steps.
-
Set up environment
import os# Set your ENTSOE API keyos.environ["ENTSOE_API_KEY"] = "your-api-key-here"# Optional: Configure multithreading (requires Python 3.13t+)os.environ["PYTHON_GIL"] = "0"os.environ["THREADS_PER_PROCESS"] = "16" -
Download data with DataPipeline
from epftoolbox2.pipelines import DataPipelinefrom epftoolbox2.data.sources import EntsoeSource, OpenMeteoSource, CalendarSourcefrom epftoolbox2.data.transformers import TimezoneTransformer, ResampleTransformer, LagTransformerfrom epftoolbox2.data.validators import CoverageValidatordata_pipeline = (DataPipeline(timezone="Europe/Warsaw").add_source(EntsoeSource(country_code="PL",api_key=os.environ["ENTSOE_API_KEY"],type=["load", "price"])).add_source(OpenMeteoSource(latitude=52.2297,longitude=21.0122,prefix="warsaw")).add_source(CalendarSource(country="PL",holidays="binary",weekday="onehot",daylight=True)).add_transformer(TimezoneTransformer()).add_transformer(ResampleTransformer(freq="1h")).add_transformer(LagTransformer(columns=["load_actual", "price"],lags=[1, 2, 7],freq="day")).add_transformer(LagTransformer(columns=["is_monday", "is_tuesday", "is_wednesday", "is_thursday", "is_friday","is_saturday", "is_sunday", "is_holiday", "daylight_hours",],lags=range(-7, 1),freq="day")).add_validator(CoverageValidator(columns=["load_actual", "price"], min_coverage=1.0)))df = data_pipeline.run(start="2023-01-01", end="2024-04-01", cache=True)print(f"Downloaded {len(df)} rows with {len(df.columns)} columns")TimezoneTransformerturns the UTC index into Warsaw time, so a day lag is the same local hour on another calendar day:price_d-1is yesterday’s price andis_monday_d+1is the calendar of the day being forecast. -
Train models with ModelPipeline
from epftoolbox2.pipelines import ModelPipelinefrom epftoolbox2.information_set import InformationSetfrom epftoolbox2.models import OLSModel, LassoCVModelfrom epftoolbox2.evaluators import MAEEvaluatorfrom epftoolbox2.exporters import ExcelExporter, TerminalExporterpredictors = ["is_monday_d+{horizon}","is_tuesday_d+{horizon}","is_wednesday_d+{horizon}","is_thursday_d+{horizon}","is_friday_d+{horizon}","is_saturday_d+{horizon}","is_sunday_d+{horizon}","is_holiday_d+{horizon}","daylight_hours_d+{horizon}","load_actual_d-1","load_actual_d-7","price_d-1","price_d-7","warsaw_temperature_2m_d+{horizon}",]# Forecasts are issued at 11:45, before the 12:00 CET day-ahead gate closureinformation_set = InformationSet("11:45", "Europe/Warsaw").with_source_rules(data_pipeline.sources)model_pipeline = (ModelPipeline(information_set=information_set).add_model(OLSModel(predictors=predictors, training_window=365, name="OLS")).add_model(LassoCVModel(predictors=predictors, training_window=365, cv=5, name="LassoCV")).add_evaluator(MAEEvaluator()).add_exporter(TerminalExporter()).add_exporter(ExcelExporter("results.xlsx")))report = model_pipeline.run(data=df,test_start="2024-02-01",test_end="2024-03-01",target="price",horizon=6, # as far ahead as the weather forecasts gosave_dir="results",)Before any model is fitted, the information set checks that every predictor is known at 11:45 on the day the forecast is issued, which leaves 15 minutes before gate closure and is late enough for JMA’s 00 UTC run, available around 09:30 UTC, to count as known in summer too. Today’s
load_actualwould be rejected, which is why only its lags are used. -
Analyze results
# Overall summaryprint(report.summary())# By forecast horizonprint(report.by_horizon())# By hour of dayprint(report.by_hour())
Expected Output
Summary┏━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┓┃ model ┃ forecasts ┃ MAE ┃┡━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━┩│ OLS │ 4320 │ 15.5850 ││ LassoCV │ 4320 │ 15.5754 │└─────────┴───────────┴─────────┘
By Horizon┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓┃ model ┃ horizon ┃ MAE ┃┡━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━┩│ OLS │ 1 │ 14.8547 ││ LassoCV │ 1 │ 14.6445 ││ OLS │ 2 │ 15.3472 ││ LassoCV │ 2 │ 14.8396 ││ OLS │ 3 │ 14.9454 ││ LassoCV │ 3 │ 14.5638 ││ OLS │ 4 │ 15.6970 ││ LassoCV │ 4 │ 15.2951 ││ OLS │ 5 │ 15.8217 ││ LassoCV │ 5 │ 16.4123 ││ OLS │ 6 │ 16.8437 ││ LassoCV │ 6 │ 17.6971 │└─────────┴─────────┴─────────┘The MAE is in EUR/MWh. Each model made 4320 forecasts: 30 issue days, 24 hours and 6 horizons.