CH NEO-ZÜRICH AUSGABE
WETTER · SAURER REGEN 12°C
BLEND DES TAGES · 07/ROGUE
EST. 2027
DIE AEC CYBER MORGENZEITUNG

PAZ Kaffi

DESIGN · ABBRUCH · KOFFEIN · DEPESCHE
AUSGABE 1112 · 12 November 2026
SENDUNG 04:42 MEZ
2'400 BOGEN GEDRUCKT
LESEZEIT · 47 MIN
Oktober war 13 % milder – Heizzähler mit 55 Zeilen Python normalisieren
Akademie
FRAME · 06:55
12-11-2026

Oktober war 13 % milder – Heizzähler mit 55 Zeilen Python normalisieren

Oktober 2026 war 13 % milder in Zürich. Heizgradtage aus MeteoSwiss-Rohdaten in Python berechnen und Heizzähler wetterbereinigen.

Das provisorische Oktober-Bulletin von MeteoSwiss, verbreitet von Keystone-SDA am 30. Oktober 2026, setzt die Schweiz auf einen Durchschnitt von 8 °C, 1,4 °C über der Referenzperiode 1991–2020. Laufe 55 Zeilen Python (Standardbibliothek) gegen die Station Zürich / Fluntern, und derselbe Monat kommt zu 218 Heizgradtage (Kd) heraus – gegen einen normalen Oktober von 250 Kd. Das macht ihn 13 % milder. Jeder Heizzähler in der Stadt sieht diesen Monat etwas besser aus, und das Gebäude verdient nur einen Teil davon.

Ein Zählerstand ist halb Gebäude, halb Wetter. Die gute Nachricht: Die Wetterhälfte ist öffentlich. MeteoSwiss veröffentlicht SwissMetNet, „158 automatische Messstationen” laut STAC-Katalog, unter CC-BY-Lizenz. Fluntern hat Tageswerte seit 1. Januar 1864, jeden Morgen aktualisiert bis gestern. Hinter dieser Datei stehen die Stationstechniker und Dateningenieure, die über mehr als 160 Winter hinweg ein Thermometer auf 604 m ü.M. betrieben haben. Jede witterungsbereinigte Energiegrösse in der Schweiz steht auf ihrer Arbeit.

Was ein Heizgradtag tatsächlich zählt

MeteoSwiss definiert einen Heiztag als einen, dessen Durchschnittstemperatur „12 °C oder weniger” ist, ein Tag, der „gemäss dieser SIA-Definition” beheizt werden muss. HGT 20/12 summiert über alle Heiztage die Differenz zwischen einem 20 °C-Raum und dem Tagesmittel: ein 5 °C-Tag ergibt 15 Kd, ein 13 °C-Tag ergibt nichts. ATD 12/12 ist einfacher: jeder Tag ergibt max(0, 12 − Tmean). MeteoSwiss stellt fest, dass sowohl Heiztage als auch Heizgradtage in den letzten Jahrzehnten landesweit rückläufig sind, und führt den Rückgang auf die Klimaerwärmung zurück.

←HEUTE: Im Jahr 2026 zählte Oktober in Zürich 218 Kd gegenüber einer Norm von 250 Kd, und die meisten Office-Tabellen verglichen ohnehin die rohen kWh.
→3012: Jeder Zählerstand trägt seinen Wetter-Zwilling mit sich, und niemand streitet über einen milden Monat mehr.
Drehpunkt: Die Korrektur funktioniert nur, weil 160 Jahre desselben Thermometers in einer Textdatei liegen.

Das Werkzeug

Das Werkzeug: MeteoSwiss Open Government Data für SwissMetNet (Sammlung ch.meteoschweiz.ogd-smn auf data.geo.admin.ch), gelesen nur mit der Python-3-Standardbibliothek: kein pip install, kein API-Schlüssel. Jede Station hat zwei tägliche CSVs: historical, vom Beginn der Messungen bis 31. Dezember des letzten Jahres, und recent, „vom 1. Januar dieses Jahres bis gestern”. Drei Spalten – tre200d0 (mittlere tägliche Lufttemperatur in 2 m), xno000d0 („Heizgradzahl 12/20 (SIA: Heizgradtage)”) und xno012d0 („Heizgradtage ATD12″) – verwandeln deine Energieberichte von Wahrsagerei in Arithmetik.

Setup

Setup:

mkdir hgt-lab
cd hgt-lab
python --version   # 3.10 oder neuer (getestet auf 3.10.11)
# optional: lies, was jede Spalte bedeutet
curl -O https://data.geo.admin.ch/ch.meteoschweiz.ogd-smn/ogd-smn_meta_parameters.csv
# speichere das Skript unten als hgt.py, dann:
python -I hgt.py
# erstes Durchlaufen lädt ~6,5 MB historical + ~48 kB recent CSV und cachert beide

Erste Schritte

Erste Schritte:

  1. Speichere das Programm unten als hgt.py und führe es aus. Die erste Zeile sollte lesen 59480 days read, own HGT differs from MeteoSwiss on 0 days: deine Arithmetik und die nationale Wetterleitstelle stimmen überein.
  2. Öffne ogd-smn_sma_d_recent.csv in Notepad: Semikola, Daten wie 01.10.2026 00:00 in UTC, schlichte Zahlen. Das ist das gesamte Format.
  3. Ersetze METERED_KWH mit deinem eigenen Oktober-Heizzählerstand und führe wieder aus.
  4. Ändere STATION zu BER, GVE, LUG oder DAV, je nachdem, welcher deiner Baustelle am nächsten liegt.

Der Code, erklärt

Der Code, erklärt:

# Heizgradtage HGT 20/12 aus MeteoSwiss-Rohdaten → witterungsbereinigung eines Zählerstands
import csv, os, urllib.request
from datetime import date

STATION = "SMA"                  # Zürich / Fluntern (siehe ogd-smn_meta_stations.csv)
START, END = (10, 1), (10, 31)   # Zeitraum prüfen: 1. Okt - 31. Okt
YEAR = 2026
METERED_KWH = 1850.0             # dein Heizzählerstand für diesen Zeitraum (Beispielwert)
HOT_WATER_SHARE = 0.20           # Teil der Energie, die nicht vom Wetter abhängt
BASE = "https://data.geo.admin.ch/ch.meteoschweiz.ogd-smn/{s}/ogd-smn_{s}_d_{p}.csv"

def load(part):
    s = STATION.lower()
    cache = f"ogd-smn_{s}_d_{part}.csv"
    if not os.path.exists(cache):
        urllib.request.urlretrieve(BASE.format(s=s, p=part), cache)
    with open(cache, encoding="cp1252") as fh:          # MeteoSwiss CSVs sind Windows-1252
        return list(csv.DictReader(fh, delimiter=";"))

days = {}                       # date → (Tmean, published HGT, published ATD)
for row in load("historical") + load("recent"):
    if not row["tre200d0"]:
        continue
    d, m, y = row["reference_timestamp"][:10].split(".")
    days[date(int(y), int(m), int(d))] = (float(row["tre200d0"]),
                                          row["xno000d0"], row["xno012d0"])

def hgt(t):  return 20.0 - t if t  0.05)
print(f"{len(days)} days read, own HGT differs from MeteoSwiss on {bad} days")

def period(year):
    a, b = date(year, *START), date(year, *END)
    vals = [v[0] for k, v in days.items() if a <= k <= b]
    return sum(map(hgt, vals)), sum(map(atd, vals)), len(vals)

h_now, a_now, n = period(YEAR)
norm = [period(y) for y in range(1991, 2021)]               # Klimanormal 1991-2020
h_norm = sum(p[0] for p in norm) / len(norm)
a_norm = sum(p[1] for p in norm) / len(norm)
print(f"{YEAR}: {n} days, HGT20/12 = {h_now:.0f} Kd, ATD12/12 = {a_now:.0f} Kd")
print(f"norm 1991-2020:     HGT20/12 = {h_norm:.0f} Kd, ATD12/12 = {a_norm:.0f} Kd")
print(f"this period was {100 * (1 - h_now / h_norm):.0f} % milder than normal (HGT)")

for name, now, ref in (("HGT", h_now, h_norm), ("ATD", a_now, a_norm)):
    weather = METERED_KWH * (1 - HOT_WATER_SHARE)
    fixed = METERED_KWH * HOT_WATER_SHARE
    normal = fixed + weather * ref / now
    print(f"{name}: {METERED_KWH:.0f} kWh metered → {normal:.0f} kWh in a normal year")

warmest = sorted((period(y)[0], y) for y in range(1981, YEAR + 1))[:3]
print("mildest periods since 1981 (HGT):", ", ".join(f"{y} {v:.0f}" for v, y in warmest))

Laufen am 7. November 2026 druckte es:

59480 days read, own HGT differs from MeteoSwiss on 0 days
2026: 31 days, HGT20/12 = 218 Kd, ATD12/12 = 58 Kd
norm 1991-2020:     HGT20/12 = 250 Kd, ATD12/12 = 80 Kd
this period was 13 % milder than normal (HGT)
HGT: 1850 kWh metered → 2066 kWh in a normal year
ATD: 1850 kWh metered → 2393 kWh in a normal year
mildest periods since 1981 (HGT): 2022 36, 2001 47, 1995 86

Zeilen 1–10, die Regler: Jeder Wert, den du ändern kannst, sitzt am Anfang als Konstante, ein grossgeschriebener Name, den der Rest des Programms nur liest. START, END sind (Monat, Tag)-Paare, sodass das Skript eine Woche, einen Monat oder eine ganze Heizperiode verarbeitet. Die 1.850 kWh und der 20 %-Warmwasseranteil sind lehrreiche Eingaben, keine echte Liegenschaft und kein Normwert: ersetze beide mit deinen eigenen Zahlen.

Zeilen 12–18, einmal laden, dann von der Platte lesen: load ist eine Funktion, ein benannter Block, den du erneut aufrufen kannst. Er lädt die Stationsdatei nur, wenn kein gecachtes Exemplar existiert, dann parsed er sie mit csv.DictReader, das jede Zeile in ein Wörterbuch umwandelt, das nach Spaltennamen indexiert ist. Das Detail, das man richtig hinbekommt: MeteoSwiss versendet seine CSVs als Windows-1252 (cp1252) mit Semikola. Die tägliche Stationsdatei ist schlichte ASCII, aber die Metadatendateien tragen Umlaute und Akzente, und gelesen als UTF-8 stoppen sie Python mit UnicodeDecodeError. Die Download-Docs von MeteoSwiss selbst fügen eine Warnung bei: hole dir die Granularität, die du brauchst, weil selbst aufsummierte 10-Minuten-Daten „nicht immer zu den gleichen Ergebnissen führen”!

Zeilen 20–26, ein Wörterbuch, ein Schlüssel pro Tag: Historical und recent Zeilen sind mit + zusammengefügt, leere Temperaturzellen werden übersprungen, und der dd.mm.yyyy Stempel wird zu einem echten date Objekt. Jedes Datum ordnet sich einem Tupel zu (ein festes kleines Bündel): die gemessene Mitteltemperatur plus MeteoSwiss’ veröffentlichte HGT und ATD.

Zeilen 28–33, berechne es selbst, dann prüfe: hgt und atd sind die beiden Definitionen als einzeilige Funktionen. Der bad Zähler vergleicht deinen Wert mit dem veröffentlichten an jedem Tag, der einen hat, und erlaubt Runden auf 0,1 Kd. Null Nichtübereinstimmungen verdienen dir Vertrauen in die übrige Ausgabe.

Zeilen 35–55, die Norm und die Witterungsbereinigung: period(year) summiert beide Indikatoren für dein Fenster; Durchschnitt 1991 bis 2020 ergibt die Klimanorm. Die Witterungsbereinigung hält den witterungsunabhängigen Anteil fest und skaliert den Rest mit norm ÷ aktuell. Oktober 2026 war mild, daher ist die Normal-Jahr-Zahl höher als der Zähler: 2.066 kWh mit HGT, 2.393 kWh mit ATD. Die letzte Zeile ordnet die mildesten Oktober seit 1981: 2022, 2001 und 1995. Der Kompromiss, offen gesagt: diese Verhältnismethode ist eine Lehrmethode, nicht das SIA-Verfahren 380:2015, und sie setzt voraus, dass witterungsabhängige Energie linear mit Gradtagen skaliert. Ein Gebäude mit grossen Solargewinnen oder einem trägen Regler wird sich nicht so verhalten.

Zwei Formulierungen, ein Datensatz

Die Energieüberwachungsseite des Kantons Freiburg stellt fest, dass „in der Schweiz die Methode der SIA … angewendet” wird, wobei Heizgradtage 20/12 verwendet werden, und formuliert Heiztage als einen Mittelwert „unter 12°C”. MeteoSwiss schreibt „12 °C oder weniger”. Die Formulierungen unterscheiden sich nur bei exakt 12,0 °C, und die Daten stimmen sie ab. In den 15.819 Tagen seit 1. Januar 1981, die einen veröffentlichten HGT tragen, passt die <= Regel auf MeteoSwiss an jedem Tag; striktes < unterscheidet sich auf 63 Tagen, die exakt auf 12,0 °C sitzen, wo MeteoSwiss 8,0 Kd bucht. Die Betonwand bemerkte die Debatte nie.

HGT oder ATD am gleichen Zähler

Ein Zähler, zwei Antworten: 2.066 kWh oder 2.393 kWh. Die Lücke ist die Basistemperatur. I. Mojic und M. Haller vom SPF Institut für Solartechnik an der OST, in einer Literaturrecherche von 2019 für das Schweizer Bundesamt für Energie (BFE), beschreiben Schweizer Heizung als „üblicherweise mittels der Heizgradtag-Methode witterungsbereinigt” vor SIA 380:2015, und bemerken, dass die neue Norm ATD empfiehlt. Der schwierige Teil, schreiben sie, ist die Wahl der Basistemperatur: ein Standard 12 °C „zu grossen Abweichungen führt”, und ohne einen gebäudespezifischen Wert funktioniert HGT besser als ATD für Wohnungen. Ihre Überprüfung gibt deinem Büro einen handfesten Grund für jeden Indikator, den es wählt.

Ein stillerer Punkt aus den späten 2070ern: die Energiedaten, die überlebten, sahen wie diese Datei aus – Semikolon-getrennte schlichte Text, den eine 25-Jährige immer noch in Notepad öffnen kann. Halte deine Zählerlogs genauso.

Atelier

Atelier: Ein kleines Zürich-Studio oder Bauleitung-Team, das Klienten einen Erste-Winter-Energiebericht übernimmt, kann leicht dahinkommen, rohe kWh über Jahre mit unterschiedlichem Wetter zu vergleichen, was milde Winter schmeichelt und kalte bleibt schuldig. Ein Büro, das KI-Assistenten diese Berichte Entwurf machen lässt, braucht eine überprüfte Zahl noch mehr, weil ein Fliessabsatz mit unkorrekthem kWh immer noch verkehrt ist. Montagszug: Addiere eine „Normal-Jahrs-kWh”-Spalte neben der gemessenen Spalte in deinem Überwachungsblatt für ein Gebäude, gefüllt mit diesem Skript.

Hack

Hack: Prüfe die Freiburg-Formulierung gegen die veröffentlichte Reihe und sage die Zählung voraus, bevor du sie läufst. Tausche den Vergleich in Zeile 28 zu striktem-kleiner-als aus und addiere einen Zähler. Erwarte, dass die erste Ausgabezeile “differs from MeteoSwiss on 63 days” liest, und der Zähler 63 druckt auch, weil jeder dieser Tage exakt auf 12,0 °C sitzt. Dann schalte den Vergleich zurück.

def hgt(t):  return 20.0 - t if t < 12.0 else 0.0     # "unter 12°C" Formulierung
edge = sum(1 for t, h, a in days.values() if h and t == 12.0)
print(edge, "published days sit exactly on 12.0 °C")

Learn-it

Learn-it:

Lade die Fluntern-Datei heute Nacht, laufe die 55 Zeilen, und setze eine Normal-Jahrs-Spalte neben deine nächste Zählerablesung.

GEMELDET AUS
MIT-UNTERZEICHNER
PAZ Academy
VERTRAUEN
HIGH
NACHDRUCKE
© PAZ - PARAMETRIC ACADEMY ZURICH · ALLE RECHTE VORBEHALTEN

PAZ Kaffi · interdisziplinäre Redaktionsarbeit, geleitet von der PAZ Academy

⚑ FEHLER MELDEN · KORREKTUR EINSENDEN
◂ ZURÜCK ZUR TITELSEITE · PAZ KAFFI

© 2026 PAZ Academy.