--- type: Trading-Modul-System _organized: true --- # Modul-13: Optimization **Status: FREIGEGEBEN ✅** · Container `Modul-13-Optimization` · Image `optimization:0.1.0` ## Zweck Deterministische, reproduzierbare **Parameteroptimierung** für die V1.1-Strategie (`trend_pullback_v1.1`, Modul-12). Findet robuste Parameter im erlaubten Suchraum **ohne KI/LLM und ohne Live-Orders** — Ergebnis ist nur **CANDIDATE/RECOMMENDATION**, es gibt keine automatische Parameterübernahme in Modul-05. ## Kernprinzipien - **Deterministisch**: gleiche Eingaben → gleiche Kandidaten, Reihenfolge, run_hash (kein Zufall außer explizit via Seed). - **Kein Lookahead**: IS/OOS strikt zeitlich getrennt; **OOS wird nie zur Selektion verwendet**. - **IS/OOS strikt**: `is_ratio` (z.B. 0.7) teilt die Daten; OOS ausschließlich zur Validierung. - **Robuste Bereiche > Einzelmax**: best = Kandidat mit bester kombinierter Score (nicht max net_pnl). - **Reject-/Overfit-Logik**: zu wenige Trades, DD-Limit, IS/OOS-Degradation → Kandidat wird `rejected`. - **Parametergrenzen zwingend**: Suchraum begrenzt auf `pullback_band_atr`, `trend_regime_window`, `rr_multiplier`. - **Score-Gewichte**: Expectancy/R 0.30, PF 0.25, Max-Drawdown 0.20, Trades 0.10, Stabilität 0.15. - **Synchron**: Request/Response über API (kein RabbitMQ). ## Architektur / Datenfluss ``` OHLCV (Modul-01 PostgreSQL, Tabelle ohlcv) │ synchron, direkt nach Timestamp/Zeitraum ▼ Modul-13-Optimization ── POST /optimization │ ├── core/split.py IS/OOS + Walk-Forward-Folds (kein Leakage) ├── core/optimizer.py Grid/Random-Suche, ScoreEngine, WF, Reject ├── core/scoring.py Multi-Metrik-Score (Gewichte siehe oben) ├── storage/storage.py Persistenz optimization_run/candidate/walk_forward ├── backtest_client.py synchroner Aufruf Modul-12 (POST /backtest) └── api/main.py REST-API (intern, Port 55013) ``` API (Docker-intern, Port 55013, kein öffentliches Port-Mapping): ``` GET /health, /health/ready POST /optimization Start (Grid/Random), synchron GET /optimization Liste aller Runs GET /optimization/{id} Run-Metadaten + Status GET /optimization/{id}/candidates Kandidaten + Multi-Metrik-Ranking GET /optimization/{id}/best bester ROBUSTER Kandidat (RECOMMENDATION/NO_RECOMMENDATION) GET /optimization/{id}/walk-forward Walk-Forward-Folds ``` ## Suchraum (V1.1 — NUR 3 optimierbare Parameter) | Parameter | Suchraum (E2E) | Zweck | |-----------|----------------|-------| | `pullback_band_atr` | {0.2, 0.5, 0.8, 1.0} | ATR-Band um EMA20 (Pullback-Timing) | | `trend_regime_window` | {60, 200, 300} | Fenster für strategie-internes Trend-Regime | | `rr_multiplier` | {1.0, 2.0, 3.0} | Target = Entry + rr×Risiko | Fix (nicht optimiert): `atr_period=14`, `regime_vol_override=false`, `min_risk_reward=1.0`, ADX-/EMA-Perioden (14/20/30), `adx_trend_threshold=20`. ## Profile | Profil | min_trades_is | min_trades_oos | max_drawdown_limit | max_oos_degradation | Zweck | |--------|---------------|----------------|--------------------|--------------------|-------| | **produktion** (Default) | 3 | 1 | 0.30 | 0.5 | Anti-Overfit, Produktion | | **test** (`profile=test`) | 1 | 1 | — | — | nur Mindest-Trade-Schwellen gesenkt für technischen E2E; sonst identisch | Das TEST-PROFIL senkt **ausschließlich** die Mindest-Trade-Schwellen (damit ein Sweep über die kalibrierte synthetische Fixture genügend Kandidaten akzeptiert). Produktive Anti-Overfit-Defaults bleiben unverändert. `profile` wird per API-Feld übergeben; explizite Request-Werte (`min_trades_is/oos`) haben Vorrang. ## Eigene Tabellen (Migration) - `optimization_run` — Run-Metadaten: optimization_id, strategy+version, symbol, timeframe, optimizer_method, optimizer_version, param_space, seed, status, result (JSON), created/completed_at. - `optimization_candidate` — Kandidaten: rank, params, backtest_run_id_is/oos, is_metrics, oos_metrics, score, score_components, rejected, reject_reasons, flags, stability, robustness. - `walk_forward_result` — WF-Folds: fold, params, is_start/end, oos_start/end, is/oos_metrics, score, backtest_run_id_is/oos. ## Reject-/Overfit- und Recommendation-Verhalten - Kandidat wird `rejected` wenn: zu wenige Trades (min_trades_is/oos), Drawdown über Limit, OOS-Degradation zu hoch (Overfit), fachlich unbrauchbare Metriken (z.B. PF<=0/kein Trades). - `/best` liefert: - `recommendation=RECOMMENDATION` + `best_candidate` wenn ein fachlich brauchbarer robuster Bester existiert. - `recommendation=NO_RECOMMENDATION` (statt leerem `best_candidate`), wenn das Kandidatenfeld fachlich unbrauchbar ist — eine produktive Empfehlung wird nie aus unbrauchbaren Daten erzeugt. ## Tests - `tests/test_optimization.py`: 12/12 grün (Grid deterministisch, Random-Seed, IS/OOS-Leak, Walk-Forward korrekt + JSON-serialisierbar, Multi-Metrik-Ranking, Reject/Overfit, Robustheit, Suchraum=3 Params, Reproduzierbarkeit, NO_RECOMMENDATION, TEST-PROFIL). ## E2E-Verifikation (VPS, 20.08.2026) - **Suchraum-Differenzierung** (kalibrierte Fixture `M13_E2E`, 1314 Bars, alle 3 Params unterscheidbar): - `pullback_band_atr`: 0.2→8 Trades, 0.5→9–10, 0.8/1.0→1 Trade. - `trend_regime_window`: bei pba=0.5: 60→9 Trades vs 200/300→10 Trades. - `rr_multiplier`: 1.0→8–10 Trades (net +828…+1046), 2.0/3.0→1 Trade. - **12/12 E2E-Punkte über API bestätigt** (e2e_full.py): Grid deterministisch, Random-Seed identisch, IS/OOS-Leak ausgeschlossen, WF-Folds zeitlich korrekt + DB-persistiert (3 Folds), Multi-Metrik-Ranking, Reject-Logik (36 Kandidaten, 30 rejected / 6 accepted), best=robust + RECOMMENDATION, DB-Run/Candidates vollständig, API list_runs, Reproduzierbarkeit (status COMPLETED), NO_RECOMMENDATION bei nur-1-Trade Konfiguration (produktion-Profil). - **Bugfix C**: Walk-Forward-Fold-Ergebnisse enthalten `datetime`-Timestamps → beim `json.dumps` in `complete_run` nicht serialisierbar (422). Fix: ISO-String-Kopie im Run-Result, datetime bleibt für `storage.insert_wf`. Verifiziert (3 WF-Folds in DB). - Health `/health/ready` → `{"status":"ready","db":"ok"}` (M13 und M12). Keine Tracebacks. - Port 55013 nur intern (`expose`), kein Host-Port-Binding (verifiziert). ## Freigabe - **20.08.2026: Modul-13-Optimization-Service vom Nutzer FREIGEGEBEN ✅** (nach vollständiger E2E-Verifikation: 12/12 API-Punkte, Suchraum-Differenzierung für alle 3 Params, TEST-PROFIL, NO_RECOMMENDATION, Bugfixes A/B/C deployt, Tests 12/12 grün). - Keine weiteren technischen Änderungen an Modul-13. ## Compose / Betrieb - Netzwerk `trading-modules`, DB-Host `Modul-01-PostgreSQL` (Modul-01), Backtest via `Modul-12-Backtesting` (intern). Port 55013 nur intern (`expose`), `restart: unless-stopped`. ## Nächste Module - **Modul-14 ff.** — noch Platzhalter (alpine), NICHT gestartet. --- ## Geändert ``` Geändert von: Rain Ocampo Datum: 20.08.2026 Grund: Modul-13-Optimization dokumentiert — E2E-verifiziert (12/12 Punkte), Suchraum-Diffusion für alle 3 Params, TEST-PROFIL, NO_RECOMMENDATION, Bugfix C (WF-JSON-datetime). Geändert von: Rain Ocampo Datum: 20.08.2026 Grund: Modul-13 vom Nutzer FREIGEGEBEN — Status auf FREIGEGEBEN gesetzt, Freigabe-Sektion ergänzt. Keine technischen Änderungen. ```