AutoUpdateAndLearn.update_data() called LottoAPIUpdater with api_name='github', which skipped the already-implemented Lottoland -> GitHub -> lottoAPI fallback chain entirely. The GitHub archive alone has repeatedly lagged 1-6 days behind actual draws (most recently the Aug 5 draw, still missing as of Aug 7), causing tips to be generated and models to be retrained on stale data. Switching to api_name='all' tries Lottoland first, which has consistently had same-day results in testing, with GitHub still covering full history/fallback. Also includes the Aug 5 draw pulled in via this fix and the resulting model retrain (data update was previously interrupted by a truncated pipe during manual testing, this completes it). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
152 lines
8.1 KiB
Markdown
152 lines
8.1 KiB
Markdown
# Architektur
|
||
|
||
Dieses Dokument beschreibt den aktiven Datenfluss, die Kernkomponenten und die
|
||
wichtigsten Design-Entscheidungen des Lotto-6aus49-Systems. Es wurde mit Hilfe
|
||
einer Code-Graph-Analyse (`graphify-out/`, siehe unten) erstellt und sollte bei
|
||
größeren strukturellen Änderungen aktualisiert werden.
|
||
|
||
## 1. Aktiver Datenfluss
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph Ingestion["1. Daten-Ingestion"]
|
||
A[GitHub Lotto Archive] -->|LottoAPIUpdater| B[AlleLottozahlen.csv]
|
||
end
|
||
|
||
subgraph Training["2. Training"]
|
||
B --> C[FeatureEngineer<br/>20 Features]
|
||
C --> D[AIMLEngine<br/>RandomForest, 40 Zahlen]
|
||
C --> E[DeepLearningEngine<br/>LSTM, PyTorch]
|
||
D --> F[Hybrid Predictor<br/>RF 40% + LSTM 60%]
|
||
E --> F
|
||
end
|
||
|
||
subgraph Generation["3. Tipp-Generierung"]
|
||
F --> G[UltimateAIMLHybridGenerator]
|
||
G --> H1[HYBRID-OPT]
|
||
G --> H2[BALANCED-SPREAD]
|
||
G --> H3[HIGH-EV]
|
||
G --> H4[SOFT-CONTRARIAN]
|
||
H1 & H2 & H3 & H4 --> I[Quality/Popularity Score]
|
||
I --> J[10 Tipps als CSV]
|
||
end
|
||
|
||
subgraph Learning["4. Learning-Loop"]
|
||
B -->|neue Ziehung| K[AutoUpdateAndLearn]
|
||
K -->|evaluiert| J
|
||
K -->|retrained| D
|
||
K -->|retrained| E
|
||
K --> L[learning_log.json /<br/>strategy_weights]
|
||
end
|
||
|
||
J --> M[LottoNotifier<br/>Telegram]
|
||
K --> M
|
||
|
||
L -.->|beeinflusst nächsten Lauf| G
|
||
```
|
||
|
||
**Zwei unabhängige Cron-Zyklen** (siehe Abschnitt 4):
|
||
|
||
| Schritt | Entrypoint | Ausführt |
|
||
| --- | --- | --- |
|
||
| Ingestion + Training + Learning | `run_update_and_learn.sh` → `scripts/automation/auto_update_and_learn.py` | Mi + Sa, 20:00 Uhr |
|
||
| Tipp-Generierung | `run_tip_generator.sh` → `scripts/automation/weekly_tip_generator.py` | Di + Fr, 21:00 Uhr |
|
||
|
||
Wichtig: Die Tipp-Generierung läuft **vor** dem nächsten Update-Lauf. Das
|
||
System hinkt daher strukturell immer bis zu einem Zyklus hinter neu
|
||
verfügbaren Ziehungen hinterher, falls die externe Datenquelle verspätet
|
||
aktualisiert (siehe Abschnitt 5).
|
||
|
||
## 2. Kernkomponenten (aktive Pipeline)
|
||
|
||
Alle Pfade relativ zum Projekt-Root.
|
||
|
||
| Komponente | Datei | Rolle |
|
||
| --- | --- | --- |
|
||
| `LottoAPIUpdater` | `scripts/utils/update_from_api.py` | Holt neue Ziehungen über `fetch_from_all_apis()`: Lottoland zuerst (liefert die neueste Ziehung meist noch am Ziehungstag), GitHub-Archiv für die Historie/als Fallback (kann tagelang hinterherhinken). `auto_update_and_learn.py` nutzt seit August 2026 `api_name='all'`, davor fest `api_name='github'` — daher wiederholt verspätete Ziehungen in der Vergangenheit. |
|
||
| `AutoUpdateAndLearn` | `scripts/automation/auto_update_and_learn.py` | Orchestriert den 4-Schritte-Workflow: Daten aktualisieren → neue Ziehung prüfen → letzte Tipps evaluieren → Learning-Update (Retraining). |
|
||
| `FeatureEngineer` | `scripts/generators/ultimate_ai_ml_hybrid_generator.py` | Baut 20 Features (Frequenzen, Gaps, Momentum, Trends, Beziehungen, Zyklen) aus den Rohdaten. |
|
||
| `AIMLEngine` | `scripts/generators/ultimate_ai_ml_hybrid_generator.py` | RandomForest-Modelle, ein Modell pro Zahl (1–49). Cached unter `data/ultimate_ml_models/`. |
|
||
| `DeepLearningEngine` | `scripts/utils/deep_learning_engine_pytorch.py` | LSTM (PyTorch) über Sequenzen der letzten 20 Ziehungen. Wird mit RF zu 40/60 kombiniert (`Hybrid Predictor`). |
|
||
| `UltimateAIMLHybridGenerator` | `scripts/generators/ultimate_ai_ml_hybrid_generator.py` | **God Node der Pipeline** (35 Kanten im Code-Graph) — verbindet Training, die 4 Tipp-Strategien und den Quality/Popularity-Score. Zentraler Einstiegspunkt für `generate_ultimate_tips()`. |
|
||
| `PatternEngine` | `scripts/generators/ultimate_ai_ml_hybrid_generator.py` | Historische Verteilungsmuster (N/M/H-Zonen etc.), fließt als `pattern_weight` in die Tipp-Bewertung ein. |
|
||
| `HybridOptimizer` | `scripts/generators/ultimate_ai_ml_hybrid_generator.py` | Kandidaten-Generierung für die HYBRID-OPT-Strategie. |
|
||
| `RealTimeLearner` | `scripts/generators/ultimate_ai_ml_hybrid_generator.py` | Persistiert Learning-State (`learning_state.json`), passt `strategy_weights` nach jedem Zyklus an (`_update_strategy_weights`). |
|
||
| `PerformanceTracker` | `scripts/generators/ultimate_ai_ml_hybrid_generator.py` | Loggt Trefferauswertungen nach `data/learning_log.json`. |
|
||
| `WeeklyTipGenerator` | `scripts/automation/weekly_tip_generator.py` | Ruft `generate_ultimate_tips()`, exportiert CSV nach `data/generated_tips/`, aktualisiert `generation_history.json`. |
|
||
| `LottoNotifier` | `scripts/utils/notifier.py` | Telegram-Benachrichtigungen für neue Tipps und Ziehungsergebnisse. |
|
||
|
||
### Die 4 Tipp-Strategien
|
||
|
||
Pro Lauf werden 10 Tipps über 4 Strategien verteilt (Gewichtung passt sich
|
||
über `RealTimeLearner` dynamisch an, Startwerte: HYBRID-OPT 40%,
|
||
BALANCED-SPREAD 30%, HIGH-EV 20%, SOFT-CONTRARIAN 10%):
|
||
|
||
- **HYBRID-OPT** — AI-Score + Pattern-Gewicht kombiniert (`HybridOptimizer`)
|
||
- **BALANCED-SPREAD** — erzwingt Verteilung über N/M/H-Zonen, Summenbereich 127–171
|
||
- **HIGH-EV** — 2–3 Zahlen >31, meidet empirisch belegte populäre Einzelzahlen (siehe Abschnitt 3)
|
||
- **SOFT-CONTRARIAN** — bevorzugt in den letzten 30 Ziehungen unterrepräsentierte Zahlen
|
||
|
||
## 3. Design-Entscheidung: Quality-Score = EV-Optimierung, nicht Trefferprognose
|
||
|
||
Lotto-6aus49-Ziehungen sind mechanisch geprüfte, unabhängige Zufallsereignisse
|
||
(i.i.d.). Kein Modell — auch kein LSTM — kann daraus einen Vorteil gegenüber
|
||
reinem Zufall bei der **Trefferwahrscheinlichkeit** ableiten. Das bestätigen
|
||
auch die eigenen `learning_log.json`-Daten: die durchschnittlichen
|
||
Haupttreffer schwanken um den Erwartungswert von Zufallstipps (~0.73 Treffer
|
||
pro 6er-Tipp), ohne erkennbaren Aufwärtstrend trotz kontinuierlichem Retraining.
|
||
|
||
Der `_calculate_quality_score()` in `ultimate_ai_ml_hybrid_generator.py`
|
||
optimiert deshalb bewusst nicht auf Trefferwahrscheinlichkeit, sondern auf
|
||
**Expected Value im Gewinnfall**: unpopuläre Zahlenkombinationen haben bei
|
||
einem Treffer weniger Mitgewinner und damit eine höhere Auszahlung.
|
||
`_calculate_popularity_score()` bewertet dafür (Gewicht 50% der Quality-Formel):
|
||
|
||
1. Geburtstags-Range (>31 bevorzugt)
|
||
2. Empirisch belegte populäre Einzelzahlen (`POPULAR_PLAYER_PICKS`)
|
||
3. Zahlenfolgen/arithmetische Muster (nicht nur direkte Nachbarn)
|
||
4. Odd/Even-Split-Extremität (Menschen bevorzugen "ausgeglichen aussehende" 3-3-Splits)
|
||
|
||
Die Superzahl-Auswahl (`_get_smart_superzahl`) folgt derselben Logik: eine
|
||
feste EV-Rangfolge unpopulärer Ziffern statt (bedeutungsloser) historischer
|
||
Ziehungshäufigkeit, da die Superzahl pro Ziehung unabhängig gleichverteilt ist.
|
||
|
||
AI-Score, Pattern-Gewicht und Recency fließen weiterhin mit reduziertem
|
||
Gewicht in die Quality-Formel ein — nicht weil sie die Trefferchance erhöhen,
|
||
sondern weil eine gewisse Portfolio-Diversität über die 10 Wochentipps
|
||
gewünscht ist.
|
||
|
||
## 4. Automatisierung
|
||
|
||
Die Automatisierung läuft über **launchd** (`~/Library/LaunchAgents/`), nicht
|
||
über `crontab` — die Kommentare in `crontab -l` sind veraltete Doku-Reste und
|
||
spiegeln nicht den tatsächlichen Zeitplan wider:
|
||
|
||
| launchd Job | Plist | Zeitplan (tatsächlich) |
|
||
| --- | --- | --- |
|
||
| `com.lotto.update` | `scripts/automation/com.lotto.update.plist` | Mi + Sa, 20:00 Uhr |
|
||
| `com.lotto.weekly` | `scripts/automation/com.lotto.weekly.plist` | Di + Fr, 21:00 Uhr |
|
||
|
||
Logs: `logs/update_stdout.log` (Update+Learning), `logs/stdout.log`
|
||
(Tipp-Generierung).
|
||
|
||
## 5. Bekannte Schwachstellen / offene Punkte
|
||
|
||
- **`update_from_web.py`** (lotto.de-Scraper) ist als dritter Fallback
|
||
implementiert, aber nirgends in der automatisierten Pipeline eingebunden.
|
||
- **Utility-Skripte** in `scripts/utils/` (`health_check.py`, `validate_csv.py`,
|
||
`verify_draws.py`, `model_evaluator.py`) existieren, sind aber nicht in die
|
||
Cron-Automatisierung eingebunden; manuelle Ausführung bei Bedarf.
|
||
|
||
## 6. Code-Graph
|
||
|
||
Eine navigierbare Graph-Ansicht aller Module, Klassen und ihrer Beziehungen
|
||
liegt unter `graphify-out/`:
|
||
|
||
- `graphify-out/graph.html` — interaktive Visualisierung (im Browser öffnen)
|
||
- `graphify-out/GRAPH_REPORT.md` — God Nodes, Communities, auffällige Verbindungen
|
||
- `graphify-out/graph.json` — Rohdaten (GraphRAG-fähig)
|
||
|
||
Bei größeren strukturellen Änderungen: `/graphify --update` zum
|
||
inkrementellen Neuaufbau.
|