7.3 KiB
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
rejectedwenn: zu wenige Trades (min_trades_is/oos), Drawdown über Limit, OOS-Degradation zu hoch (Overfit), fachlich unbrauchbare Metriken (z.B. PF<=0/kein Trades). /bestliefert:recommendation=RECOMMENDATION+best_candidatewenn ein fachlich brauchbarer robuster Bester existiert.recommendation=NO_RECOMMENDATION(statt leerembest_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 → beimjson.dumpsincomplete_runnicht serialisierbar (422). Fix: ISO-String-Kopie im Run-Result, datetime bleibt fürstorage.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-HostModul-01-PostgreSQL(Modul-01), Backtest viaModul-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.