# DRAFT · OPEN-POSITIONS-VIEW (Filament-Page) Status: planned (P2) Erstellt: Nightly 2026-05-18 Scope: GUI-Entwurf — read-only, kein Code in `gui/app/Filament/Pages/` ohne Operator-GO. --- ## 1. Motivation `/admin/positions` (basiert auf `PositionSnapshotResource`) zeigt **snapshot rows**, nicht „aktuelle Bot-Positionen". Operator-Frage „welche Positionen hält der Bot gerade?" lässt sich daraus nur per SQL-Window-Funktion beantworten (`DISTINCT ON (position_id) ORDER BY created_at DESC`). Außerdem fehlt der Initial-Entry / Avg-Entry / DCA-Count-Aggregat-Blick: - Initial Entry vs Avg Entry (siehe ALERTS.md P1-C) - DCA-Tranchen-Count + Pyramid-Count - USDT-Wert offen + unrealisiertes PnL - Stuck-Position-Marker (für STATE-EXCHANGE-RECONCILE-LOOP) --- ## 2. Ziel-Page Neue Filament-Page (nicht Resource), Route `/admin/positions/live`. Datenquelle (read-only, kein Bot-Touch): - primary: `live_portfolio.json` (über existing Service, Pattern wie `gui/app/Services/Roadmap/`) - sekundär für historische Felder: `dca_log.json` (siehe DCA-TRANCHES-GUI) - tertiär: position_snapshots-Tabelle für `decision_id` / `opened_at` (sobald SNAPSHOT-EMIT-COMPLETENESS done) --- ## 3. Datenmodell der View Pro offener Position: | Feld | Quelle | Notiz | |---|---|---| | Symbol | live_portfolio.positions[X] (key) | | | Strategy Group | live_portfolio.positions[X].strategy_group | mit StrategyGroupLabels | | Initial Entry | (fehlt aktuell) → bot_stdout.log oder neuer `initial_entry_price` Slot | „n/a" bis Backend gepatcht | | Avg Entry | live_portfolio.positions[X].entry_price (= avg nach DCA) | semantisch klar labelen | | Quantity | live_portfolio.positions[X].quantity | | | Cost (USDT) | live_portfolio.positions[X].cost | | | Stop-Loss (current) | live_portfolio.positions[X].stop_loss | | | Take-Profit (current) | live_portfolio.positions[X].take_profit | | | DCA Count | dca_log.positions[X].dca_count | | | Pyramid Count | dca_log.positions[X].pyramid_count | | | Total Invested | dca_log.positions[X].total_invested | | | Mode-Label | ModeLabels::for(\$pos) | „TESTNET LIVE" / „MAINNET" / „PAPER" | | Position-Age | now() - opened_at | | | Stuck-Marker | derived: ist Position in state ABER `_track_sell_failure`-Counter > N | nach STATE-EXCHANGE-RECONCILE-LOOP | | Quick-Actions | Manual-Close (CommandBus) | bereits gewired via ViewPosition.php | --- ## 4. Mockup (textuell, kein Figma) ``` +----------------------------------------------------------------+ | Aktuelle Bot-Positionen [↻ Reload]| | | | Mode-Banner: EXCHANGE_TESTNET (BINANCE_TESTNET=true) | | Stand: 2026-05-18 02:44 CEST · Quelle: live_portfolio.json | | | | +--------------------------------------------------------+ | | | ● TON/USDT T1 · OPPORTUNISTIC | | | | Avg Entry: 1.9080 Qty: 110.64 | | | | Initial : 1.9080 (= Avg, kein DCA) | | | | Cost : 211.10 USDT · Open PnL: +0.42 USDT (+0.2%)| | | | SL: 1.857 · TP: 2.010 · Age: 3h 0m | | | | DCA: 0 · Pyramid: 0 · Invested: 211.10 USDT | | | | [Manual Close] [View Detail] [Tranches…] | | | +--------------------------------------------------------+ | | | | 1 Position offen · Total exposed: 211.10 USDT · Cash: 10351| +----------------------------------------------------------------+ ``` Für Stuck-Cases: ``` | ⚠️ SHIB/USDT T1 · STUCK_NO_EXCHANGE_BALANCE | | Avg Entry: 0.000006 Qty: 68 066 671 | | Last SELL fail: 2026-05-17 23:51 (insufficient_funds)| | [Operator Decision: Cleanup | Re-Buy Replicate] | ``` (nur sichtbar nach STATE-EXCHANGE-RECONCILE-LOOP) --- ## 5. Boundaries - **0× Bot-Touch** — Page liest JSON-Datei via Service-Layer. - **0× DB-Migration** — falls position_snapshots eingebunden wird, nur SELECT. - **0× neue CommandBus-Commands** — Manual-Close existiert bereits. - **0× hardcoded mode-Strings** — `ModeLabels` benutzen. --- ## 6. Folge-Abhängigkeiten | Vor-Aufgabe | Status | |---|---| | SNAPSHOT-EMIT-COMPLETENESS | planned (P2) | | INITIAL-ENTRY-PERSIST | planned (P2) — neuer Backlog-Vorschlag | | STATE-EXCHANGE-RECONCILE-LOOP | planned | Page kann **ohne** die Vor-Aufgaben gebaut werden, dann fallen betroffene Felder auf Placeholder „—" zurück (Pattern wie GUI-VIEW-POSITION-POLISH-1). --- ## 7. Test-Skizze - `RoadmapPageTest`-analoge Feature-Tests: - Service liest live_portfolio.json korrekt (Fixture-File) - Service kombiniert dca_log korrekt - Page-Render zeigt 1 Position für Fixture - Page zeigt „— (kein DCA)" für TON-ähnliche Fixture - Integration nicht nötig — Service-Layer entkoppelt von DB. --- ## 8. STOP Kein GUI-Code vor Operator-GO. Diese Datei ist ein Entwurf, kein Patch.