Day-Ahead-Gebote: Vom Fahrplan zu Börsengeboten

← Learning Hub Lektion 4 · Batterieoptimierungs-Kurs · Geschätzte Dauer: 20 Minuten

Bisher nimmt dein Optimierer Preise als gegeben und erzeugt einen Fahrplan. Aber in der Realität kennst du die Preise von morgen nicht, wenn du bietest. Die Day-Ahead-Auktion clearet alle Gebote gleichzeitig — dein Gebot beeinflusst den Preis. Diese Lektion zeigt, wie der Day-Ahead-Markt tatsächlich funktioniert und wie du die Ausgabe deines Optimierers in gültige Börsengebote übersetzt.

Wie die Day-Ahead-Auktion funktioniert

Die EPEX-SPOT-Day-Ahead-Auktion (verwendet in Zentral-/Westeuropa) funktioniert so:

  1. Gate öffnet: Marktteilnehmer geben Gebote für jede Stunde von morgen ab (Produkte: stündlich, Block).
  2. Gate schließt: Typischerweise 12:00 MEZ am Tag D-1.
  3. Clearing: Die Börse aggregiert alle Kauf- und Verkaufsgebote zu Angebots-/Nachfragekurven pro Stunde. Der Schnittpunkt bestimmt den Market Clearing Price (MCP).
  4. Ergebnisse: Veröffentlicht ~12:42 MEZ. Wenn dein Gebotspreis ≤ MCP (bei Verkäufen) oder ≥ MCP (bei Käufen), bist du angenommen.
Preisnehmer-Annahme: Für eine einzelne Batterie (sagen wir 10 MW) bewegen deine Gebote den MCP nicht messbar. Du kannst den Preis sicher als exogen behandeln. Das gilt nur nicht für sehr große Portfolios.

Gebotsarten für Batterien

Stundengebote (stufenförmig oder linear)

Du gibst ein Preis-Mengen-Paar für jede Stunde ab. Beispiel: „Ich kaufe 10 MW in Stunde 3, wenn Preis ≤ €25/MWh" oder „Ich verkaufe 10 MW in Stunde 17, wenn Preis ≥ €60/MWh."

Für eine Batterie gibst du zwei Gebote pro Stunde ab:

Blockgebote (verknüpfte Stunden)

Ein Blockgebot ist ein Alles-oder-Nichts-Gebot über mehrere aufeinanderfolgende Stunden. Beispiel: „Kaufe 10 MW für Stunden 1–4 zum Durchschnittspreis ≤ €22/MWh — akzeptiere alle Stunden oder keine." Nützlich für Batterien, weil Laden eine Sequenz von Stunden braucht, nicht nur eine.

Verknüpfte Blockgebote

Eltern-Kind-Verknüpfungen: „Akzeptiere mein Entlade-Block (Stunden 17–19) nur, wenn mein Lade-Block (Stunden 2–5) ebenfalls akzeptiert wurde." Das stellt sicher, dass die Batterie Energie hat, bevor sie verkauft.

Vom Optimierer zu Geboten: die Strategie

Der einfachste Ansatz — und der von den meisten BESS-Betreibern in der Praxis verwendete:

  1. Preise prognostizieren — verwende eine Preisprognose für die 24 Stunden von morgen
  2. Optimierer ausführen aus Lektion 3 mit den prognostizierten Preisen
  3. Gebotspreise bestimmen — für jede Stunde den Break-Even-Preis berechnen:
  4. Gebote einreichen — Mengen vom Optimierer, Preise aus Schritt 3
"""
day_ahead_gebote.py — Erzeuge Börsengebote aus Optimierer-Ergebnis
"""
import pyomo.environ as pyo
import numpy as np
import pandas as pd

# ... (Modell aus Lektion 3, gelöst) ...
# Annahme: Modell ist gelöst, Fahrplan-DataFrame existiert

# --- Gebotserzeugung ---
preis_prognose = preise  # In Produktion: aus deinem Prognosemodell
marge = 2.0  # €/MWh — Gebotsmarge (Toleranz für Prognosefehler)

gebote = []
for t in range(T):
    laden_mw = round(pyo.value(model.p_laden[t]), 2)
    entladen_mw = round(pyo.value(model.p_entladen[t]), 2)

    if laden_mw > 0.1:  # Ladestunde
        # Kaufgebot: bereit bis Prognose + Marge zu zahlen
        gebote.append({
            'stunde': t,
            'richtung': 'KAUF',
            'menge_mw': laden_mw,
            'preis_eur_mwh': round(preis_prognose[t] + marge, 2),
            'typ': 'stündlich'
        })
    elif entladen_mw > 0.1:  # Entladestunde
        # Verkaufsgebot: bereit ab Prognose - Marge zu verkaufen
        gebote.append({
            'stunde': t,
            'richtung': 'VERKAUF',
            'menge_mw': entladen_mw,
            'preis_eur_mwh': round(preis_prognose[t] - marge, 2),
            'typ': 'stündlich'
        })

gebot_df = pd.DataFrame(gebote)
print(gebot_df.to_string(index=False))
Der Margen-Trade-off: Eine breitere Marge erhöht die Annahmewahrscheinlichkeit, reduziert aber den Erlös. Eine engere Marge riskiert Nichtannahme bei leicht falscher Prognose. In der Praxis sind 1–3 €/MWh Margen üblich für Preisnehmer-Batterien.

Was wenn Gebote nur teilweise angenommen werden?

Wenn der Clearing-Preis zwischen deinen Kauf- und Verkaufsgeboten liegt, werden manche Stunden nicht gecleart. Dein Fahrplan ist dann teilweise gefüllt. Das ist ein Problem: vielleicht wurden nur die Ladestunden gecleart, aber nicht die Entladestunden. Du sitzt mit einer vollen Batterie ohne Verkaufsposition da.

Lösungen:

Preisnehmer-Gebot (der einfache Ansatz)

# Preisnehmer: Annahme garantieren, jeden Clearing-Preis akzeptieren
preisnehmer_gebote = []
for t in range(T):
    laden_mw = round(pyo.value(model.p_laden[t]), 2)
    entladen_mw = round(pyo.value(model.p_entladen[t]), 2)

    if laden_mw > 0.1:
        preisnehmer_gebote.append({
            'stunde': t,
            'richtung': 'KAUF',
            'menge_mw': laden_mw,
            'preis_eur_mwh': 3000.00,  # Maximum erlaubt — immer angenommen
            'typ': 'stündlich'
        })
    elif entladen_mw > 0.1:
        preisnehmer_gebote.append({
            'stunde': t,
            'richtung': 'VERKAUF',
            'menge_mw': entladen_mw,
            'preis_eur_mwh': -500.00,  # Minimum erlaubt — immer angenommen
            'typ': 'stündlich'
        })
Warum das funktioniert: Wenn deine Preisprognose gut ist und dein Optimierer die richtigen Stunden gefunden hat, garantieren Preisnehmer-Gebote die Ausführung. Du verdienst den tatsächlichen Clearing-Preis, der nahe an deiner Prognose liegen sollte. Das Risiko ist, dass Preise erheblich von der Prognose abweichen — dann hast du dich auf ein schlechtes Geschäft festgelegt.

Der vollständige Gebotsworkflow

┌─────────────────────────────────────────────────┐
│  D-1, morgens: Preisprognose empfangen          │
│  ↓                                              │
│  Optimierer ausführen → Fahrplan erhalten       │
│  ↓                                              │
│  Gebote erzeugen (stündlich oder Block)         │
│  ↓                                              │
│  An Börse senden vor 12:00 MEZ                  │
│  ↓                                              │
│  ~12:42: Clearing-Ergebnisse empfangen          │
│  ↓                                              │
│  Angenommene vs. abgelehnte Gebote prüfen       │
│  ↓                                              │
│  Bei Teilfüllung → im Intraday korrigieren      │
└─────────────────────────────────────────────────┘

Überprüfe dein Verständnis

Eine Batterie gibt ein VERKAUF-Gebot bei €65/MWh für Stunde 18 ab. Der Clearing-Preis ist €72/MWh. Was passiert?

Warum könnte ein Batteriebetreiber verknüpfte Blockgebote statt unabhängiger Stundengebote verwenden?

Was ist das Hauptrisiko bei Preisnehmer-Geboten (Kauf bei €3000, Verkauf bei -€500)?

📖 Empfohlene Lektüre

EPEX SPOT — Day-Ahead-Handelsprodukte — offizielle Dokumentation zu stündlichen Geboten, Blockgeboten, verknüpften Blöcken und Clearing-Regeln.

💬 Fragen? Gebotsstrategien haben viele Nuancen — Block-Dimensionierung, kürzbare Blöcke, paradox abgelehnte Gebote. Frag, wenn du tiefer in eines davon einsteigen möchtest.

Rechtliches: Impressum