Letzte Aktualisierung: Mai 2026
Für: Nora (geb. 30.10.2017, Typ-1-Diabetes), verwaltet von Stephan und Nina
Diabotus ist ein persönliches Diabetes-Management-System für Nora. Es besteht
aus drei Teilen, die zusammen arbeiten:
┌─────────────────────────────────────────────────────────────────┐
│ DIABOTUS │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ Matrix Bot │ │ Nightscout │ │ Glooko Import │ │
│ │ matrixbot.py │ │ Import │ │ glooko_import.py │ │
│ │ │ │ (CGM-Daten) │ │ (Pump + Bolus-Dat) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬─────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL Datenbank: diabotus │ │
│ │ glucose_entries │ events │ context_events │ therapy-... │ │
│ └─────────────────────────────────┬────────────────────────┘ │
│ │ │
│ ┌──────────────────────────┼───────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────────────────┐ ┌────────────┐ │
│ │ insulin_ │ │ plot.py / prognosis │ │ context_ │ │
│ │ model.py │ │ Glukosekurven, Prognosen│ │ builder.py│ │
│ │ (IOB, COB) │ └──────────────────────────┘ └────────────┘ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Diabotus läuft als Matrix-Chat-Bot. Du schreibst ihm Nachrichten in natürlicher
Sprache – er versteht sie und führt die passende Aktion aus (Eintrag in die DB,
Plot, Prognose usw.).
| Befehl | Was passiert |
|---|---|
!ping |
Bot antwortet kurz – prüft ob er läuft |
!status |
Zeigt aktuellen BZ, Therapiewerte, letzte Ereignisse |
!plot [h] |
Glukose-Plot der letzten h Stunden (Standard: 6h) |
!prognose [h] |
BZ + 3h-Prognose, h Stunden Verlauf davor |
!pumpe <min> [Grund] |
Pumpe für N Minuten anhalten (auto-Resume) |
!pumpe aus/an |
Manuell Pumpe stoppen / fortsetzen |
!meta <Anfrage> |
Quellcode oder Datenbankstruktur ändern (KI-Hilfe) |
!tune |
Modell-Validierung auslösen (Prognosen vs. Wirklichkeit) |
!help |
Vollständige Befehlsreferenz |
Alle anderen Nachrichten werden als Anfragen an die KI weitergeleitet (mit
medizinischem Kontext angereichert).
"Nora hat gerade 60g Nudeln gegessen und 5,45 Einheiten gespritzt"
"Korrektur: BZ 230, 2E gegeben"
"Nora schläft ein"
"Katheterwechsel, Teflonkatheter rechtes Bein"
"Sensorwechsel, G7 neu gesetzt"
Quelle: Dexcom G7 → Nightscout (lokal) → glucose_entries-Tabelle
Frequenz: alle 5 Minuten
Einheit: mg/dL
-- Letzte 3 Werte abfragen:
SELECT timestamp, sgv, direction FROM glucose_entries
ORDER BY timestamp DESC LIMIT 3;
Die direction-Werte bedeuten:
| Wert | Trend |
|------|-------|
| DoubleUp | Sehr schnell steigend (>3 mg/dL/min) |
| SingleUp | Schnell steigend |
| FortyFiveUp | Leicht steigend |
| Flat | Stabil |
| FortyFiveDown | Leicht fallend |
| SingleDown | Schnell fallend |
| DoubleDown | Sehr schnell fallend |
Alle insulin- und kohlenhydrat-bezogenen Ereignisse werden in der
events-Tabelle gespeichert.
Bekannte Typen:
| Typ | Beschreibung | JSON-Daten |
|---|---|---|
carb |
Kohlenhydrataufnahme | {"grams": 60, "description": "Nudeln", "absorption": "slow"} |
insulin |
Bolus | {"units": 5.45, "for_grams": 60} |
insulin_stretched |
Gestreckter Bolus | {"units": 1.5, "duration_min": 60, "planned_units": 2.0} |
pump_suspend |
Pumpe angehalten | {"reason": "Sport", "duration_min": 60} |
pump_resume |
Pumpe fortgesetzt | {"reason": "Sport beendet"} |
Wichtig: Der Typ ist immer
carb, niemalsmeal. Der JSON-Schlüssel ist
immergrams, niemalscarbs.
Optionale Felder bei carb:
| Feld | Bedeutung | Beispiel |
|---|---|---|
description |
Name des Lebensmittels | "Pizza" |
absorption |
Aufnahmegeschwindigkeit | "slow" (→ Kapitel 4) |
fat_g |
Gramm Fett (für FPE-Modell) | 18 |
protein_g |
Gramm Protein (für FPE-Modell) | 12 |
Qualitative Ereignisse ohne direkte Insulinwirkung:
| Kategorie | Wann | Wichtige Felder |
|---|---|---|
illness |
Nora ist krank | description: "Nora hat Fieber" |
activity |
Sport | description: "Turnstunde 60min" |
sleep |
Einschlafen/Aufwachen | metadata: {"onset": "20:45"} oder {"wake": "06:30"} |
catheter_change |
Katheter getauscht | metadata: {"type": "soft", "site": "abdomen_left"} |
sensor_change |
G7-Sensor gewechselt | metadata: {"model": "G7", "status": "inserted"} |
note |
Allgemeine Notiz | description: "Nora war heute müde" |
pump_observation |
CIQ-Rate abgelesen | metadata: {"actual_rate": 2.3, "programmed_rate": 1.3} |
Sleep-Events sind besonders wichtig: Diabotus nutzt Einschlafzeiten für
das Einschlaf-Glukose-Modell (→ Kapitel 6.3).
Über glooko_import.py werden alle 2–3 Monate Daten vom Glooko-Export
nachgeladen. Diese landen in:
- glooko_basal_raw – Basalraten-Segmente (5-Minuten-Takt, echte CIQ-Raten)
- glooko_bolus_raw – alle abgegebenen Bolusse mit BZ- und KH-Angabe
Diese Tabellen dienen primär zur Modellkalibrierung, nicht zur täglichen
Nutzung.
Das Insulin-Pharmakokinetikmodell berechnet, wie viel von einem injizierten
Insulin noch aktiv (wirksam) im Körper ist — das sogenannte
IOB (Insulin On Board, Insulin an Bord).
Das Modell folgt dem exponentiellen Ansatz von LoopKit/OpenAPS, der für
schnell-wirksame Analoga (NovoRapid, Humalog, Fiasp) entwickelt wurde.
DIA_MIN = 270 Minuten = 4,5 Stunden
→ Nach DIA Minuten ist das Insulin vollständig abgebaut.
→ Höheres DIA = Insulin wirkt länger, weniger aggressiv am Anfang
→ Niedrigeres DIA = Insulin wirkt kürzer, mehr Wirkung früh
TP_MIN = 75 Minuten = 1,25 Stunden
→ Nach TP Minuten ist die Insulinaktivität (Wirkrate) am höchsten
→ Niedrigeres TP = Insulin wirkt früher am stärksten (z.B. Fiasp: ~55 min)
→ Höheres TP = Wirkmaximum kommt später (träges Profil)
Die IOB-Kurve zeigt, welcher Anteil eines Bolus noch aktiv ist:

Ablesen der Kurve:
- Y-Achse: 1.0 = frisch injiziert (100% noch aktiv), 0.0 = vollständig abgebaut
- X-Achse: Zeit nach Injektion in Minuten
- Bei DIA=270, TP=75 (Standardprofil NovoRapid): nach 90 min noch ~70% aktiv,
nach 180 min noch ~20%, nach 270 min = 0%
Die Wirkrate ist der erste Ableitung der IOB-Kurve und zeigt, wie viel Insulin
pro Zeiteinheit gerade wirksam wird (also BZ senkt):
t = TP_MINt = DIA_MINPraxisbeispiel: 1 Einheit NovoRapid (DIA=270, TP=75)
- Maximale BZ-Senkung: ~0.7 mg/dL pro Minute bei t=75 min
- Gesamte BZ-Senkung: ISF mg/dL (z.B. ISF=100 → senkt um 100 mg/dL über 4,5h)
Diabotus unterstützt unterschiedliche PK-Parameter für Tag und Nacht:
| Parameter | Tag | Nacht (22–6 Uhr) |
|---|---|---|
| DIA | 270 min (4,5h) | 270 min (4,5h) |
| TP | 75 min | 75 min |
| ISF | aus model_isf_profile |
aus model_isf_profile |
Aktuell sind Tag- und Nacht-DIA/TP identisch. Die Unterschiede kommen
stattdessen aus dem stündlichen ISF-Profil (→ Kapitel 7).

Was wäre der Unterschied wenn Nacht-TP kleiner wäre?
Ein niedrigeres Nacht-TP (z.B. 55 min) würde bedeuten: Insulin wirkt in der
Nacht schneller und aggressiver – das braucht man normalerweise nicht, weil
die Insulinsensitivität nachts oft höher ist (höherer ISF).
Die Pumpe gibt Basalinsulin kontinuierlich ab. Diabotus modelliert das als
synthetische Micro-Boli alle 5 Minuten:
Basalrate 0.8 E/h →
alle 5 min: 0.8 × 5/60 = 0.0667 E als "_basal"-Event
Jeder dieser Micro-Boli hat seine eigene IOB-Kurve. Das Gesamt-IOB aus dem
Basalinsulin ist die Summe aller noch aktiven Micro-Boli.
Kohlenhydrate heben den BZ nicht sofort, sondern werden erst über den
Darm aufgenommen. Diabotus modelliert das als lineare Absorption:
KH werden gleichmäßig über die Absorptionszeit aufgenommen.
COB (Carbs on Board) = Verbleibende KH, die noch nicht absorbiert wurden.

Verschiedene Lebensmittel haben sehr unterschiedliche Absorptionsgeschwindigkeiten:
| Typ | Dauer | Typische Lebensmittel |
|---|---|---|
very_fast |
30 min | Traubenzucker, Glukosegel, Dextro |
fast |
60 min | Saft, Gummibärchen, Softdrinks |
medium |
120 min | Brot, Müsli, Cornflakes, Weißbrot |
slow |
180 min | Nudeln, Reis, Pizza, Kartoffeln |
very_slow |
240 min | Hülsenfrüchte, sehr fettreiche Mahlzeiten |
Standard (wenn nicht angegeben): medium = 120 Minuten (wird als 180 min
behandelt wenn kein Typ gesetzt – Fallback = CARB_ABS_MIN = 180 min)
Tipp: Beim Eingeben von Mahlzeiten immer den Absorptionstyp mitgeben!
Beispiel:"Nora isst 60g Nudeln, slow, 5.45E"
Das macht die Prognose deutlich genauer.
Beispiel: 30g KH mit richtiger Bolus-Menge
Bei fast-Absorption absorbiert das KH innerhalb von 60 min vollständig –
das Insulin (das 75 min bis zum Maximum braucht) wirkt aber erst später.
→ Risiko: Hypoglykämie nach der Mahlzeit!
Bei slow-Absorption sind nach 60 min erst 33% der KH absorbiert –
Insulin und KH kommen gleichzeitiger.
→ Flacherer, sichererer Verlauf

Fett und Protein können ebenfalls den BZ erhöhen, aber sehr verzögert:
- Zeitverzögerung: Wirkung beginnt erst 60 Minuten nach der Mahlzeit
- Gesamtdauer: 240 Minuten (sehr langsame Absorption)
- Faktor Fett: 10% des Fettgewichts als KH-Äquivalent
- Faktor Protein: 50% des Proteingewichts als KH-Äquivalent
Beispiel Pizza (60g KH, 18g Fett, 12g Protein):
FPE = 18 × 0.10 + 12 × 0.50 = 1.8 + 6.0 = 7.8g KH-Äquivalent
Absorption: beginnt 60 min nach der Pizza, über 240 min linear
Hinweis: Das FPE-Modell ist implementiert (
build_fpe_events()), wird
aber nur genutzt wennfat_gund/oderprotein_gim Event hinterlegt sind.
Die Tandem t:slim X2 Pumpe von Nora hat Control-IQ (CIQ) – ein Closed-Loop-
System, das automatisch die Basalrate anpasst:
Das bedeutet: Nora bekommt nicht immer die "programmierte" Basalrate, sondern
eine durch CIQ dynamisch angepasste Rate.
Diabotus hat aus 90 Tagen Glooko-Daten (8.024 Messpunkte) ein empirisches
Modell des CIQ-Verhaltens trainiert:

Wie man den Plot liest:
- X-Achse: Novas aktueller BZ (mg/dL)
- Y-Achse: Faktor, mit dem die programmierte Rate multipliziert wird
- Faktor 1.0 = Pumpe liefert exakt die programmierte Rate
- Faktor 0.35 bei BZ=80 = Pumpe gibt nur 35% der programmierten Rate ab
- Faktor 4.3 bei BZ=200 = Pumpe gibt 430% der programmierten Rate ab!
- Die drei Linien zeigen den Einfluss des BZ-Trends (fallend/stabil/steigend)
Crossover-Punkt: BZ ≈ 119 mg/dL → bei diesem BZ liefert CIQ exakt die
programmierte Rate (Faktor = 1.0). Dieser Wert entspricht dem CIQ-Ziel-BZ.
Technische Details des Modells:
Modell: GradientBoostingRegressor (sklearn)
Training: 8.024 Segmente aus glooko_basal_raw (5-min-Takt)
CV R²: 0.66 (erklärt 66% der Ratenvarianz)
Globales Durchschnittsverhältnis: 1.87
(CIQ liefert im Schnitt 87% mehr als programmiert – weil Nora oft BZ > 119)
Features (nach Wichtigkeit):
BZ aktuell 37% ← wichtigster Faktor
Tageszeit (cos) 25%
Tageszeit (sin) 25%
BZ-Lags 11% (BZ vor 5 und 10 min)
BZ-Trend 2%
Zusätzlich zur Basalraten-Anpassung gibt CIQ stündliche Auto-Boli ab:
Sleep-Modus (22–6 Uhr):
- Auslöser: Vorhergesagter BZ in 30 min > 120 mg/dL
- Maximale Bolus-Größe: 80% der programmierten Stunden-Basaldosis
- Mindestabstand: 60 Minuten zwischen Auto-Boli
Normal-Modus (6–22 Uhr):
- Auslöser: Vorhergesagter BZ in 30 min > 160 mg/dL
- Maximale Bolus-Größe: 60% der programmierten Stunden-Basaldosis
- Mindestabstand: 60 Minuten
Die Vorhersage erfolgt durch lineare Extrapolation über die letzten 15 Minuten.

Bei !prognose nutzt Diabotus das CIQ-Modell im Feedback-Regelkreis:
Für jeden 5-min-Schritt in der Prognose:
1. Aktuellen (prognostizierten) BZ abrufen
2. Pump-Modell fragen: "Welche Rate gibt CIQ bei BZ=X ab?"
3. Diese tatsächliche Rate als Insulin-Event einbuchen
4. IOB und BZ-Delta berechnen
Das macht die Prognose realistischer als wenn man nur mit der programmierten
Basalrate rechnen würde.
project_glucose()?Die Prognosefunktion berechnet den erwarteten BZ-Verlauf für die nächsten
N Minuten. Sie kombiniert:
Basisformel pro Zeitschritt:
ΔBZ = (KH absorbiert in diesem Schritt) × (ISF / KH-Faktor)
- (IOB-Abnahme in diesem Schritt) × ISF
Mit Trend-Anchoring:
ΔBZ = (1 - w) × Modell-Delta + w × Beobachteter-Trend
wobei w = 0.5^(vergangene Zeit / 45 min) – exponentiell abnehmend
Das Trend-Anchoring sorgt dafür, dass die Prognose anfangs dem beobachteten
BZ-Trend folgt (realistisch), und nach ~45 min stärker auf das Modell
umschaltet.
Der Insulinsensitivitätsfaktor (ISF) ist nicht den ganzen Tag gleich. Diabotus
nutzt ein stündliches ISF-Profil (model_isf_profile):
Was ISF bedeutet:
ISF = 100 mg/dL/E → 1 Einheit Insulin senkt den BZ um 100 mg/dL
Beim Einschlafen steigt Noras BZ typischerweise an – unabhängig vom Insulin.
Das liegt an:
- Reduzierter Muskeltätigkeit (weniger Glukoseverbrauch)
- Wachstumshormonausschüttung (erhöht Insulinresistenz kurzfristig)
- Hepatischer Glukoseabgabe (Leber gibt Glukose ins Blut ab)
Diabotus modelliert das als synthetische Glukosezufuhr beim Einschlafen:
Parameter (anpassbar via !meta):
sleep_hepatic_glucose_g = 15g (KH-Äquivalent der hepatischen Glukose)
sleep_hepatic_duration_min = 90min (Absorptionsdauer)
Das erzeugt beim Einschlafen einen erwarteten BZ-Anstieg von etwa
15g × ISF / KH-Faktor:
Beispiel (ISF=100, KH-Faktor=12g/E):
15g × 100 / 12 ≈ +125 mg/dL über 90 min
(davon Basalinsulin gegenläufig: netto typisch +30–50 mg/dL)

Wie gibt man Einschlafzeiten ein?
Bot: "Nora schläft ein" → speichert {"onset": "aktuelle Uhrzeit"}
Bot: "Nora ist aufgewacht" → speichert {"wake": "aktuelle Uhrzeit"}
Ohne explizite Eingabe verwendet Diabotus die Standardzeiten:
- Wochentag: Einschlafen 20:45, Aufwachen 06:30
- Wochenende: Einschlafen 20:45, Aufwachen 07:00
Diese Werte sind in der Datenbank hinterlegt und gelten für Nora im Mai 2026.
Alle Werte können via !meta angepasst werden.

Der obige Plot zeigt alle vier zeitabhängigen Profile auf einen Blick:
- ISF (oben links): Sensitivität schwankt von 85 (morgens) bis 133 (mittags)
- Basalrate (oben rechts): Sehr niedrig nachts (0.1 E/h), höchste Rate abends (1.3 E/h)
- KH-Faktor (unten links): Morgens nur 5g/E (sehr resistent), nachts 25g/E (sensitiv)
- Bolus-Rechner (unten rechts): 45g KH zu verschiedenen Zeiten – zeigt die Variabilität
Die programmierte Basalrate der Pumpe (E/h):
| Uhrzeit | Rate (E/h) | Bemerkung |
|---|---|---|
| 00:00–02:00 | 0.10 | Tiefe Nacht, sehr niedrig |
| 02:00–04:00 | 0.15 | |
| 04:00–06:00 | 0.55 | Dämmerungsanstieg (Dawn Phenomenon) |
| 06:00–08:00 | 0.60 | |
| 08:00–10:00 | 0.45 | |
| 10:00–11:00 | 0.30 | |
| 11:00–12:00 | 0.20 | |
| 12:00–15:00 | 0.125 | Mittagstief |
| 15:00–16:00 | 0.30 | |
| 16:00–17:00 | 0.40 | |
| 17:00–18:00 | 0.50 | |
| 18:00–19:00 | 0.80 | Abend-Anstieg |
| 19:00–20:00 | 1.25 | |
| 20:00–22:00 | 1.30 | Höchste Rate: Abend/Einschlafen |
| 22:00–23:00 | 0.50 | |
| 23:00–24:00 | 0.10 |
Wichtig: CIQ passt diese Raten dynamisch an. Die tatsächlich abgegebene
Rate kann erheblich davon abweichen (Faktor 0.3–4.3×).
Wie viele Gramm KH werden durch 1 Einheit Insulin gedeckt:
| Uhrzeit | KH-Faktor (g/E) | Bedeutung |
|---|---|---|
| 00:00–04:00 | 25 | Nacht: sehr empfindlich |
| 04:00–06:00 | 10 | Früh: resistent |
| 06:00–08:00 | 5 | Frühmorgens: sehr resistent → viel Insulin pro KH |
| 08:00–10:00 | 5.5 | |
| 10:00–11:00 | 15 | |
| 11:00–15:00 | 13 | |
| 15:00–16:00 | 15 | |
| 16:00–19:00 | 11 | |
| 19:00–22:00 | 12 | |
| 22:00–24:00 | 20 | Spät-Abend: sehr empfindlich |
Bolus-Formel: Insulin (E) = KH (g) ÷ KH-Faktor (g/E)
Beispiel: 60g Nudeln um 18 Uhr → 60 ÷ 11 = 5.45 Einheiten
Das stündliche ISF-Profil aus model_isf_profile (in mg/dL/E):
| Stunden | ISF | Einordnung |
|---|---|---|
| 0–5 Uhr | 100 | Nacht: sehr sensitiv |
| 6–9 Uhr | 85 | Morgens: etwas resistenter (Dawn) |
| 10 Uhr | 121 | |
| 11 Uhr | 133 | Mittags: sensibler |
| 12–14 Uhr | 115 | |
| 15–17 Uhr | 117–121 | |
| 18–19 Uhr | 97 | Abend: etwas resistenter |
| 20 Uhr | 120 | |
| 21–23 Uhr | 100 |
Korrektur-Formel: Korrektur (E) = (Aktueller BZ − Ziel-BZ) ÷ ISF
Beispiel: BZ=200, Ziel=100, ISF=100 → (200−100)÷100 = 1.0 Einheit
| Parameter | Wert |
|---|---|
| Nacht-Start | 22:00 Uhr |
| Nacht-Ende | 06:00 Uhr |
| DIA (beide) | 270 min |
| TP (beide) | 75 min |
| Parameter | Wert |
|---|---|
| Hepatische Glukose | 15g |
| Absorptionsdauer | 90 min |
| Einschlaf Wochentag | 20:45 Uhr |
| Aufwachen Wochentag | 06:30 Uhr |
| Einschlaf Wochenende | 20:45 Uhr |
| Aufwachen Wochenende | 07:00 Uhr |
Das Modell sollte angepasst werden wenn:
- Die Prognosen systematisch zu hoch oder zu niedrig sind (Bias > ±20 mg/dL)
- Nora gewachsen ist (Insulin-Bedarf ändert sich)
- Neue Therapiewerte von der Kinderdiabetologie vorliegen
- Der ISF sich saisonal ändert (Sommer vs. Winter)
!tune – automatische Prognose-ValidierungDer !tune-Befehl vergleicht gespeicherte Prognosen mit den tatsächlich
gemessenen BZ-Werten:
!tune
→ MAE (mittlerer absoluter Fehler) pro Stunde
→ Bias (+ = Modell überschätzt BZ, − = Modell unterschätzt)
→ Empfehlungen für ISF-Anpassungen
!meta "Der Nacht-ISF zwischen 0 und 5 Uhr scheint zu hoch zu sein,
bitte von 100 auf 90 mg/dL/E reduzieren"
!meta "Die mittlere Absorptionszeit für 'medium' scheint eher 90 min
als 120 min zu sein für Nora – bitte CARB_ABS_MIN anpassen"
!meta "Der Einschlaf-Anstieg ist bei Nora eher +20 mg/dL als +40 mg/dL,
bitte sleep_hepatic_glucose_g von 15 auf 8 reduzieren"
Das CIQ-Pump-Modell wird neu trainiert nach jedem Glooko-Import:
cd /home/schruste/diabotus
source venv/bin/activate
python pump_model.py
Das Modell braucht mindestens 2.000 Datenpunkte und einen aktuellen Glooko-Export
in glooko_basal_raw.
Die folgenden Szenarien illustrieren das Modellverhalten ohne Datenbankzugriff.
Sie können mit python docs/examples.py regeneriert werden.

Nora hat BZ=100 und nimmt 5g Traubenzucker (very_fast, Absorption 30 min).
Kein Insulin wird gegeben. Das Modell erwartet:
- BZ-Anstieg: +20–25 mg/dL innerhalb von 30 min
- Anschließend: BZ fällt wieder leicht (laufendes Basalinsulin)

BZ=140, 60g Nudeln (slow, 180 min), korrekter Bolus (60g ÷ ISF-angepasst).
Typischer Verlauf: BZ steigt anfangs 30–50 mg/dL, kehrt dann über 3h zurück.

BZ=200, Korrekturbolus. Drei Kurven für ISF=80/100/120 zeigen, wie stark
der Bolus den BZ senkt. Mit ISF=100 und 1E: BZ erreicht nach 3–4h ~100 mg/dL.
Dokumentation generiert mit docs/examples.py.
Diagramme aktualisieren: cd /home/schruste/diabotus && python docs/examples.py