# Serwisy DLOB na VPS (k3s / `trade-staging`) Ten dokument opisuje rolę serwisów “DLOB” uruchomionych w namespace `trade-staging` oraz ich przepływ danych. ## Czy `dlob-worker` pracuje na VPS? Tak — wszystkie serwisy wymienione niżej działają **na VPS** jako Deploymenty w klastrze k3s, w namespace `trade-staging`. ## Czy na VPS jest GraphQL/WS dla stats i orderbook? Tak — **GraphQL wystawia Hasura** (na VPS w k3s), a nie `dlob-server`. - Dane L2 i liczone statsy są zapisane do Postgresa jako tabele `dlob_*_latest` i są dostępne przez Hasurę jako GraphQL (query + subscriptions). - Z zewnątrz korzystamy przez frontend (proxy) pod: - HTTP: `https://trade.rv32i.pl/graphql` - WS: `wss://trade.rv32i.pl/graphql` (subskrypcje, protokół `graphql-ws`) `dlob-server` wystawia **REST** (np. `/l2`, `/l3`) w klastrze; to jest źródło danych dla workerów albo do debugowania. ## TL;DR: kto co robi ### `dlob-worker` - **Rola:** kolektor L2 + wyliczenie “basic stats”. - **Wejście:** HTTP L2 z `DLOB_HTTP_URL` (u nas obecnie `https://dlob.drift.trade`, ale można przełączyć na `http://dlob-server:6969`). - **Wyjście:** upsert do Hasury (Postgres) tabel: - `dlob_l2_latest` (raw snapshot L2, JSON leveli) - `dlob_stats_latest` (pochodne: best bid/ask, mid, spread, depth, imbalance, itp.) - **Częstotliwość:** `DLOB_POLL_MS` (u nas 500 ms). ### `dlob-slippage-worker` - **Rola:** symulacja slippage vs rozmiar zlecenia na podstawie L2. - **Wejście:** czyta z Hasury `dlob_l2_latest` (dla listy rynków). - **Wyjście:** upsert do Hasury tabeli `dlob_slippage_latest` (m.in. `impact_bps`, `vwap_price`, `worst_price`, `fill_pct`). - **Częstotliwość:** `DLOB_POLL_MS` (u nas 1000 ms); rozmiary w `DLOB_SLIPPAGE_SIZES_USD`. ### `dlob-depth-worker` - **Rola:** metryki “głębokości” w pasmach ±bps wokół mid. - **Wejście:** czyta z Hasury `dlob_l2_latest`. - **Wyjście:** upsert do Hasury tabeli `dlob_depth_bps_latest` (per `(market_name, band_bps)`). - **Częstotliwość:** `DLOB_POLL_MS` (u nas 1000 ms); pasma w `DLOB_DEPTH_BPS_BANDS`. ### `dlob-publisher` - **Rola:** utrzymuje “żywy” DLOB na podstawie subskrypcji on-chain i publikuje snapshoty do Redis. - **Wejście:** Solana RPC/WS (`ENDPOINT`, `WS_ENDPOINT` z secreta `trade-dlob-rpc`), Drift SDK; konfiguracja rynków np. `PERP_MARKETS_TO_LOAD`. - **Wyjście:** zapis/publish do `dlob-redis` (cache / pubsub / streamy), z którego korzysta serwer HTTP (i ewentualnie WS manager). ### `dlob-server` - **Rola:** HTTP API do danych DLOB (np. `/l2`, `/l3`) serwowane z cache Redis. - **Wejście:** `dlob-redis` + slot subscriber (do oceny “świeżości” danych). - **Wyjście:** endpoint HTTP w klastrze (Service `dlob-server:6969`), który może być źródłem dla `dlob-worker` (gdy `DLOB_HTTP_URL=http://dlob-server:6969`). ### `dlob-redis` - **Rola:** Redis (u nas single-node “cluster mode”) jako **cache i kanał komunikacji** między `dlob-publisher` a `dlob-server`. - **Uwagi:** to “klej” między komponentami publish/serve; bez niego publisher i server nie współpracują. ## Jak to się spina (przepływ danych) 1) `dlob-publisher` (on-chain) → publikuje snapshoty do `dlob-redis`. 2) `dlob-server` → serwuje `/l2` i `/l3` z `dlob-redis` (HTTP w klastrze). 3) `dlob-worker` → pobiera L2 (obecnie z `https://dlob.drift.trade`; opcjonalnie z `dlob-server`) i zapisuje “latest” do Hasury/DB. 4) `dlob-slippage-worker` + `dlob-depth-worker` → liczą agregaty z `dlob_l2_latest` i zapisują do Hasury/DB (pod UI). ## Co to jest L1 / L2 / L3 (orderbook) - `L1` (top-of-book): tylko najlepszy bid i najlepszy ask (czasem też spread). - `L2` (Level 2): **zagregowane poziomy cenowe** po stronie bid/ask — lista leveli `{ price, size }`, gdzie `size` to suma wolumenu na danej cenie (to jest typowy “orderbook UI” i baza pod spread/depth/imbalance). - `L3` (Level 3): **niezagregowane, pojedyncze zlecenia** (każde osobno, zwykle z dodatkowymi polami/identyfikatorami). Większy wolumen danych; przydatne do “pro” analiz i debugowania mikrostruktury. W tym stacku: - `dlob-server` udostępnia REST endpointy `/l2` i `/l3`. - Hasura/DB trzyma “latest” snapshot L2 w `dlob_l2_latest` oraz metryki w `dlob_stats_latest` / `dlob_depth_bps_latest` / `dlob_slippage_latest`. ## Słownik pojęć (bid/ask/spread i metryki) ### Podstawy orderbooka - **Bid**: zlecenia kupna (chęć kupna). W orderbooku “bid side”. - **Ask**: zlecenia sprzedaży (chęć sprzedaży). W orderbooku “ask side”. - **Best bid / best ask**: najlepsza (najwyższa) cena kupna i najlepsza (najniższa) cena sprzedaży na topie księgi (L1). - **Spread**: różnica pomiędzy `best_ask` a `best_bid`. Im mniejszy spread, tym “taniej” wejść/wyjść (mniej kosztów natychmiastowej realizacji). - **Mid price**: cena “po środku”: `(best_bid + best_ask) / 2`. Używana jako punkt odniesienia do bps i slippage. - **Level**: pojedynczy poziom cenowy w L2 (np. `price=100.00`, `size=12.3`). - **Size**: ilość/płynność na poziomie (zwykle w jednostkach “base asset”). - **Base / Quote**: - `base` = instrument bazowy (np. SOL), - `quote` = waluta wyceny (często USD). ## Kolory w UI (visualizer) - `bid` / “buy side” = zielony (`.pos`, `#22c55e`) - `ask` / “sell side” = czerwony (`.neg`, `#ef4444`) - “flat” / brak zmiany = niebieski (`#60a5fa`) — używany m.in. w “brick stack” pod świecami ### Jednostki i skróty - **bps (basis points)**: 1 bps = 0.01% = `0.0001`. Np. 25 bps = 0.25%. - **USD**: u nas wiele wartości jest przeliczanych do USD (np. `size_base * price`). ### Metryki “stats” (np. `dlob_stats_latest`) - `spread_abs` (USD): `best_ask - best_bid`. - `spread_bps` (bps): `(spread_abs / mid_price) * 10_000`. - `depth_levels`: ile leveli (top‑N) z każdej strony braliśmy do liczenia “depth”. - `depth_bid_base` / `depth_ask_base`: suma `size` po top‑N levelach bid/ask (w base). - `depth_bid_usd` / `depth_ask_usd`: suma `size_base * price` po top‑N levelach (w USD). - `imbalance` ([-1..1]): miara asymetrii płynności: - `(depth_bid_usd - depth_ask_usd) / (depth_bid_usd + depth_ask_usd)` - >0 = relatywnie więcej płynności po bid, <0 = po ask. - `oracle_price`: cena z oracla (np. Pyth) jako punkt odniesienia. - `mark_price`: “mark” z rynku/perp (cena referencyjna dla rozliczeń); różni się od oracle/top-of-book. ### Metryki “depth bands” (np. `dlob_depth_bps_latest`) - `band_bps`: szerokość pasma wokół `mid_price` (np. 5/10/20/50/100/200 bps). - `bid_usd` / `ask_usd`: płynność po danej stronie, ale **tylko z poziomów mieszczących się w oknie ±`band_bps`** wokół mid. - `imbalance`: jak wyżej, ale liczony per band. ### Metryki “slippage” (np. `dlob_slippage_latest`) To jest symulacja “gdybym teraz zrobił market order o rozmiarze X” na podstawie L2. - `size_usd`: docelowy rozmiar zlecenia w USD. - `vwap_price`: średnia cena realizacji (Volume Weighted Average Price) dla symulowanego fill. - `impact_bps`: koszt/odchylenie względem `mid_price` wyrażone w bps (zwykle na bazie `vwap` vs `mid`). - `worst_price`: najgorsza cena dotknięta podczas “zjadania” kolejnych leveli. - `filled_usd` / `filled_base`: ile realnie udało się wypełnić (może być < docelowego, jeśli brakuje płynności). - `fill_pct`: procent wypełnienia (100% = pełny fill). - `levels_consumed`: ile leveli zostało “zjedzonych” podczas fill. ### Metadane czasu (“świeżość”) - `ts`: timestamp źródła (czas snapshotu). - `slot`: slot Solany, z którego pochodzi snapshot (monotoniczny “numer czasu” chaina). - `updated_at`: kiedy nasz worker zapisał/odświeżył rekord w DB (do oceny, czy dane są świeże). ## Szybka diagnostyka na VPS ```bash KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n trade-staging get deploy | grep -E 'dlob-(worker|slippage-worker|depth-worker|publisher|server|redis)' KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n trade-staging logs deploy/dlob-worker --tail=80 KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n trade-staging logs deploy/dlob-publisher --tail=80 KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n trade-staging logs deploy/dlob-server --tail=80 ``` ## Ważna uwaga (źródło L2 w `dlob-worker`) Jeśli chcesz, żeby `dlob-worker` polegał na **naszym** stacku (własny RPC + `dlob-publisher` + `dlob-server`), ustaw: - `DLOB_HTTP_URL=http://dlob-server:6969` Aktualnie w `trade-staging` jest ustawione: - `DLOB_HTTP_URL=https://dlob.drift.trade`