digdigdig3_station/data/
open_interest_ext.rs1use digdigdig3::core::types::{OpenInterest, StreamEvent};
11use serde::{Deserialize, Serialize};
12
13use crate::series::DataPoint;
14
15#[inline]
16fn opt_f64(v: Option<f64>) -> f64 {
17 v.unwrap_or(f64::NAN)
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct OpenInterestIndicatorsPoint {
36 pub ts_ms: i64,
37 pub open_interest: f64,
38 pub open_interest_value: f64,
39 pub open_interest_ccy: f64,
40 pub open_interest_usd: f64,
41 pub single_open_interest: f64,
42 pub sum_open_interest: f64,
43 pub single_open_interest_value: f64,
44 pub sum_open_interest_value: f64,
45 pub cmc_circulating_supply: f64,
46 pub trade_amount: f64,
47 pub trade_volume: f64,
48 pub trade_turnover: f64,
49}
50
51const INDICATORS_SIZE: usize = 104;
52
53impl OpenInterestIndicatorsPoint {
54 pub fn from_open_interest(oi: &OpenInterest) -> Self {
56 Self {
57 ts_ms: oi.timestamp,
58 open_interest: oi.open_interest,
59 open_interest_value: opt_f64(oi.open_interest_value),
60 open_interest_ccy: opt_f64(oi.open_interest_ccy),
61 open_interest_usd: opt_f64(oi.open_interest_usd),
62 single_open_interest: opt_f64(oi.single_open_interest),
63 sum_open_interest: opt_f64(oi.sum_open_interest),
64 single_open_interest_value: opt_f64(oi.single_open_interest_value),
65 sum_open_interest_value: opt_f64(oi.sum_open_interest_value),
66 cmc_circulating_supply: opt_f64(oi.cmc_circulating_supply),
67 trade_amount: opt_f64(oi.trade_amount),
68 trade_volume: opt_f64(oi.trade_volume),
69 trade_turnover: opt_f64(oi.trade_turnover),
70 }
71 }
72}
73
74impl DataPoint for OpenInterestIndicatorsPoint {
75 const RECORD_SIZE: usize = INDICATORS_SIZE;
76
77 fn encode(&self, out: &mut [u8]) {
78 out[0..8].copy_from_slice(&(self.ts_ms as u64).to_le_bytes());
79 out[8..16].copy_from_slice(&self.open_interest.to_le_bytes());
80 out[16..24].copy_from_slice(&self.open_interest_value.to_le_bytes());
81 out[24..32].copy_from_slice(&self.open_interest_ccy.to_le_bytes());
82 out[32..40].copy_from_slice(&self.open_interest_usd.to_le_bytes());
83 out[40..48].copy_from_slice(&self.single_open_interest.to_le_bytes());
84 out[48..56].copy_from_slice(&self.sum_open_interest.to_le_bytes());
85 out[56..64].copy_from_slice(&self.single_open_interest_value.to_le_bytes());
86 out[64..72].copy_from_slice(&self.sum_open_interest_value.to_le_bytes());
87 out[72..80].copy_from_slice(&self.cmc_circulating_supply.to_le_bytes());
88 out[80..88].copy_from_slice(&self.trade_amount.to_le_bytes());
89 out[88..96].copy_from_slice(&self.trade_volume.to_le_bytes());
90 out[96..104].copy_from_slice(&self.trade_turnover.to_le_bytes());
91 }
92
93 fn decode(bytes: &[u8]) -> Option<Self> {
94 if bytes.len() != INDICATORS_SIZE {
95 return None;
96 }
97 Some(Self {
98 ts_ms: u64::from_le_bytes(bytes[0..8].try_into().ok()?) as i64,
99 open_interest: f64::from_le_bytes(bytes[8..16].try_into().ok()?),
100 open_interest_value: f64::from_le_bytes(bytes[16..24].try_into().ok()?),
101 open_interest_ccy: f64::from_le_bytes(bytes[24..32].try_into().ok()?),
102 open_interest_usd: f64::from_le_bytes(bytes[32..40].try_into().ok()?),
103 single_open_interest: f64::from_le_bytes(bytes[40..48].try_into().ok()?),
104 sum_open_interest: f64::from_le_bytes(bytes[48..56].try_into().ok()?),
105 single_open_interest_value: f64::from_le_bytes(bytes[56..64].try_into().ok()?),
106 sum_open_interest_value: f64::from_le_bytes(bytes[64..72].try_into().ok()?),
107 cmc_circulating_supply: f64::from_le_bytes(bytes[72..80].try_into().ok()?),
108 trade_amount: f64::from_le_bytes(bytes[80..88].try_into().ok()?),
109 trade_volume: f64::from_le_bytes(bytes[88..96].try_into().ok()?),
110 trade_turnover: f64::from_le_bytes(bytes[96..104].try_into().ok()?),
111 })
112 }
113
114 fn timestamp_ms(&self) -> i64 { self.ts_ms }
115
116 fn from_stream_event(ev: &StreamEvent) -> Option<Self> {
117 if let StreamEvent::OpenInterestUpdate { open_interest, .. } = ev {
118 Some(Self {
119 ts_ms: open_interest.timestamp,
120 open_interest: open_interest.open_interest,
121 open_interest_value: opt_f64(open_interest.open_interest_value),
122 open_interest_ccy: opt_f64(open_interest.open_interest_ccy),
123 open_interest_usd: opt_f64(open_interest.open_interest_usd),
124 single_open_interest: opt_f64(open_interest.single_open_interest),
125 sum_open_interest: opt_f64(open_interest.sum_open_interest),
126 single_open_interest_value: opt_f64(open_interest.single_open_interest_value),
127 sum_open_interest_value: opt_f64(open_interest.sum_open_interest_value),
128 cmc_circulating_supply: opt_f64(open_interest.cmc_circulating_supply),
129 trade_amount: opt_f64(open_interest.trade_amount),
130 trade_volume: opt_f64(open_interest.trade_volume),
131 trade_turnover: opt_f64(open_interest.trade_turnover),
132 })
133 } else {
134 None
135 }
136 }
137}
138
139pub type OpenInterestFullPoint = OpenInterestIndicatorsPoint;