nautilus_common/messages/system/
trading.rs1use std::{
17 any::Any,
18 fmt::{Debug, Display},
19};
20
21use indexmap::IndexMap;
22use nautilus_core::{UUID4, UnixNanos};
23use nautilus_model::{enums::TradingState, identifiers::TraderId};
24use serde::{Deserialize, Serialize};
25
26#[repr(C)]
28#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
29#[serde(tag = "type")]
30#[cfg_attr(
31 feature = "python",
32 pyo3::pyclass(module = "nautilus_trader.model", from_py_object)
33)]
34pub struct TradingStateChanged {
35 pub trader_id: TraderId,
37 pub state: TradingState,
39 pub config: IndexMap<String, String>,
41 pub event_id: UUID4,
43 pub ts_event: UnixNanos,
45 pub ts_init: UnixNanos,
47}
48
49impl TradingStateChanged {
50 #[must_use]
52 pub fn new(
53 trader_id: TraderId,
54 state: TradingState,
55 config: IndexMap<String, String>,
56 event_id: UUID4,
57 ts_event: UnixNanos,
58 ts_init: UnixNanos,
59 ) -> Self {
60 Self {
61 trader_id,
62 state,
63 config,
64 event_id,
65 ts_event,
66 ts_init,
67 }
68 }
69
70 pub fn as_any(&self) -> &dyn Any {
71 self
72 }
73}
74
75impl Display for TradingStateChanged {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(
78 f,
79 "{}(trader_id={}, state={}, event_id={})",
80 stringify!(TradingStateChanged),
81 self.trader_id,
82 self.state,
83 self.event_id,
84 )
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use rstest::rstest;
91
92 use super::*;
93
94 fn trading_state_changed() -> TradingStateChanged {
95 let mut config = IndexMap::new();
96 config.insert(
97 "max_order_submit_rate".to_string(),
98 "100/00:00:01".to_string(),
99 );
100
101 TradingStateChanged::new(
102 TraderId::from("TESTER-001"),
103 TradingState::Halted,
104 config,
105 UUID4::from("00000000-0000-4000-8000-000000000002"),
106 UnixNanos::from(7),
107 UnixNanos::from(11),
108 )
109 }
110
111 #[rstest]
112 fn test_new_assigns_every_field() {
113 let event = trading_state_changed();
114
115 assert_eq!(event.trader_id, TraderId::from("TESTER-001"));
116 assert_eq!(event.state, TradingState::Halted);
117 assert_eq!(
118 event.config.get("max_order_submit_rate").unwrap(),
119 "100/00:00:01"
120 );
121 assert_eq!(
122 event.event_id,
123 UUID4::from("00000000-0000-4000-8000-000000000002")
124 );
125 assert_eq!(event.ts_event, UnixNanos::from(7));
126 assert_eq!(event.ts_init, UnixNanos::from(11));
127 }
128
129 #[rstest]
130 fn test_display_reports_identity_state_and_event_id() {
131 assert_eq!(
132 trading_state_changed().to_string(),
133 "TradingStateChanged(trader_id=TESTER-001, state=HALTED, \
134 event_id=00000000-0000-4000-8000-000000000002)"
135 );
136 }
137
138 #[rstest]
139 fn test_as_any_downcasts_to_self() {
140 let event = trading_state_changed();
141
142 assert_eq!(
143 event.as_any().downcast_ref::<TradingStateChanged>(),
144 Some(&event)
145 );
146 }
147
148 #[rstest]
149 fn test_serde_round_trips() {
150 let event = trading_state_changed();
151
152 let json = serde_json::to_string(&event).unwrap();
153
154 assert_eq!(
155 serde_json::from_str::<TradingStateChanged>(&json).unwrap(),
156 event
157 );
158 }
159}