diff --git a/.gitignore b/.gitignore index b084b3e..2ab7981 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,6 @@ data/*.backup* data/generated_tips/weekly_lotto_tips_*.csv data/performance_reports/ data/data/ + +# graphify Code-Graph (regenerierbar via /graphify --update) +graphify-out/ diff --git a/documentation/ARCHITECTURE.md b/documentation/ARCHITECTURE.md new file mode 100644 index 0000000..bb17a8d --- /dev/null +++ b/documentation/ARCHITECTURE.md @@ -0,0 +1,163 @@ +# 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
20 Features] + C --> D[AIMLEngine
RandomForest, 40 Zahlen] + C --> E[DeepLearningEngine
LSTM, PyTorch] + D --> F[Hybrid Predictor
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 /
strategy_weights] + end + + J --> M[LottoNotifier
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. Unterstützt 3 Quellen (Lottoland, GitHub-Archiv, lottoAPI) über `fetch_from_all_apis()`, **aber** `auto_update_and_learn.py` ruft aktuell fest `api_name='github'` auf — Lottoland/lottoAPI-Fallback ist im Code vorhanden, aber nicht verdrahtet (siehe Abschnitt 5). | +| `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 + +- **Ungenutzter Fallback:** `LottoAPIUpdater.fetch_from_all_apis()` unterstützt + Lottoland → GitHub → lottoAPI als Fallback-Kette, aber + `AutoUpdateAndLearn.update_data()` ruft fest `api_name='github'` auf. Bei + Verzögerungen der GitHub-Quelle (schon mehrfach vorgekommen) hinkt die + Pipeline entsprechend hinterher, obwohl Lottoland oft schneller aktuell ist. +- **`update_from_web.py`** (lotto.de-Scraper) ist als dritter Fallback + implementiert, aber nirgends in der automatisierten Pipeline eingebunden. +- **Legacy-Generatoren im Projekt-Root** (`ultimate_lotto_6aus49_generator.py`, + `super_lotto_generator.py`, `ai_ml_lotto_generator.py`, + `pattern_weighted_ai_generator.py`, `ultimate_hybrid_lotto_generator.py`) + sind eigenständige, ältere Implementierungen und **nicht** Teil der + automatisierten Pipeline (die nutzt ausschließlich + `scripts/generators/ultimate_ai_ml_hybrid_generator.py`). Vor Änderungen an + "dem Generator" prüfen, welche Datei gemeint ist. +- **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.