trading-system-docs/notes/trading/system-docs/modul-13-optimization.md
Red Queen 022c30e537 feat(tolaria): migrate C3H HR wave 1 — 16 safe root↔canonical pairs to schema v1
C3H HUMAN REVIEW WAVE 1: migriert 16 freigegebene HR-A PAIR_MIGRATION_SAFE Paare.
Pro Pair: Root (representation=source) + Canonical (representation=canonical,
derived_from=Root-ID) atomar. Body byte-genau unveraendert. IDs stabil aus
C3 Mapping Preview v2. modul-12/18/19/vps.md NICHT angefasst.
Knowledge schema v1. (Red Queen)
2026-08-25 19:19:02 +00:00

142 lines
7.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
knowledge_schema: 1
id: object/2c48489e-0fb9-bdbf-8000-6bbba26771fb
type: arch
role: module
representation: canonical
state: current
derived_from: object/bde121b1-121f-590d-2b54-fedc13b02173
_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→910, 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→810 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.
```