diff --git a/notes/trading/second-brain/Phase10c_Slippage_Deterministic.md b/notes/trading/second-brain/Phase10c_Slippage_Deterministic.md new file mode 100644 index 0000000..ee5b3d6 --- /dev/null +++ b/notes/trading/second-brain/Phase10c_Slippage_Deterministic.md @@ -0,0 +1,105 @@ +--- +type: Note +_organized: true +--- + +# Phase 10c — Deterministische Slippage (DETERMINISTIC_FIXED) + +**Geändert von:** Rain Ocampo (Hermes) +**Datum:** 23.08.2026 +**Grund:** Deterministische Slippage-Komponente `DETERMINISTIC_FIXED` als zusätzliche, eigenständige Ausführungskomponente auf Basis von `LEGACY_SINGLE_PRICE` / `REFERENCE_BID_ASK` — formal/verifikativ abgeschlossen nach Deploy. + +## Zusammenfassung + +Phase 10c führt ein **deterministisches Slippage-Modell** (`slippage_model = DETERMINISTIC_FIXED`, Version `slippage_model_v1`) ein. Slippage ist eine **zusätzliche, eigenständige Komponente** auf dem Fill-Preis — **getrennt vom Spread**. Der Spread bleibt beim Ausführungspfad `REFERENCE_BID_ASK` intrinsisch (`BID_ASK_INTRINSIC`); Slippage wird **erst danach** auf den Fill-Preis aufgeschlagen. Legacy (`LEGACY_SINGLE_PRICE`) bleibt byte-identisch unverändert. + +## Modell & Einheit + +- **`DETERMINISTIC_FIXED`** + `slippage_model_version = slippage_model_v1` +- `slippage_unit = PRICE` → absolute Preisdistanz (keine implizite Umrechnung; Audit zeigt Einheit) +- **Kein** Random/Seed/Volatilität/Liquidität — reproduzierbar +- `NONE` (Default) vs `FIXED(0)`: **gleiche Fillpreise/PnL**, aber **unterschiedlicher ExecutionContext/run_hash** — gewollt + +## Adverse Slippage-Semantik + +- **LONG ENTRY** = ASK + slip, **LONG EXIT** = BID − slip +- **SHORT ENTRY** = BID − slip, **SHORT EXIT** = ASK + slip +- Basis: LONG Entry=ASK / Exit=BID, SHORT Entry=BID / Exit=ASK (unverändert) +- BUY → höher, SELL → tiefer (adversarial) + +## Trigger ≠ Fill + +- Stop/Target-Trigger laufen gegen **Basis-Preise** (ohne Slippage) +- Slippage erst auf den **Fill-Preis** — kein Doppel-Aufschlag + +## Fail-Closed (15) + +- `DETERMINISTIC_FIXED` ohne gültigen Wert → blockiert +- negativ/NaN/Inf/nichtnumerisch → ungültig +- unbekannte Einheit → ungültig +- `NONE`/Default → 0.0, V2-Pfad unverändert + +## ExecutionContext / run_hash / Audit + +- ExecutionContext Default: `NONE`/0.0; V2-Pfad unverändert, wenn nicht gesetzt +- `run_hash` inkl. `slippage_value` + `slippage_unit` (18) +- Audit: `entry/exit_market_price`/`fill_price`/`slippage` (19) +- gleiche Slippage-Konfig 2× → **identischer** run_hash; 0.10 vs 0.20 → anderer; NONE vs FIXED(0) → anderer +- Audit exakt = ExecutionContext + +## Legacy byte-identisch (21) + +- `params["slippage"]` unverändert (Legacy-Slippage-Feld) +- **kein** V2-Slippage-Audit im Legacy-Pfad +- **kein** DatasetGate-Block im Legacy-Pfad + +## Beweis (Tests) + +| Suite | Ergebnis | +|---|---| +| Phase10cSlippage | **30/30** grün (inkl. symmetrischer PnL-Beweis: LONG +2.80 / SHORT +2.80, slip 0.10) | +| Phase10bFixtureE2E | **8/8** grün | +| Phase10bEngine | **7/7** grün | +| Phase10a (execution_context) | **15/15** grün | +| Phase8 | **14/14** grün | +| Phase6/5 | 14/14 / 20/20 grün | +| M13Shared A–J + M13Compat | grün | +| **Gesamtsuite (Runner, nach Deploy)** | **2× alle 12 Suiten grün** | + +## Deployment (kontrollierter Minimal-Deploy, Backup + Rollback) + +- **Backup:** `/opt/data/m12m13_work/backup_phase10c_deploy_20260823_095549/` (m12 5 Dateien, sha256-verifiziert) +- **M12** (`Modul-12-Backtesting`): `core/pricing.py`, `core/engine.py`, `core/service.py`, `api/schemas.py`, `shared/historical/execution_context.py` +- **Verifikation:** Backup+sha256 VORHER, `docker cp`, `chown 1001:1001`, py_compile OK, Import-Smoke OK, Restart; `/health`=200, `/health/ready`=`{"status":"ready","db":"ok"}` (10.0.13.16:55012, intern) +- **M13**: `shared/execution_context.py` vorhanden, /health+ready grün (10.0.13.9:55013) +- **KEINE Phase 10d, keine IG-Calls/Orders, keine V2-Produktivaktivierung** + +## V2-Runtime-Smoke (nach Deploy) + +- `DETERMINISTIC_FIXED` importierbar +- `SlippageUnit.PRICE` importierbar +- `BID_ASK_INTRINSIC` weiterhin korrekt +- `slippage_amount(exec)` liefert erwarteten Wert (0.0001 für FIXED 0.0001) +- LONG entry +slip / SHORT entry −slip (adversarial) +- Audit/ExecutionContext serialisierbar, keine Importfehler + +## Legacy-Produktions-Smoke (nach Deploy, 2 Runs A/B) + +- **run_hash: `bc6e25533d22ee102b6921eeeccd8f7b7dff4ec74a3316e381007ec56b0e1b37`** (A=B, deterministisch) +- **data_hash: `d76a75496453d9c05d5690237f4621534f954f9f3e87b67eee4ae9327c5c6bb9`** (A=B, identisch Phase 8) +- **net_pnl: 196.586062** (A=B), total_trades 1, LONG 1/SHORT 0 +- Trades/Fills/PnL identisch; **Legacy-Slippage unverändert**; kein V2-Audit; kein Gate-Block + +## Produktions-Gate (Final Check) + +- M12: `/health`=200, `/health/ready`=200, `HISTORICAL_DATA_SOURCE=UNSET` (legacy), `ALLOW_FIXTURE_DATA=UNSET` (false) +- M13: `/health`=200, `/health/ready`=200, Gates UNSET +- Keine V2-Produktivläufe, keine Fixture-Aktivierung, keine verwaisten Testprozesse +- M13-Optimizer-Parameterraum enthält **kein** `slippage_model/value/unit`; keine Execution-/Cost-Parameter optimierbar + +## Bekannte Grenzen + +- NONE vs FIXED(0) → unterschiedlicher run_hash (gewollt, kein Fehler) +- Fixture-E2E nur mit `ALLOW_FIXTURE_DATA=true` (test-only); danach garantiert false/unset +- M13-Optimizer nutzt das neue Slippage-Modell **nicht** im Parameterraum (Legacy-`slippage`-Feld bleibt) +- Kein Random-/Volatilitäts-Slippage implementiert (bewusst, Scope-10c)