Skip to main content

digdigdig3_station/data/
bar.rs

1use digdigdig3::core::types::{Kline, StreamEvent};
2use serde::{Deserialize, Serialize};
3
4use crate::series::DataPoint;
5
6/// 64 B bar record (LE):
7///   u64 open_time_ms
8///   f64 open, high, low, close
9///   f64 volume
10///   f64 quote_volume     (NaN if absent)
11///   u64 trades_count     (0 if absent)
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct BarPoint {
14    pub open_time: i64,
15    pub open: f64,
16    pub high: f64,
17    pub low: f64,
18    pub close: f64,
19    pub volume: f64,
20    pub quote_volume: f64,
21    pub trades_count: u64,
22}
23
24const SIZE: usize = 64;
25
26impl BarPoint {
27    pub fn from_kline(k: &Kline) -> Self {
28        Self {
29            open_time: k.open_time,
30            open: k.open,
31            high: k.high,
32            low: k.low,
33            close: k.close,
34            volume: k.volume,
35            quote_volume: k.quote_volume.unwrap_or(f64::NAN),
36            trades_count: k.trades.unwrap_or(0),
37        }
38    }
39}
40
41impl DataPoint for BarPoint {
42    const RECORD_SIZE: usize = SIZE;
43
44    fn encode(&self, out: &mut [u8]) {
45        out[0..8].copy_from_slice(&(self.open_time as u64).to_le_bytes());
46        out[8..16].copy_from_slice(&self.open.to_le_bytes());
47        out[16..24].copy_from_slice(&self.high.to_le_bytes());
48        out[24..32].copy_from_slice(&self.low.to_le_bytes());
49        out[32..40].copy_from_slice(&self.close.to_le_bytes());
50        out[40..48].copy_from_slice(&self.volume.to_le_bytes());
51        out[48..56].copy_from_slice(&self.quote_volume.to_le_bytes());
52        out[56..64].copy_from_slice(&self.trades_count.to_le_bytes());
53    }
54
55    fn decode(bytes: &[u8]) -> Option<Self> {
56        if bytes.len() != SIZE { return None; }
57        Some(Self {
58            open_time: u64::from_le_bytes(bytes[0..8].try_into().ok()?) as i64,
59            open: f64::from_le_bytes(bytes[8..16].try_into().ok()?),
60            high: f64::from_le_bytes(bytes[16..24].try_into().ok()?),
61            low: f64::from_le_bytes(bytes[24..32].try_into().ok()?),
62            close: f64::from_le_bytes(bytes[32..40].try_into().ok()?),
63            volume: f64::from_le_bytes(bytes[40..48].try_into().ok()?),
64            quote_volume: f64::from_le_bytes(bytes[48..56].try_into().ok()?),
65            trades_count: u64::from_le_bytes(bytes[56..64].try_into().ok()?),
66        })
67    }
68
69    fn timestamp_ms(&self) -> i64 { self.open_time }
70
71    fn from_stream_event(ev: &StreamEvent) -> Option<Self> {
72        if let StreamEvent::Kline { kline, .. } = ev {
73            Some(Self::from_kline(kline))
74        } else {
75            None
76        }
77    }
78}