6.9 KiB
DLOB + L1…L10 — podstawy (co jest czym i gdzie to liczymy)
Ten dokument wyjaśnia pojęcia:
- DLOB (Drift Limit Order Book),
- L1 / L2 / L3 oraz potoczne L1…L10,
- na jakich warstwach w naszym stacku powstają dane i metryki,
- gdzie “pracuje AI” (modele/strategie) vs gdzie jest execution (order placement).
Co to jest DLOB
DLOB = Decentralized Limit Order Book w Drift.
W praktyce: to jest księga zleceń dla rynku (np.
SOL-PERP):
- bids = zlecenia kupna (po stronie bid),
- asks = zlecenia sprzedaży (po stronie ask).
Księga ma wiele “poziomów” cenowych; przy każdej cenie stoi pewna ilość (size).
L1 / L2 / L3 (format i sens)
L1 (Top of Book)
L1 to skrót od “top of book”:
- best bid = najwyższa cena kupna (pierwszy poziom po stronie bid),
- best ask = najniższa cena sprzedaży (pierwszy poziom po stronie ask).
Z L1 najczęściej liczysz:
- spread =
best_ask - best_bid, - mid =
(best_bid + best_ask) / 2.
L2 (zagregowane poziomy)
L2 to lista poziomów (levels) po obu stronach:
bids: [{ price, size }, ...](zwykle posortowane malejąco poprice)asks: [{ price, size }, ...](zwykle posortowane rosnąco poprice)
To jest najpopularniejszy “orderbook UI”: słupki/heat per poziom ceny.
L3 (pojedyncze zlecenia)
L3 to “niezagregowane” dane: pojedyncze zlecenia (większy wolumen danych). U nas pod UI i metryki zazwyczaj wystarcza L2.
L1…L10 (co to znaczy w praktyce)
L1…L10 to potoczne określenie:
“pierwsze 10 poziomów z L2 najbliżej top of book”.
To nie jest osobny format; to po prostu wycinek L2.
W naszym stacku “ile leveli bierzemy” kontroluje:
DLOB_DEPTH(np. 10 → “L1…L10”).
Jak to działa w naszym stacku (warstwy)
Poniżej aktualny łańcuch od źródła do metryk w live runtime:
Warstwa A: On-chain → DLOB w pamięci (VPS/k3s)
Komponenty: dlob-publisher-hot i
dlob-publisher-all.
- Łączą się do Solany przez prywatny RPC/WS/gRPC.
- Budują DLOB w pamięci.
- Publikują snapshoty do Redis:
dlob-hot:*dlob-all:*
To jest najbliżej źródła i najbardziej “real-time”.
Warstwa B: Redis → PostgreSQL (VPS/k3s)
Komponenty:
dlob-hot-redis-to-postgres-raw-writerdlob-hot-postgres-to-postgres-derived-writerdlob-all-redis-to-postgres-derived-writer
Ten etap:
- utrwala raw
hotw PostgreSQL, - buduje derived layer
hotiall, - zapisuje znormalizowane poziomy orderbooka oraz metryki top-of-book
do tabel
dlob_*_derived_*.
Warstwa C: Hasura + aplikacja
Hasurawystawia derived tables jako GraphQL + subscriptions.- UI i narzędzia aplikacyjne czytają z
dlob_hot_derived_latestorazdlob_all_derived_latest. - Metryki depth/slippage nie są już liczone przez osobne workery k3s; bieżąca ścieżka aplikacji wylicza je z danych L2/derived.
Gdzie “pracuje AI” (TFT itp.)
AI/strategia powinna pracować na warstwie “features”, a nie na surowych subskrypcjach Solany:
Najczęstszy zestaw wejść dla modelu:
- candles/ticki (np.
drift_ticks+get_drift_candles(...)), - bieżące statsy z DLOB:
dlob_stats_latest(mid/spread/depth/imbalance),dlob_depth_bps_latest(depth w bandach),dlob_slippage_latest(slippage vs size),
- opcjonalnie pełny snapshot L2 (z
dlob_l2_latest), jeśli model potrzebuje “kształtu” książki.
Kluczowa zasada bezpieczeństwa:
- Model (np. na Vast) może sugerować “desired state” (wejść/wyjść/parametry),
- Executor na VPS zawsze odpowiada za:
- risk checks,
- składanie/cancel/close,
- klucze prywatne i podpisywanie transakcji,
- kill switch.
Szybki słownik (1-liner)
- bid: kupno, zielona strona książki
- ask: sprzedaż, czerwona strona książki
- best bid / best ask (L1): top-of-book
- spread: koszt “wejścia/wyjścia natychmiast” (ask-bid)
- mid: punkt odniesienia między bid/ask
- L2: lista poziomów
{price,size} - L1…L10: top 10 poziomów z L2 (u nas kontrolowane
przez
DLOB_DEPTH)
Jak liczymy “liquidity” i “kasa” (USD) w metrykach
W UI/DB słowo “liquidity” zwykle oznacza depth: “ile wolumenu stoi w orderbooku blisko ceny”. U nas trzymamy to rozdzielnie dla bid/ask oraz w dwóch wariantach:
A) Top‑N leveli
(np. L1…L10) — dlob_*_derived_latest
Zapisywane w writerach warstwy pochodnej na podstawie live snapshotów orderbooka:
- Bierzemy znormalizowane top level’e z
bids_normiasks_norm. - Każdy level ma:
pricesize_base- “kasa” (notional) na tym levelu:
size_usd = size_base * price
- Sumujemy po levelach:
depth_bid_base = Σ size_base(po stronie bid),depth_bid_usd = Σ (size_base * price)(po stronie bid),- analogicznie
depth_ask_base,depth_ask_usd(po stronie ask).
To odpowiada intuicji “ile jest płynności na L1…LN”.
B) Okno cenowe w bps od mid
W aktualnej ścieżce aplikacji to liczenie jest robione z danych L2/derived, a nie przez osobny backend worker:
- Dla pasma
band_bpswyznaczamy:minBidPrice = mid * (1 - band_bps/10_000)maxAskPrice = mid * (1 + band_bps/10_000)
- Sumujemy wszystkie levele, które mieszczą się w tym oknie:
- bids:
price >= minBidPrice - asks:
price <= maxAskPrice
- bids:
- Liczymy sumy:
bid_base,bid_usd,ask_base,ask_usdtak jak wyżej (usd = base * price).
To odpowiada intuicji “ile płynności jest blisko ceny w ±X bps”.
Ważne doprecyzowanie
Te liczby to notional z orderbooka (ile “stoi” na poziomach cenowych). Nie są to “pieniądze w kontrakcie”, tylko przybliżenie kosztu/pojemności wykonania przy danej cenie i bez przesunięcia rynku.
Spec: Orderbook UI (L1…L10 + “liquidity bars”)
Wizualizacja orderbooka (jak na screenach) jest oparta o L2 i pokazuje tylko top‑N leveli:
N= liczba leveli wyświetlanych na stronę (np. 10 → “L1…L10”).
Kolumny / wartości
Na każdym levelu liczymy:
size_usd = size_base * price
W UI pokazujemy:
Size (USD)=size_usddla danego poziomu,Total (USD)= suma skumulowana od best‑price “w głąb” (cumulative):- bids: kumulacja od best bid w dół,
- asks: kumulacja od best ask w górę (w UI zwykle best ask jest bliżej środka).
“Liquidity bars” (znormalizowane słupki tła)
Żeby “na oko” widzieć gdzie stoi płynność:
- Level bar (per‑poziom) — normalizacja do
największego
size_usdw widocznych levelach danej strony:level_scale = size_usd / max(size_usd w widoku)
- Total bar (cumulative) — normalizacja do
największego
total_usdw widocznych levelach danej strony:total_scale = total_usd / max(total_usd w widoku)
Żeby duże “ściany” nie zabijały kontrastu, warto użyć krzywej:
scale_curved = sqrt(clamp01(scale))
Interpretacja:
- level bar = “ile stoi na tym poziomie”,
- total bar = “ile stoi łącznie do tego poziomu”.