digdigdig3_station/data/
ticker.rs1use digdigdig3::core::types::{StreamEvent, Ticker};
2use serde::{Deserialize, Serialize};
3
4use crate::series::DataPoint;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct TickerPoint {
14 pub ts_ms: i64,
15 pub last: f64,
16 pub bid: f64,
17 pub ask: f64,
18 pub high_24h: f64,
19 pub low_24h: f64,
20 pub vol_24h: f64,
21 pub quote_vol_24h: f64,
22 pub change_pct_24h: f64,
23}
24
25const SIZE: usize = 72;
26
27impl TickerPoint {
28 pub fn from_ticker(t: &Ticker) -> Self {
29 Self {
30 ts_ms: t.timestamp,
31 last: t.last_price,
32 bid: t.bid_price.unwrap_or(f64::NAN),
33 ask: t.ask_price.unwrap_or(f64::NAN),
34 high_24h: t.high_24h.unwrap_or(f64::NAN),
35 low_24h: t.low_24h.unwrap_or(f64::NAN),
36 vol_24h: t.volume_24h.unwrap_or(f64::NAN),
37 quote_vol_24h: t.quote_volume_24h.unwrap_or(f64::NAN),
38 change_pct_24h: t.price_change_percent_24h.unwrap_or(f64::NAN),
39 }
40 }
41}
42
43impl DataPoint for TickerPoint {
44 const RECORD_SIZE: usize = SIZE;
45
46 fn encode(&self, out: &mut [u8]) {
47 out[0..8].copy_from_slice(&(self.ts_ms as u64).to_le_bytes());
48 out[8..16].copy_from_slice(&self.last.to_le_bytes());
49 out[16..24].copy_from_slice(&self.bid.to_le_bytes());
50 out[24..32].copy_from_slice(&self.ask.to_le_bytes());
51 out[32..40].copy_from_slice(&self.high_24h.to_le_bytes());
52 out[40..48].copy_from_slice(&self.low_24h.to_le_bytes());
53 out[48..56].copy_from_slice(&self.vol_24h.to_le_bytes());
54 out[56..64].copy_from_slice(&self.quote_vol_24h.to_le_bytes());
55 out[64..72].copy_from_slice(&self.change_pct_24h.to_le_bytes());
56 }
57
58 fn decode(bytes: &[u8]) -> Option<Self> {
59 if bytes.len() != SIZE { return None; }
60 Some(Self {
61 ts_ms: u64::from_le_bytes(bytes[0..8].try_into().ok()?) as i64,
62 last: f64::from_le_bytes(bytes[8..16].try_into().ok()?),
63 bid: f64::from_le_bytes(bytes[16..24].try_into().ok()?),
64 ask: f64::from_le_bytes(bytes[24..32].try_into().ok()?),
65 high_24h: f64::from_le_bytes(bytes[32..40].try_into().ok()?),
66 low_24h: f64::from_le_bytes(bytes[40..48].try_into().ok()?),
67 vol_24h: f64::from_le_bytes(bytes[48..56].try_into().ok()?),
68 quote_vol_24h: f64::from_le_bytes(bytes[56..64].try_into().ok()?),
69 change_pct_24h: f64::from_le_bytes(bytes[64..72].try_into().ok()?),
70 })
71 }
72
73 fn timestamp_ms(&self) -> i64 { self.ts_ms }
74
75 fn from_stream_event(ev: &StreamEvent) -> Option<Self> {
76 if let StreamEvent::Ticker { ticker, .. } = ev {
77 Some(Self::from_ticker(ticker))
78 } else {
79 None
80 }
81 }
82}