# Observer Visualizer V1 Ten dokument opisuje pierwszy panel UI dla `bot-observer` w visualizerze. ## Cel Pokazać operatorowi stan observera bez liczenia logiki bota po stronie frontendu. UI ma: - czytać gotowy stan z control plane - pokazywać bieżącą decyzję, gates i feature snapshot - pokazywać heartbeat, błędy i feed eventów ## Źródła danych Panel czyta przez istniejący `trade-api`: - `GET /api/v1/bots?limit=100` - `GET /api/v1/bots/:id/state` - `GET /api/v1/bots/:id/events?limit=100` Frontend nie odpytuje Hasury bezpośrednio dla panelu observera. ## Zasada wyboru aktywnego bota Panel rozwiązuje bota w kolejności: 1. `VITE_BOT_ID` jeśli ustawione 2. `VITE_BOT_NAME` jeśli ustawione 3. pierwszy bot, którego `market_name === aktualny symbol na wykresie` Jeśli żaden bot nie pasuje, panel pokazuje stan `No bot configured`. ## Schema danych w UI ### `bot_config` UI używa: - `id` - `name` - `market_name` - `market_type` - `mode` - `kill_switch` - `updated_at` ### `bot_state` UI używa: - `last_heartbeat_at` - `last_action_at` - `last_error` - `updated_at` - `state` ### `bot_state.state` Observer zapisuje już gotowy summary payload. UI czyta tylko: ```json { "service": "bot-observer", "version": "observer-sol-v1", "observe_only": true, "market_name": "SOL-PERP", "market_type": "perp", "mode": "observe", "kill_switch": false, "status": "observe", "strategy_type": "predictive_observer_v1", "loop_ms": 1000, "last_snapshot": { "query_latency_ms": 82, "data_age_ms": 214, "candles_count": 64, "stats_age_ms": 180, "depth_age_ms": 210, "buy_slippage_age_ms": 205, "sell_slippage_age_ms": 208 }, "last_features": { "mark_price": 182.12, "oracle_price": 182.08, "mid_price": 182.11, "spread_bps": 2.1, "stats_imbalance": 0.08, "depth_bid_usd": 12400, "depth_ask_usd": 9700, "depth_imbalance": 0.12, "buy_slippage_bps": 4.2, "sell_slippage_bps": 4.0, "mark_vs_oracle_bps": 0.22, "mom_3s": 3.8, "mom_10s": 6.1, "mom_30s": -12.5, "vol_30s": 5.9 }, "last_gates": { "fresh": true, "spread_ok": true, "slippage_ok": true, "depth_ok": true, "has_candles": true, "all": true }, "last_decision": { "side": "long", "confidence": 0.72, "long_score": 1.91, "short_score": -2.34, "target_notional_usd": 500, "horizon_s": 60, "skip_reason": null }, "counters": { "loops": 1012, "decisions": 620, "skips": 382, "errors": 1 } } ``` ## Sekcje panelu ### 1. Status - `mode` - `kill_switch` - `status` - `observe_only` - `heartbeat age` - `last_error` ### 2. Current Decision - `side` - `confidence` - `target_notional_usd` - `horizon_s` - `long_score` - `short_score` - `skip_reason` ### 3. Gates - `fresh` - `spread_ok` - `slippage_ok` - `depth_ok` - `has_candles` ### 4. Feature Snapshot - `spread_bps` - `mark_vs_oracle_bps` - `mom_3s` - `mom_10s` - `mom_30s` - `vol_30s` - `depth_bid_usd` - `depth_ask_usd` - `depth_imbalance` - `buy_slippage_bps` - `sell_slippage_bps` - `data_age_ms` - `query_latency_ms` ### 5. Event Feed Pokazujemy ostatnie eventy: - `decision` - `skip` - `status` - `error` UI nie renderuje pełnego JSON, tylko krótkie summary + timestamp. ## Zakres V1 V1 to tylko wizualizacja aktualnego stanu observera. Poza zakresem: - edycja `bot_config` - ręczne sterowanie `mode` - wykres historyczny decyzji na świecach - live subscriptions V2 może dodać: - markery decyzji na wykresie - odtwarzanie `decision history` - mutacje control-plane z UI