8.4 KiB
8.4 KiB
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_*_latesti 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)
- HTTP:
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 obecniehttps://dlob.drift.trade, ale można przełączyć nahttp://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 wDLOB_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 wDLOB_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_ENDPOINTz secretatrade-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 dladlob-worker(gdyDLOB_HTTP_URL=http://dlob-server:6969).
dlob-redis
- Rola: Redis (u nas single-node “cluster mode”) jako cache i kanał komunikacji między
dlob-publisheradlob-server. - Uwagi: to “klej” między komponentami publish/serve; bez niego publisher i server nie współpracują.
Jak to się spina (przepływ danych)
dlob-publisher(on-chain) → publikuje snapshoty dodlob-redis.dlob-server→ serwuje/l2i/l3zdlob-redis(HTTP w klastrze).dlob-worker→ pobiera L2 (obecnie zhttps://dlob.drift.trade; opcjonalnie zdlob-server) i zapisuje “latest” do Hasury/DB.dlob-slippage-worker+dlob-depth-worker→ liczą agregaty zdlob_l2_latesti 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 }, gdziesizeto 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-serverudostępnia REST endpointy/l2i/l3.- Hasura/DB trzyma “latest” snapshot L2 w
dlob_l2_latestoraz metryki wdlob_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_askabest_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: sumasizepo top‑N levelach bid/ask (w base).depth_bid_usd/depth_ask_usd: sumasize_base * pricepo 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_bpswokół 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ędemmid_pricewyrażone w bps (zwykle na bazievwapvsmid).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
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