← Back to projects

Case study

German Energy Shift

German day-ahead prices plus heat-pump stress into a deterministic shift recommender, with a published 2022 ridge MAE.

At a glance

Plain summary for recruiters and visitors. Technical detail follows below.

What it is
I built a German energy hybrid that scores day-ahead power prices with heat-pump stress. It recommends run and avoid hours for flexible loads on curated weeks.
What I owned
Solo end to end. SMARD and When2Heat ingest, ridge price holdout, stress index, deterministic shift scorer, and the Cloudflare demo Worker.
Why it matters
Recruiters can see price spikes, stress bands, and shift windows in one play. Privacy stays public data only. No live household meters.
Try it on this page vs full project
The page demo serves frozen SMARD-style scenarios from a Worker. Training notebooks, aligned CSV rebuild, and full eval stack stay on request.
German Energy Shift

Problem

Flexible loads need hours that are cheap on the day-ahead market and gentle on heat-pump stress.

Method

Aligned SMARD filter 4169 prices with When2Heat DE demand and COP. Trained offline price models, published ridge MAE on 2022, and scored weeks with a weighted price-stress blend.

Result

Ridge MAE 16.91 EUR/MWh on the 2022 holdout beats naive last-hour at 21.87. The live demo serves frozen winter spike, wind surplus, and normal week scenarios only.

Architecture

How the system is shaped. Full implementation stays private.

  1. Step 1

    Ingest

    SMARD day-ahead prices (filter 4169) and When2Heat DE heat demand plus COP, both CC BY 4.0 public series.

  2. Step 2

    Price model

    Offline train on 2020 to 2021. Publish ridge MAE on the hard 2022 holdout year. Freeze metrics.json.

  3. Step 3

    Heat stress

    Normalized DE space-heat demand blended with inverted ASHP COP into a unitless stress index.

  4. Step 4

    Shift score

    score = w1 * norm_price + w2 * norm_stress. Top-K run hours and avoid hours. Worker serves frozen scenarios only.

Holdout day-ahead MAE (2022)

SMARD DE-LU filter 4169, hourly 2020 to 2021 train and 2022 holdout. The table publishes MAE in EUR/MWh as the primary score. Floored MAPE was also computed with |price| at least 5 EUR/MWh. It stays secondary because near-zero and negative prices explode raw MAPE.

ModelMAENote
Ridge16.91 EUR/MWhPublished model
Naive last hour21.87 EUR/MWh
Hist GBM24.18 EUR/MWh
Naive same hour yesterday57.99 EUR/MWh

Algorithm

Hybrid price-stress shift ranking

Normalize day-ahead price and heat-pump stress, blend with recruiter-tunable weights, then pick the cheapest low-stress windows.

price_n = minmax(prices_eur_mwh)
stress_n = minmax(stress_index)
score = w_price * price_n + w_stress * stress_n
run_hours = argsort(score)[:top_k]
avoid_hours = argsort(score, descending)[:top_k]

Key logic

Compact illustrative snippet (Deterministic shift blend (illustrative)). Not the full codebase.

def build_shift_recommendation(prices, stress, price_weight=0.6, stress_weight=0.4, top_k=24):
    w1, w2 = clamp01(price_weight), clamp01(stress_weight)
    score = w1 * minmax(prices) + w2 * minmax(stress)
    order = np.argsort(score)
    return {"run_hours": order[:top_k].tolist(), "avoid_hours": order[::-1][:top_k].tolist()}

Stack

Time SeriesRidge RegressionSMARDWhen2HeatCloudflare WorkersPrivacy-by-DesignPythonEnergy Analytics

Try a live shift week

Free Cloudflare demo on curated SMARD-style weeks plus When2Heat stress. Not live trading data. Published holdout MAE stays on the metrics table above. SMARD day-ahead prices and When2Heat DE heat series are CC BY 4.0 public data. Toy run versus week-mean percent in the KPIs is illustrative only. It is not a retail electricity bill claim.

Scenario

Source code

Full source is available to hiring managers on request. The public page shows architecture, algorithms, and compact proofs only.