Skip to main content

hypercall_db/traits/
analytics.rs

1//! Analytics and historical data traits (async, API read path).
2//!
3//! These power the public REST API endpoints for trade history, fills,
4//! orders, PnL, and theo history. All async because the API layer uses
5//! `diesel-async` with a separate connection pool.
6
7use anyhow::Result;
8use hypercall_types::WalletAddress;
9use rust_decimal::Decimal;
10use std::collections::{HashMap, HashSet};
11
12use crate::{
13    BboReferenceData, BboSnapshotRecord, FillRecord, HistoricalPnlPoint, HistoricalTheoPoint,
14    NewBboSnapshotInput, OrderRecord, SettlementPayoutRecord, TradeRecord, VolSurfaceSnapshot,
15};
16
17/// Read-only analytics queries for the API layer.
18#[async_trait::async_trait]
19pub trait AnalyticsReader: Send + Sync {
20    /// Paginated trade history, ordered by timestamp descending.
21    async fn get_all_trades(&self, limit: usize, offset: usize) -> Result<Vec<TradeRecord>>;
22
23    /// Trades for a specific option symbol (e.g. "BTC-20260131-100000-C").
24    async fn get_trades_by_option(&self, option_id: &str, limit: usize)
25        -> Result<Vec<TradeRecord>>;
26
27    /// Trades for all instruments with the given underlying (e.g. "BTC").
28    async fn get_trades_by_underlying(
29        &self,
30        underlying: &str,
31        limit: usize,
32        offset: usize,
33    ) -> Result<Vec<TradeRecord>>;
34
35    /// Trades where the wallet was either maker or taker.
36    async fn get_trades_by_account(
37        &self,
38        account: &WalletAddress,
39        limit: usize,
40        offset: usize,
41    ) -> Result<Vec<TradeRecord>>;
42
43    /// Trades for a symbol within a time range (inclusive, ascending order).
44    async fn get_trades_for_symbol_in_range(
45        &self,
46        symbol: &str,
47        start_time_ms: i64,
48        end_time_ms: i64,
49    ) -> Result<Vec<TradeRecord>>;
50
51    /// Fills for a wallet, ordered by timestamp descending.
52    async fn get_fills_by_account(
53        &self,
54        account: &WalletAddress,
55        limit: usize,
56        offset: usize,
57    ) -> Result<Vec<FillRecord>>;
58
59    /// Orders for a wallet, optionally filtered by status. Descending by timestamp.
60    async fn get_orders_by_account(
61        &self,
62        account: &WalletAddress,
63        status: Option<&str>,
64        limit: usize,
65        offset: usize,
66    ) -> Result<Vec<OrderRecord>>;
67
68    /// Check whether any trades exist for a symbol.
69    async fn trade_history_exists_for_symbol(&self, symbol: &str) -> Result<bool>;
70
71    /// Check whether any historical theo snapshots exist for a symbol.
72    async fn historical_theo_history_exists_for_symbol(&self, symbol: &str) -> Result<bool>;
73
74    /// Historical equity snapshots for a wallet at the given interval.
75    /// Returns points in ascending timestamp order.
76    async fn get_historical_pnl(
77        &self,
78        wallet: &WalletAddress,
79        interval_ms: i64,
80        limit: usize,
81        include_attribution: bool,
82    ) -> Result<Vec<HistoricalPnlPoint>>;
83
84    /// Historical theoretical price snapshots for a symbol at the given interval.
85    async fn get_historical_theos(
86        &self,
87        symbol: &str,
88        interval_ms: i64,
89        limit: usize,
90    ) -> Result<Vec<HistoricalTheoPoint>>;
91
92    /// Batch fetch historical theos for multiple symbols at once.
93    async fn get_historical_theos_batch(
94        &self,
95        symbols: &[String],
96        interval_ms: i64,
97        limit: usize,
98    ) -> Result<HashMap<String, Vec<HistoricalTheoPoint>>>;
99
100    /// Historical vol surface snapshots for an underlying at the given interval.
101    async fn get_vol_surface_history(
102        &self,
103        underlying: &str,
104        interval_ms: i64,
105        limit: usize,
106    ) -> Result<Vec<VolSurfaceSnapshot>>;
107
108    /// BBO snapshots since a cutoff timestamp, ordered by symbol then time.
109    async fn load_bbo_snapshots_since(&self, cutoff_ts: i64) -> Result<Vec<BboSnapshotRecord>>;
110
111    /// Reference best-ask prices for 24h-change calculation. Falls back to
112    /// the earliest available snapshot if no data exists before the cutoff.
113    async fn get_bbo_reference_asks(
114        &self,
115        symbols: &[String],
116        cutoff_ts: i64,
117    ) -> Result<HashMap<String, BboReferenceData>>;
118
119    /// Settlement payouts for a wallet with optional filters. Returns (rows, total_count).
120    async fn get_settlement_payouts(
121        &self,
122        wallet: &WalletAddress,
123        limit: i64,
124        offset: i64,
125        symbol: Option<&str>,
126        ledger_applied: Option<bool>,
127    ) -> Result<(Vec<SettlementPayoutRecord>, i64)>;
128
129    /// Which payout IDs have been marked as "seen" by the user.
130    async fn get_seen_settlement_payout_ids(
131        &self,
132        wallet: &WalletAddress,
133        payout_ids: &[i64],
134    ) -> Result<HashSet<i64>>;
135
136    /// Batch lookup of client_ids by order_ids. Missing orders are omitted.
137    async fn get_client_ids_by_order_ids(
138        &self,
139        order_ids: &[i64],
140    ) -> Result<HashMap<i64, Option<String>>>;
141
142    /// Latest theoretical marks for symbols at or before a timestamp.
143    async fn get_theo_marks_at_timestamp(
144        &self,
145        symbols: &[String],
146        timestamp_ms: i64,
147    ) -> Result<HashMap<String, Decimal>>;
148
149    /// Deposit and withdraw ledger events for a wallet, ascending by time.
150    async fn get_deposit_withdraw_events(
151        &self,
152        wallet: &WalletAddress,
153    ) -> Result<Vec<crate::LedgerEventTimeDelta>>;
154
155    /// Net realized PnL per symbol for a wallet, scoped to events at or before
156    /// the given timestamp. Covers fill_premium, fill_realized_pnl, and
157    /// settlement_realized_pnl event types.
158    async fn get_settled_pnl_by_symbol(
159        &self,
160        wallet: &WalletAddress,
161        before_ts_ms: i64,
162    ) -> Result<Vec<(String, Decimal)>>;
163
164    /// Recent fills since a cutoff timestamp, ascending by time.
165    /// Used for cache backfill (market stats).
166    async fn get_fills_since_timestamp(
167        &self,
168        cutoff_timestamp: i64,
169    ) -> Result<Vec<crate::FillBackfillRecord>>;
170}
171
172/// Write operations for analytics tables (snapshots, BBO, etc.).
173#[async_trait::async_trait]
174pub trait AnalyticsWriter: AnalyticsReader {
175    /// Upsert PnL snapshots for a batch of wallets, pruning beyond `max_periods`.
176    async fn upsert_historical_pnl_batch(
177        &self,
178        interval_ms: i64,
179        timestamp_ms: i64,
180        snapshots: &[(WalletAddress, Decimal, Option<Vec<u8>>)],
181        max_periods: i64,
182    ) -> Result<usize>;
183
184    /// Upsert theo price snapshots for a batch of symbols, pruning beyond `max_periods`.
185    async fn upsert_historical_theo_batch(
186        &self,
187        interval_ms: i64,
188        timestamp_ms: i64,
189        snapshots: &[(String, Decimal)],
190        max_periods: i64,
191    ) -> Result<usize>;
192
193    /// Upsert a vol surface JSON snapshot, pruning beyond `max_periods`.
194    async fn upsert_vol_surface_snapshot(
195        &self,
196        interval_ms: i64,
197        timestamp_ms: i64,
198        underlying: &str,
199        surface_json: serde_json::Value,
200        max_periods: i64,
201    ) -> Result<usize>;
202
203    /// Upsert BBO snapshots for multiple symbols at a given timestamp.
204    async fn upsert_bbo_snapshots(
205        &self,
206        snapshot_ts: i64,
207        snapshots: &[NewBboSnapshotInput],
208    ) -> Result<usize>;
209
210    /// Delete BBO snapshots older than `cutoff_ts`. Returns count deleted.
211    async fn delete_bbo_snapshots_older_than(&self, cutoff_ts: i64) -> Result<usize>;
212
213    /// Mark settlement payout IDs as "seen" for a wallet (idempotent).
214    async fn mark_settlement_payouts_seen(
215        &self,
216        wallet: &WalletAddress,
217        payout_ids: &[i64],
218    ) -> Result<usize>;
219}