Skip to main content

nautilus_model/events/order/
any.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use std::fmt::Display;
17
18use nautilus_core::UnixNanos;
19use serde::{Deserialize, Serialize};
20use ustr::Ustr;
21
22use super::{OrderEvent, OrderEventType};
23use crate::{
24    events::{
25        OrderAccepted, OrderCancelRejected, OrderCanceled, OrderDenied, OrderEmulated,
26        OrderExpired, OrderFillVoided, OrderFilled, OrderInitialized, OrderModifyRejected,
27        OrderPendingCancel, OrderPendingUpdate, OrderRejected, OrderReleased, OrderSubmitted,
28        OrderTriggered, OrderUpdated,
29    },
30    identifiers::{AccountId, ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId},
31};
32
33/// Wraps an `OrderEvent` allowing polymorphism.
34#[allow(
35    clippy::large_enum_variant,
36    reason = "lint fires only with high-precision feature"
37)]
38#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
39pub enum OrderEventAny {
40    Initialized(OrderInitialized),
41    Denied(OrderDenied),
42    Emulated(OrderEmulated),
43    Released(OrderReleased),
44    Submitted(OrderSubmitted),
45    Accepted(OrderAccepted),
46    Rejected(OrderRejected),
47    Canceled(OrderCanceled),
48    Expired(OrderExpired),
49    Triggered(OrderTriggered),
50    PendingUpdate(OrderPendingUpdate),
51    PendingCancel(OrderPendingCancel),
52    ModifyRejected(OrderModifyRejected),
53    CancelRejected(OrderCancelRejected),
54    Updated(OrderUpdated),
55    Filled(OrderFilled),
56    FillVoided(OrderFillVoided),
57}
58
59impl OrderEventAny {
60    #[must_use]
61    pub fn into_boxed(self) -> Box<dyn OrderEvent> {
62        match self {
63            Self::Initialized(event) => Box::new(event),
64            Self::Denied(event) => Box::new(event),
65            Self::Emulated(event) => Box::new(event),
66            Self::Released(event) => Box::new(event),
67            Self::Submitted(event) => Box::new(event),
68            Self::Accepted(event) => Box::new(event),
69            Self::Rejected(event) => Box::new(event),
70            Self::Canceled(event) => Box::new(event),
71            Self::Expired(event) => Box::new(event),
72            Self::Triggered(event) => Box::new(event),
73            Self::PendingUpdate(event) => Box::new(event),
74            Self::PendingCancel(event) => Box::new(event),
75            Self::ModifyRejected(event) => Box::new(event),
76            Self::CancelRejected(event) => Box::new(event),
77            Self::Updated(event) => Box::new(event),
78            Self::Filled(event) => Box::new(event),
79            Self::FillVoided(event) => Box::new(event),
80        }
81    }
82
83    #[must_use]
84    pub fn event_type(&self) -> OrderEventType {
85        match self {
86            Self::Initialized(_) => OrderEventType::Initialized,
87            Self::Denied(_) => OrderEventType::Denied,
88            Self::Emulated(_) => OrderEventType::Emulated,
89            Self::Released(_) => OrderEventType::Released,
90            Self::Submitted(_) => OrderEventType::Submitted,
91            Self::Accepted(_) => OrderEventType::Accepted,
92            Self::Rejected(_) => OrderEventType::Rejected,
93            Self::Canceled(_) => OrderEventType::Canceled,
94            Self::Expired(_) => OrderEventType::Expired,
95            Self::Triggered(_) => OrderEventType::Triggered,
96            Self::PendingUpdate(_) => OrderEventType::PendingUpdate,
97            Self::PendingCancel(_) => OrderEventType::PendingCancel,
98            Self::ModifyRejected(_) => OrderEventType::ModifyRejected,
99            Self::CancelRejected(_) => OrderEventType::CancelRejected,
100            Self::Updated(_) => OrderEventType::Updated,
101            Self::Filled(_) => OrderEventType::Filled,
102            Self::FillVoided(_) => OrderEventType::FillVoided,
103        }
104    }
105
106    #[must_use]
107    pub fn trader_id(&self) -> TraderId {
108        match self {
109            Self::Initialized(event) => event.trader_id,
110            Self::Denied(event) => event.trader_id,
111            Self::Emulated(event) => event.trader_id,
112            Self::Released(event) => event.trader_id,
113            Self::Submitted(event) => event.trader_id,
114            Self::Accepted(event) => event.trader_id,
115            Self::Rejected(event) => event.trader_id,
116            Self::Canceled(event) => event.trader_id,
117            Self::Expired(event) => event.trader_id,
118            Self::Triggered(event) => event.trader_id,
119            Self::PendingUpdate(event) => event.trader_id,
120            Self::PendingCancel(event) => event.trader_id,
121            Self::ModifyRejected(event) => event.trader_id,
122            Self::CancelRejected(event) => event.trader_id,
123            Self::Updated(event) => event.trader_id,
124            Self::Filled(event) => event.trader_id,
125            Self::FillVoided(event) => event.trader_id,
126        }
127    }
128
129    #[must_use]
130    pub fn client_order_id(&self) -> ClientOrderId {
131        match self {
132            Self::Initialized(event) => event.client_order_id,
133            Self::Denied(event) => event.client_order_id,
134            Self::Emulated(event) => event.client_order_id,
135            Self::Released(event) => event.client_order_id,
136            Self::Submitted(event) => event.client_order_id,
137            Self::Accepted(event) => event.client_order_id,
138            Self::Rejected(event) => event.client_order_id,
139            Self::Canceled(event) => event.client_order_id,
140            Self::Expired(event) => event.client_order_id,
141            Self::Triggered(event) => event.client_order_id,
142            Self::PendingUpdate(event) => event.client_order_id,
143            Self::PendingCancel(event) => event.client_order_id,
144            Self::ModifyRejected(event) => event.client_order_id,
145            Self::CancelRejected(event) => event.client_order_id,
146            Self::Updated(event) => event.client_order_id,
147            Self::Filled(event) => event.client_order_id,
148            Self::FillVoided(event) => event.client_order_id,
149        }
150    }
151
152    #[must_use]
153    pub fn with_client_order_id(mut self, client_order_id: ClientOrderId) -> Self {
154        match &mut self {
155            Self::Initialized(event) => event.client_order_id = client_order_id,
156            Self::Denied(event) => event.client_order_id = client_order_id,
157            Self::Emulated(event) => event.client_order_id = client_order_id,
158            Self::Released(event) => event.client_order_id = client_order_id,
159            Self::Submitted(event) => event.client_order_id = client_order_id,
160            Self::Accepted(event) => event.client_order_id = client_order_id,
161            Self::Rejected(event) => event.client_order_id = client_order_id,
162            Self::Canceled(event) => event.client_order_id = client_order_id,
163            Self::Expired(event) => event.client_order_id = client_order_id,
164            Self::Triggered(event) => event.client_order_id = client_order_id,
165            Self::PendingUpdate(event) => event.client_order_id = client_order_id,
166            Self::PendingCancel(event) => event.client_order_id = client_order_id,
167            Self::ModifyRejected(event) => event.client_order_id = client_order_id,
168            Self::CancelRejected(event) => event.client_order_id = client_order_id,
169            Self::Updated(event) => event.client_order_id = client_order_id,
170            Self::Filled(event) => event.client_order_id = client_order_id,
171            Self::FillVoided(event) => event.client_order_id = client_order_id,
172        }
173
174        self
175    }
176
177    #[must_use]
178    pub fn venue_order_id(&self) -> Option<VenueOrderId> {
179        match self {
180            Self::Initialized(event) => event.venue_order_id(),
181            Self::Denied(event) => event.venue_order_id(),
182            Self::Emulated(event) => event.venue_order_id(),
183            Self::Released(event) => event.venue_order_id(),
184            Self::Submitted(event) => event.venue_order_id(),
185            Self::Accepted(event) => event.venue_order_id(),
186            Self::Rejected(event) => event.venue_order_id(),
187            Self::Canceled(event) => event.venue_order_id(),
188            Self::Expired(event) => event.venue_order_id(),
189            Self::Triggered(event) => event.venue_order_id(),
190            Self::PendingUpdate(event) => event.venue_order_id(),
191            Self::PendingCancel(event) => event.venue_order_id(),
192            Self::ModifyRejected(event) => event.venue_order_id(),
193            Self::CancelRejected(event) => event.venue_order_id(),
194            Self::Updated(event) => event.venue_order_id(),
195            Self::Filled(event) => event.venue_order_id(),
196            Self::FillVoided(event) => event.venue_order_id(),
197        }
198    }
199
200    #[must_use]
201    pub fn account_id(&self) -> Option<AccountId> {
202        match self {
203            Self::Initialized(event) => event.account_id(),
204            Self::Denied(event) => event.account_id(),
205            Self::Emulated(event) => event.account_id(),
206            Self::Released(event) => event.account_id(),
207            Self::Submitted(event) => event.account_id(),
208            Self::Accepted(event) => event.account_id(),
209            Self::Rejected(event) => event.account_id(),
210            Self::Canceled(event) => event.account_id(),
211            Self::Expired(event) => event.account_id(),
212            Self::Triggered(event) => event.account_id(),
213            Self::PendingUpdate(event) => event.account_id(),
214            Self::PendingCancel(event) => event.account_id(),
215            Self::ModifyRejected(event) => event.account_id(),
216            Self::CancelRejected(event) => event.account_id(),
217            Self::Updated(event) => event.account_id(),
218            Self::Filled(event) => event.account_id(),
219            Self::FillVoided(event) => event.account_id(),
220        }
221    }
222
223    #[must_use]
224    pub fn instrument_id(&self) -> InstrumentId {
225        match self {
226            Self::Initialized(event) => event.instrument_id(),
227            Self::Denied(event) => event.instrument_id(),
228            Self::Emulated(event) => event.instrument_id(),
229            Self::Released(event) => event.instrument_id(),
230            Self::Submitted(event) => event.instrument_id(),
231            Self::Accepted(event) => event.instrument_id(),
232            Self::Rejected(event) => event.instrument_id(),
233            Self::Canceled(event) => event.instrument_id(),
234            Self::Expired(event) => event.instrument_id(),
235            Self::Triggered(event) => event.instrument_id(),
236            Self::PendingUpdate(event) => event.instrument_id(),
237            Self::PendingCancel(event) => event.instrument_id(),
238            Self::ModifyRejected(event) => event.instrument_id(),
239            Self::CancelRejected(event) => event.instrument_id(),
240            Self::Updated(event) => event.instrument_id(),
241            Self::Filled(event) => event.instrument_id(),
242            Self::FillVoided(event) => event.instrument_id(),
243        }
244    }
245
246    #[must_use]
247    pub fn strategy_id(&self) -> StrategyId {
248        match self {
249            Self::Initialized(event) => event.strategy_id,
250            Self::Denied(event) => event.strategy_id,
251            Self::Emulated(event) => event.strategy_id,
252            Self::Released(event) => event.strategy_id,
253            Self::Submitted(event) => event.strategy_id,
254            Self::Accepted(event) => event.strategy_id,
255            Self::Rejected(event) => event.strategy_id,
256            Self::Canceled(event) => event.strategy_id,
257            Self::Expired(event) => event.strategy_id,
258            Self::Triggered(event) => event.strategy_id,
259            Self::PendingUpdate(event) => event.strategy_id,
260            Self::PendingCancel(event) => event.strategy_id,
261            Self::ModifyRejected(event) => event.strategy_id,
262            Self::CancelRejected(event) => event.strategy_id,
263            Self::Updated(event) => event.strategy_id,
264            Self::Filled(event) => event.strategy_id,
265            Self::FillVoided(event) => event.strategy_id,
266        }
267    }
268
269    #[must_use]
270    pub fn ts_event(&self) -> UnixNanos {
271        match self {
272            Self::Initialized(event) => event.ts_event,
273            Self::Denied(event) => event.ts_event,
274            Self::Emulated(event) => event.ts_event,
275            Self::Released(event) => event.ts_event,
276            Self::Submitted(event) => event.ts_event,
277            Self::Accepted(event) => event.ts_event,
278            Self::Rejected(event) => event.ts_event,
279            Self::Canceled(event) => event.ts_event,
280            Self::Expired(event) => event.ts_event,
281            Self::Triggered(event) => event.ts_event,
282            Self::PendingUpdate(event) => event.ts_event,
283            Self::PendingCancel(event) => event.ts_event,
284            Self::ModifyRejected(event) => event.ts_event,
285            Self::CancelRejected(event) => event.ts_event,
286            Self::Updated(event) => event.ts_event,
287            Self::Filled(event) => event.ts_event,
288            Self::FillVoided(event) => event.ts_event,
289        }
290    }
291
292    #[must_use]
293    pub fn message(&self) -> Option<Ustr> {
294        match self {
295            Self::Initialized(_) => None,
296            Self::Denied(event) => Some(event.reason),
297            Self::Emulated(_) => None,
298            Self::Released(_) => None,
299            Self::Submitted(_) => None,
300            Self::Accepted(_) => None,
301            Self::Rejected(event) => Some(event.reason),
302            Self::Canceled(_) => None,
303            Self::Expired(_) => None,
304            Self::Triggered(_) => None,
305            Self::PendingUpdate(_) => None,
306            Self::PendingCancel(_) => None,
307            Self::ModifyRejected(event) => Some(event.reason),
308            Self::CancelRejected(event) => Some(event.reason),
309            Self::Updated(_) => None,
310            Self::Filled(_) => None,
311            Self::FillVoided(event) => event.reason,
312        }
313    }
314}
315
316/// Converts an `OrderEventAny` into an `OrderFilled`.
317///
318/// # Panics
319///
320/// Panics if `event` is not a `Filled` variant.
321impl From<OrderEventAny> for OrderFilled {
322    #[inline]
323    fn from(event: OrderEventAny) -> Self {
324        match event {
325            OrderEventAny::Filled(event) => event,
326            _ => panic!("Invalid `OrderEventAny` not `OrderFilled`, was {event:?}"),
327        }
328    }
329}
330
331impl Display for OrderEventAny {
332    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
333        match self {
334            Self::Initialized(e) => write!(f, "{e}"),
335            Self::Denied(e) => write!(f, "{e}"),
336            Self::Emulated(e) => write!(f, "{e}"),
337            Self::Released(e) => write!(f, "{e}"),
338            Self::Submitted(e) => write!(f, "{e}"),
339            Self::Accepted(e) => write!(f, "{e}"),
340            Self::Rejected(e) => write!(f, "{e}"),
341            Self::Canceled(e) => write!(f, "{e}"),
342            Self::Expired(e) => write!(f, "{e}"),
343            Self::Triggered(e) => write!(f, "{e}"),
344            Self::PendingUpdate(e) => write!(f, "{e}"),
345            Self::PendingCancel(e) => write!(f, "{e}"),
346            Self::ModifyRejected(e) => write!(f, "{e}"),
347            Self::CancelRejected(e) => write!(f, "{e}"),
348            Self::Updated(e) => write!(f, "{e}"),
349            Self::Filled(e) => write!(f, "{e}"),
350            Self::FillVoided(e) => write!(f, "{e}"),
351        }
352    }
353}
354
355#[cfg(test)]
356mod tests {
357    use rstest::rstest;
358
359    use super::OrderEventAny;
360    use crate::events::{OrderAccepted, OrderFilled, order::stubs::*};
361
362    #[rstest]
363    fn test_from_order_event_any_to_filled(order_filled: OrderFilled) {
364        let expected_trade_id = order_filled.trade_id;
365        let event = OrderEventAny::Filled(order_filled);
366        let filled: OrderFilled = event.into();
367        assert_eq!(filled.trade_id, expected_trade_id);
368    }
369
370    #[rstest]
371    #[should_panic(expected = "Invalid `OrderEventAny` not `OrderFilled`")]
372    fn test_from_order_event_any_to_filled_panics_on_wrong_variant(order_accepted: OrderAccepted) {
373        let event = OrderEventAny::Accepted(order_accepted);
374        let _filled: OrderFilled = event.into();
375    }
376
377    #[rstest]
378    fn test_display_delegates_to_inner(order_filled: OrderFilled) {
379        let inner_display = format!("{order_filled}");
380        let event = OrderEventAny::Filled(order_filled);
381        assert_eq!(format!("{event}"), inner_display);
382    }
383}