nautilus_execution/models/
latency.rs1use std::fmt::{Debug, Display};
17
18use nautilus_core::UnixNanos;
19
20pub trait LatencyModel: Debug {
25 fn get_insert_latency(&self) -> UnixNanos;
27
28 fn get_update_latency(&self) -> UnixNanos;
30
31 fn get_delete_latency(&self) -> UnixNanos;
33
34 fn get_base_latency(&self) -> UnixNanos;
36}
37
38#[derive(Debug, Clone)]
39pub enum LatencyModelAny {
40 Static(StaticLatencyModel),
41}
42
43impl LatencyModel for LatencyModelAny {
44 fn get_insert_latency(&self) -> UnixNanos {
45 match self {
46 Self::Static(model) => model.get_insert_latency(),
47 }
48 }
49
50 fn get_update_latency(&self) -> UnixNanos {
51 match self {
52 Self::Static(model) => model.get_update_latency(),
53 }
54 }
55
56 fn get_delete_latency(&self) -> UnixNanos {
57 match self {
58 Self::Static(model) => model.get_delete_latency(),
59 }
60 }
61
62 fn get_base_latency(&self) -> UnixNanos {
63 match self {
64 Self::Static(model) => model.get_base_latency(),
65 }
66 }
67}
68
69impl From<LatencyModelAny> for Box<dyn LatencyModel> {
70 fn from(value: LatencyModelAny) -> Self {
71 match value {
72 LatencyModelAny::Static(model) => Box::new(model),
73 }
74 }
75}
76
77#[derive(Debug, Clone)]
86#[cfg_attr(
87 feature = "python",
88 pyo3::pyclass(
89 module = "nautilus_trader.core.nautilus_pyo3.execution",
90 unsendable,
91 from_py_object
92 )
93)]
94#[cfg_attr(
95 feature = "python",
96 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.execution")
97)]
98#[allow(
99 clippy::struct_field_names,
100 reason = "latency_nanos suffix consistently identifies latency types"
101)]
102pub struct StaticLatencyModel {
103 base_latency_nanos: UnixNanos,
104 insert_latency_nanos: UnixNanos,
105 update_latency_nanos: UnixNanos,
106 delete_latency_nanos: UnixNanos,
107}
108
109impl StaticLatencyModel {
110 #[must_use]
121 pub fn new(
122 base_latency_nanos: UnixNanos,
123 insert_latency_nanos: UnixNanos,
124 update_latency_nanos: UnixNanos,
125 delete_latency_nanos: UnixNanos,
126 ) -> Self {
127 Self {
128 base_latency_nanos,
129 insert_latency_nanos: UnixNanos::from(
130 base_latency_nanos.as_u64() + insert_latency_nanos.as_u64(),
131 ),
132 update_latency_nanos: UnixNanos::from(
133 base_latency_nanos.as_u64() + update_latency_nanos.as_u64(),
134 ),
135 delete_latency_nanos: UnixNanos::from(
136 base_latency_nanos.as_u64() + delete_latency_nanos.as_u64(),
137 ),
138 }
139 }
140}
141
142impl LatencyModel for StaticLatencyModel {
143 fn get_insert_latency(&self) -> UnixNanos {
144 self.insert_latency_nanos
145 }
146
147 fn get_update_latency(&self) -> UnixNanos {
148 self.update_latency_nanos
149 }
150
151 fn get_delete_latency(&self) -> UnixNanos {
152 self.delete_latency_nanos
153 }
154
155 fn get_base_latency(&self) -> UnixNanos {
156 self.base_latency_nanos
157 }
158}
159
160impl Display for StaticLatencyModel {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 write!(f, "LatencyModel()")
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use rstest::rstest;
169
170 use super::*;
171
172 #[rstest]
173 fn test_static_latency_model() {
174 let model = StaticLatencyModel::new(
175 UnixNanos::from(1_000_000),
176 UnixNanos::from(2_000_000),
177 UnixNanos::from(3_000_000),
178 UnixNanos::from(4_000_000),
179 );
180
181 assert_eq!(model.get_insert_latency().as_u64(), 3_000_000);
183 assert_eq!(model.get_update_latency().as_u64(), 4_000_000);
184 assert_eq!(model.get_delete_latency().as_u64(), 5_000_000);
185 assert_eq!(model.get_base_latency().as_u64(), 1_000_000);
186 }
187}