digdigdig3_station/data/
trade.rs1use digdigdig3::core::types::{StreamEvent, TradeSide};
2use serde::{Deserialize, Serialize};
3
4use crate::series::DataPoint;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct TradePoint {
15 pub ts_ms: i64,
16 pub price: f64,
17 pub quantity: f64,
18 pub side: u8,
19 pub trade_id_hash: u64,
20}
21
22const SIZE: usize = 48;
23
24impl TradePoint {
25 pub fn from_public(t: &digdigdig3::core::types::PublicTrade) -> Self {
26 Self {
27 ts_ms: t.timestamp,
28 price: t.price,
29 quantity: t.quantity,
30 side: match t.side {
31 TradeSide::Buy => 0,
32 TradeSide::Sell => 1,
33 },
34 trade_id_hash: fnv1a_64(t.id.as_bytes()),
35 }
36 }
37
38 pub fn side_label(&self) -> &'static str {
39 match self.side {
40 0 => "Buy",
41 1 => "Sell",
42 _ => "?",
43 }
44 }
45}
46
47impl DataPoint for TradePoint {
48 const RECORD_SIZE: usize = SIZE;
49
50 fn encode(&self, out: &mut [u8]) {
51 out[0..8].copy_from_slice(&(self.ts_ms as u64).to_le_bytes());
52 out[8..16].copy_from_slice(&self.price.to_le_bytes());
53 out[16..24].copy_from_slice(&self.quantity.to_le_bytes());
54 out[24] = self.side;
55 out[25..33].copy_from_slice(&self.trade_id_hash.to_le_bytes());
56 }
58
59 fn decode(bytes: &[u8]) -> Option<Self> {
60 if bytes.len() != SIZE {
61 return None;
62 }
63 let ts_ms = u64::from_le_bytes(bytes[0..8].try_into().ok()?) as i64;
64 let price = f64::from_le_bytes(bytes[8..16].try_into().ok()?);
65 let quantity = f64::from_le_bytes(bytes[16..24].try_into().ok()?);
66 let side = bytes[24];
67 let trade_id_hash = u64::from_le_bytes(bytes[25..33].try_into().ok()?);
68 Some(Self { ts_ms, price, quantity, side, trade_id_hash })
69 }
70
71 fn timestamp_ms(&self) -> i64 {
72 self.ts_ms
73 }
74
75 fn from_stream_event(ev: &StreamEvent) -> Option<Self> {
76 if let StreamEvent::Trade { trade, .. } = ev {
77 Some(Self::from_public(trade))
78 } else {
79 None
80 }
81 }
82}
83
84fn fnv1a_64(bytes: &[u8]) -> u64 {
85 let mut h: u64 = 0xcbf29ce484222325;
86 for b in bytes {
87 h ^= *b as u64;
88 h = h.wrapping_mul(0x100000001b3);
89 }
90 h
91}