5.3 KiB
SOL-PERP Observer V1
Ten dokument definiuje pierwszy działający observer bota dla
SOL-PERP.
Celem nie jest jeszcze trading, tylko:
- stabilny loop
1s - powtarzalny snapshot feature'ów
- decyzja
long|flat|short - heartbeat i audyt w
bot_state/bot_events
Zakres
- rynek:
SOL-PERP - tryb:
observe - źródło danych v1:
Hasura - bez kluczy prywatnych
- bez składania transakcji
Architektura
bot_configpozostaje desired state i źródłem parametrówbot-observerczytabot_config, pobiera snapshot rynku, liczy feature'y i zapisuje wynikbot_stateprzechowuje heartbeat, ostatni błąd i ostatni wynik loopabot_eventsprzechowuje append-only audyt decyzji i błędów
Źródła danych
Observer czyta z Hasury:
get_drift_candles(...)dlob_hot_derived_latestdla hot marketów z fallbackiem dodlob_all_derived_latest
Depth bands i slippage nie są już czytane z osobnych legacy tabel.
Observer liczy je lokalnie z bids_norm /
asks_norm nowego derived read-model.
Wersja v1 zakłada małe query tylko dla jednego rynku.
Parametry w
bot_config.params
Minimalny kontrakt:
{
"strategy": {
"type": "predictive_observer_v1"
},
"loop": {
"decision_interval_ms": 1000,
"candle_bucket_seconds": 1,
"candles_limit": 64
},
"features": {
"mom_fast_s": 3,
"mom_mid_s": 10,
"mom_slow_s": 30,
"vol_window_s": 30,
"depth_band_bps": 10,
"slippage_size_usd": 500
},
"gates": {
"freshness_max_ms": 800,
"spread_max_bps": 8,
"slippage_max_bps": 12,
"depth_band_min_usd": 3000
},
"sizing": {
"target_notional_usd": 500
},
"decision": {
"threshold": 1.2,
"horizon_s": 60
},
"scoring": {
"weights": {
"mom_fast": 0.9,
"mom_mid": 0.35,
"mom_slow_reversal": 0.55,
"imbalance": 5.0,
"mark_vs_oracle": 0.08,
"spread": 0.15,
"slippage": 0.12
}
}
}Feature Snapshot
Na każdy tick observer liczy:
mark_priceoracle_pricemid_pricespread_bpsstats_imbalancedepth_bid_usddepth_ask_usddepth_imbalancebuy_slippage_bpssell_slippage_bpsmark_vs_oracle_bpsmom_3smom_10smom_30svol_30sdata_age_ms
Gates
Jeśli którykolwiek gate nie przechodzi, observer nie produkuje
sygnału kierunkowego i zapisuje event skip.
Wersja v1:
data_age_ms <= freshness_max_msspread_bps <= spread_max_bpsmax(buy_slippage_bps, sell_slippage_bps) <= slippage_max_bpsmin(depth_bid_usd, depth_ask_usd) >= depth_band_min_usd
Model decyzji
V1 nie używa ML. To baseline scoring do zebrania danych i benchmarku.
Long side:
long_score =
mom_fast * w_mom_fast
+ mom_mid * w_mom_mid
- mom_slow * w_mom_slow_reversal
+ depth_imbalance * w_imbalance
- mark_vs_oracle_bps * w_mark_vs_oracle
- spread_bps * w_spread
- buy_slippage_bps * w_slippage
Short side jest lustrzanym odbiciem long side.
Decyzja:
- jeśli gates fail ->
flat - jeśli
max(abs(long_score), abs(short_score)) < threshold->flat - w przeciwnym razie
longalboshort
Event decision
{
"version": "observer-sol-v1",
"bot": {
"id": "uuid",
"name": "sol-observer",
"mode": "observe",
"market_name": "SOL-PERP",
"kill_switch": false
},
"runtime": {
"service": "bot-observer",
"observe_only": true,
"loop_ms": 1000,
"query_latency_ms": 82,
"loop_latency_ms": 96
},
"snapshot": {
"data_age_ms": 214,
"stats_updated_at": "2026-03-23T20:12:31.112Z",
"depth_updated_at": "2026-03-23T20:12:31.112Z",
"buy_slippage_updated_at": "2026-03-23T20:12:31.112Z",
"sell_slippage_updated_at": "2026-03-23T20:12:31.112Z"
},
"features": {
"mom_3s": 3.8,
"mom_10s": 6.1,
"mom_30s": -12.5,
"vol_30s": 5.9,
"spread_bps": 2.1,
"depth_imbalance": 0.18,
"buy_slippage_bps": 4.2,
"sell_slippage_bps": 4.0,
"mark_vs_oracle_bps": -1.3
},
"gates": {
"fresh": true,
"spread_ok": true,
"slippage_ok": true,
"depth_ok": true
},
"decision": {
"side": "long",
"confidence": 0.72,
"long_score": 1.91,
"short_score": -2.34,
"target_notional_usd": 500,
"horizon_s": 60
}
}Event skip
Observer zapisuje skip, gdy:
- dane są stale
- brakuje wymaganych metryk
- gates nie przechodzą
- bot jest w trybie innym niż aktywny observe loop
Payload skip ma ten sam nagłówek co
decision, ale z polem:
{
"skip_reason": "gate_failed:freshness"
}bot_state.state
V1 zapisuje w bot_state.state znormalizowany stan
loopa:
serviceversionobserve_onlymarket_namemodestatuslast_decisionlast_featureslast_gateslast_snapshotcounters
Zmienne środowiskowe
Najważniejsze:
BOT_IDalboBOT_NAMEHASURA_GRAPHQL_URLHASURA_ADMIN_SECRETDLOB_SOURCEopcjonalnie, jeśli chcesz zawęzić derived read-model do konkretnegosourceCANDLES_SOURCEopcjonalnie, jeśli chcesz zawęzić candles do konkretnego źródła tickówOBSERVER_PORTopcjonalnie, domyślnie8791
Cel wersji v1
V1 ma odpowiedzieć na trzy pytania:
- czy Hasura daje stabilny loop
1sdla jednego rynku - czy feature snapshot jest wystarczająco świeży
- czy baseline scoring daje sensowny materiał do dalszego strojenia i późniejszego ML