nautilus_model/orders/
any.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 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 indexmap::IndexMap;
19use nautilus_core::{UnixNanos, UUID4};
20use rust_decimal::Decimal;
21use serde::{Deserialize, Serialize};
22use ustr::Ustr;
23
24use super::{
25    base::{Order, OrderError},
26    limit::LimitOrder,
27    limit_if_touched::LimitIfTouchedOrder,
28    market::MarketOrder,
29    market_if_touched::MarketIfTouchedOrder,
30    market_to_limit::MarketToLimitOrder,
31    stop_limit::StopLimitOrder,
32    stop_market::StopMarketOrder,
33    trailing_stop_limit::TrailingStopLimitOrder,
34    trailing_stop_market::TrailingStopMarketOrder,
35};
36use crate::{
37    enums::{
38        ContingencyType, LiquiditySide, OrderSide, OrderSideSpecified, OrderStatus, OrderType,
39        PositionSide, TimeInForce, TrailingOffsetType, TriggerType,
40    },
41    events::OrderEventAny,
42    identifiers::{
43        AccountId, ClientOrderId, ExecAlgorithmId, InstrumentId, OrderListId, PositionId,
44        StrategyId, TradeId, TraderId, VenueOrderId,
45    },
46    types::{Currency, Money, Price, Quantity},
47};
48
49#[derive(Clone, Debug, Serialize, Deserialize)]
50pub enum OrderAny {
51    Limit(LimitOrder),
52    LimitIfTouched(LimitIfTouchedOrder),
53    Market(MarketOrder),
54    MarketIfTouched(MarketIfTouchedOrder),
55    MarketToLimit(MarketToLimitOrder),
56    StopLimit(StopLimitOrder),
57    StopMarket(StopMarketOrder),
58    TrailingStopLimit(TrailingStopLimitOrder),
59    TrailingStopMarket(TrailingStopMarketOrder),
60}
61
62impl Default for OrderAny {
63    fn default() -> Self {
64        Self::Limit(LimitOrder::default())
65    }
66}
67
68impl OrderAny {
69    /// Applies the given `event` to the order.
70    pub fn apply(&mut self, event: OrderEventAny) -> Result<(), OrderError> {
71        match self {
72            OrderAny::Limit(order) => order.apply(event),
73            OrderAny::LimitIfTouched(order) => order.apply(event),
74            OrderAny::Market(order) => order.apply(event),
75            OrderAny::MarketIfTouched(order) => order.apply(event),
76            OrderAny::MarketToLimit(order) => order.apply(event),
77            OrderAny::StopLimit(order) => order.apply(event),
78            OrderAny::StopMarket(order) => order.apply(event),
79            OrderAny::TrailingStopLimit(order) => order.apply(event),
80            OrderAny::TrailingStopMarket(order) => order.apply(event),
81        }
82    }
83
84    #[must_use]
85    pub fn from_limit(order: LimitOrder) -> Self {
86        Self::Limit(order)
87    }
88
89    #[must_use]
90    pub fn from_limit_if_touched(order: LimitIfTouchedOrder) -> Self {
91        Self::LimitIfTouched(order)
92    }
93
94    #[must_use]
95    pub fn from_market(order: MarketOrder) -> Self {
96        Self::Market(order)
97    }
98
99    #[must_use]
100    pub fn from_market_if_touched(order: MarketIfTouchedOrder) -> Self {
101        Self::MarketIfTouched(order)
102    }
103
104    #[must_use]
105    pub fn from_market_to_limit(order: MarketToLimitOrder) -> Self {
106        Self::MarketToLimit(order)
107    }
108
109    #[must_use]
110    pub fn from_stop_limit(order: StopLimitOrder) -> Self {
111        Self::StopLimit(order)
112    }
113
114    #[must_use]
115    pub fn from_stop_market(order: StopMarketOrder) -> Self {
116        Self::StopMarket(order)
117    }
118
119    #[must_use]
120    pub fn from_trailing_stop_limit(order: StopLimitOrder) -> Self {
121        Self::StopLimit(order)
122    }
123
124    #[must_use]
125    pub fn from_trailing_stop_market(order: StopMarketOrder) -> Self {
126        Self::StopMarket(order)
127    }
128
129    pub fn from_events(events: Vec<OrderEventAny>) -> anyhow::Result<Self> {
130        if events.is_empty() {
131            anyhow::bail!("No order events provided to create OrderAny");
132        }
133
134        // Pop the first event
135        let init_event = events.first().unwrap();
136        match init_event {
137            OrderEventAny::Initialized(init) => {
138                let mut order = Self::from(init.clone());
139                // Apply the rest of the events
140                for event in events.into_iter().skip(1) {
141                    // Apply event to order
142                    println!("Applying event: {:?}", event);
143                    order.apply(event).unwrap();
144                }
145                Ok(order)
146            }
147            _ => {
148                anyhow::bail!("First event must be `OrderInitialized`");
149            }
150        }
151    }
152
153    pub fn events(&self) -> Vec<&OrderEventAny> {
154        match self {
155            Self::Limit(order) => order.events(),
156            Self::LimitIfTouched(order) => order.events(),
157            Self::Market(order) => order.events(),
158            Self::MarketIfTouched(order) => order.events(),
159            Self::MarketToLimit(order) => order.events(),
160            Self::StopLimit(order) => order.events(),
161            Self::StopMarket(order) => order.events(),
162            Self::TrailingStopLimit(order) => order.events(),
163            Self::TrailingStopMarket(order) => order.events(),
164        }
165    }
166
167    #[must_use]
168    pub fn last_event(&self) -> &OrderEventAny {
169        match self {
170            Self::Limit(order) => order.last_event(),
171            Self::LimitIfTouched(order) => order.last_event(),
172            Self::Market(order) => order.last_event(),
173            Self::MarketIfTouched(order) => order.last_event(),
174            Self::MarketToLimit(order) => order.last_event(),
175            Self::StopLimit(order) => order.last_event(),
176            Self::StopMarket(order) => order.last_event(),
177            Self::TrailingStopLimit(order) => order.last_event(),
178            Self::TrailingStopMarket(order) => order.last_event(),
179        }
180    }
181
182    #[must_use]
183    pub fn trader_id(&self) -> TraderId {
184        match self {
185            Self::Limit(order) => order.trader_id,
186            Self::LimitIfTouched(order) => order.trader_id,
187            Self::Market(order) => order.trader_id,
188            Self::MarketIfTouched(order) => order.trader_id,
189            Self::MarketToLimit(order) => order.trader_id,
190            Self::StopLimit(order) => order.trader_id,
191            Self::StopMarket(order) => order.trader_id,
192            Self::TrailingStopLimit(order) => order.trader_id,
193            Self::TrailingStopMarket(order) => order.trader_id,
194        }
195    }
196
197    #[must_use]
198    pub fn strategy_id(&self) -> StrategyId {
199        match self {
200            Self::Limit(order) => order.strategy_id,
201            Self::LimitIfTouched(order) => order.strategy_id,
202            Self::Market(order) => order.strategy_id,
203            Self::MarketIfTouched(order) => order.strategy_id,
204            Self::MarketToLimit(order) => order.strategy_id,
205            Self::StopLimit(order) => order.strategy_id,
206            Self::StopMarket(order) => order.strategy_id,
207            Self::TrailingStopLimit(order) => order.strategy_id,
208            Self::TrailingStopMarket(order) => order.strategy_id,
209        }
210    }
211
212    #[must_use]
213    pub fn instrument_id(&self) -> InstrumentId {
214        match self {
215            Self::Limit(order) => order.instrument_id,
216            Self::LimitIfTouched(order) => order.instrument_id,
217            Self::Market(order) => order.instrument_id,
218            Self::MarketIfTouched(order) => order.instrument_id,
219            Self::MarketToLimit(order) => order.instrument_id,
220            Self::StopLimit(order) => order.instrument_id,
221            Self::StopMarket(order) => order.instrument_id,
222            Self::TrailingStopLimit(order) => order.instrument_id,
223            Self::TrailingStopMarket(order) => order.instrument_id,
224        }
225    }
226
227    #[must_use]
228    pub fn client_order_id(&self) -> ClientOrderId {
229        match self {
230            Self::Limit(order) => order.client_order_id,
231            Self::LimitIfTouched(order) => order.client_order_id,
232            Self::Market(order) => order.client_order_id,
233            Self::MarketIfTouched(order) => order.client_order_id,
234            Self::MarketToLimit(order) => order.client_order_id,
235            Self::StopLimit(order) => order.client_order_id,
236            Self::StopMarket(order) => order.client_order_id,
237            Self::TrailingStopLimit(order) => order.client_order_id,
238            Self::TrailingStopMarket(order) => order.client_order_id,
239        }
240    }
241
242    #[must_use]
243    pub fn account_id(&self) -> Option<AccountId> {
244        match self {
245            Self::Limit(order) => order.account_id,
246            Self::LimitIfTouched(order) => order.account_id,
247            Self::Market(order) => order.account_id,
248            Self::MarketIfTouched(order) => order.account_id,
249            Self::MarketToLimit(order) => order.account_id,
250            Self::StopLimit(order) => order.account_id,
251            Self::StopMarket(order) => order.account_id,
252            Self::TrailingStopLimit(order) => order.account_id,
253            Self::TrailingStopMarket(order) => order.account_id,
254        }
255    }
256
257    #[must_use]
258    pub fn venue_order_id(&self) -> Option<VenueOrderId> {
259        match self {
260            Self::Limit(order) => order.venue_order_id,
261            Self::LimitIfTouched(order) => order.venue_order_id,
262            Self::Market(order) => order.venue_order_id,
263            Self::MarketIfTouched(order) => order.venue_order_id,
264            Self::MarketToLimit(order) => order.venue_order_id,
265            Self::StopLimit(order) => order.venue_order_id,
266            Self::StopMarket(order) => order.venue_order_id,
267            Self::TrailingStopLimit(order) => order.venue_order_id,
268            Self::TrailingStopMarket(order) => order.venue_order_id,
269        }
270    }
271
272    #[must_use]
273    pub fn position_id(&self) -> Option<PositionId> {
274        match self {
275            Self::Limit(order) => order.position_id,
276            Self::LimitIfTouched(order) => order.position_id,
277            Self::Market(order) => order.position_id,
278            Self::MarketIfTouched(order) => order.position_id,
279            Self::MarketToLimit(order) => order.position_id,
280            Self::StopLimit(order) => order.position_id,
281            Self::StopMarket(order) => order.position_id,
282            Self::TrailingStopLimit(order) => order.position_id,
283            Self::TrailingStopMarket(order) => order.position_id,
284        }
285    }
286
287    #[must_use]
288    pub fn order_list_id(&self) -> Option<OrderListId> {
289        match self {
290            Self::Limit(order) => order.order_list_id(),
291            Self::LimitIfTouched(order) => order.order_list_id(),
292            Self::Market(order) => order.order_list_id(),
293            Self::MarketIfTouched(order) => order.order_list_id(),
294            Self::MarketToLimit(order) => order.order_list_id(),
295            Self::StopLimit(order) => order.order_list_id(),
296            Self::StopMarket(order) => order.order_list_id(),
297            Self::TrailingStopLimit(order) => order.order_list_id(),
298            Self::TrailingStopMarket(order) => order.order_list_id(),
299        }
300    }
301
302    #[must_use]
303    pub fn last_trade_id(&self) -> Option<TradeId> {
304        match self {
305            Self::Limit(order) => order.last_trade_id,
306            Self::LimitIfTouched(order) => order.last_trade_id,
307            Self::Market(order) => order.last_trade_id,
308            Self::MarketIfTouched(order) => order.last_trade_id,
309            Self::MarketToLimit(order) => order.last_trade_id,
310            Self::StopLimit(order) => order.last_trade_id,
311            Self::StopMarket(order) => order.last_trade_id,
312            Self::TrailingStopLimit(order) => order.last_trade_id,
313            Self::TrailingStopMarket(order) => order.last_trade_id,
314        }
315    }
316
317    #[must_use]
318    pub fn init_id(&self) -> UUID4 {
319        match self {
320            Self::Limit(order) => order.init_id,
321            Self::LimitIfTouched(order) => order.init_id,
322            Self::Market(order) => order.init_id,
323            Self::MarketIfTouched(order) => order.init_id,
324            Self::MarketToLimit(order) => order.init_id,
325            Self::StopLimit(order) => order.init_id,
326            Self::StopMarket(order) => order.init_id,
327            Self::TrailingStopLimit(order) => order.init_id,
328            Self::TrailingStopMarket(order) => order.init_id,
329        }
330    }
331
332    #[must_use]
333    pub fn ts_init(&self) -> UnixNanos {
334        match self {
335            Self::Limit(order) => order.ts_init,
336            Self::LimitIfTouched(order) => order.ts_init,
337            Self::Market(order) => order.ts_init,
338            Self::MarketIfTouched(order) => order.ts_init,
339            Self::MarketToLimit(order) => order.ts_init,
340            Self::StopLimit(order) => order.ts_init,
341            Self::StopMarket(order) => order.ts_init,
342            Self::TrailingStopLimit(order) => order.ts_init,
343            Self::TrailingStopMarket(order) => order.ts_init,
344        }
345    }
346
347    #[must_use]
348    pub fn ts_last(&self) -> UnixNanos {
349        match self {
350            Self::Limit(order) => order.ts_last,
351            Self::LimitIfTouched(order) => order.ts_last,
352            Self::Market(order) => order.ts_last,
353            Self::MarketIfTouched(order) => order.ts_last,
354            Self::MarketToLimit(order) => order.ts_last,
355            Self::StopLimit(order) => order.ts_last,
356            Self::StopMarket(order) => order.ts_last,
357            Self::TrailingStopLimit(order) => order.ts_last,
358            Self::TrailingStopMarket(order) => order.ts_last,
359        }
360    }
361
362    #[must_use]
363    pub fn exec_algorithm_id(&self) -> Option<ExecAlgorithmId> {
364        match self {
365            Self::Limit(order) => order.exec_algorithm_id,
366            Self::LimitIfTouched(order) => order.exec_algorithm_id,
367            Self::Market(order) => order.exec_algorithm_id,
368            Self::MarketIfTouched(order) => order.exec_algorithm_id,
369            Self::MarketToLimit(order) => order.exec_algorithm_id,
370            Self::StopLimit(order) => order.exec_algorithm_id,
371            Self::StopMarket(order) => order.exec_algorithm_id,
372            Self::TrailingStopLimit(order) => order.exec_algorithm_id,
373            Self::TrailingStopMarket(order) => order.exec_algorithm_id,
374        }
375    }
376
377    #[must_use]
378    pub fn exec_algorithm_params(&self) -> Option<IndexMap<Ustr, Ustr>> {
379        match self {
380            Self::Limit(order) => order.exec_algorithm_params.clone(),
381            Self::LimitIfTouched(order) => order.exec_algorithm_params.clone(),
382            Self::Market(order) => order.exec_algorithm_params.clone(),
383            Self::MarketIfTouched(order) => order.exec_algorithm_params.clone(),
384            Self::MarketToLimit(order) => order.exec_algorithm_params.clone(),
385            Self::StopLimit(order) => order.exec_algorithm_params.clone(),
386            Self::StopMarket(order) => order.exec_algorithm_params.clone(),
387            Self::TrailingStopLimit(order) => order.exec_algorithm_params.clone(),
388            Self::TrailingStopMarket(order) => order.exec_algorithm_params.clone(),
389        }
390    }
391
392    #[must_use]
393    pub fn exec_spawn_id(&self) -> Option<ClientOrderId> {
394        match self {
395            Self::Limit(order) => order.exec_spawn_id,
396            Self::LimitIfTouched(order) => order.exec_spawn_id,
397            Self::Market(order) => order.exec_spawn_id,
398            Self::MarketIfTouched(order) => order.exec_spawn_id,
399            Self::MarketToLimit(order) => order.exec_spawn_id,
400            Self::StopLimit(order) => order.exec_spawn_id,
401            Self::StopMarket(order) => order.exec_spawn_id,
402            Self::TrailingStopLimit(order) => order.exec_spawn_id,
403            Self::TrailingStopMarket(order) => order.exec_spawn_id,
404        }
405    }
406
407    #[must_use]
408    pub fn order_side(&self) -> OrderSide {
409        match self {
410            Self::Limit(order) => order.side,
411            Self::LimitIfTouched(order) => order.side,
412            Self::Market(order) => order.side,
413            Self::MarketIfTouched(order) => order.side,
414            Self::MarketToLimit(order) => order.side,
415            Self::StopLimit(order) => order.side,
416            Self::StopMarket(order) => order.side,
417            Self::TrailingStopLimit(order) => order.side,
418            Self::TrailingStopMarket(order) => order.side,
419        }
420    }
421
422    #[must_use]
423    pub fn order_side_specified(&self) -> OrderSideSpecified {
424        match self {
425            Self::Limit(order) => order.side.as_specified(),
426            Self::LimitIfTouched(order) => order.side.as_specified(),
427            Self::Market(order) => order.side.as_specified(),
428            Self::MarketIfTouched(order) => order.side.as_specified(),
429            Self::MarketToLimit(order) => order.side.as_specified(),
430            Self::StopLimit(order) => order.side.as_specified(),
431            Self::StopMarket(order) => order.side.as_specified(),
432            Self::TrailingStopLimit(order) => order.side.as_specified(),
433            Self::TrailingStopMarket(order) => order.side.as_specified(),
434        }
435    }
436
437    #[must_use]
438    pub fn order_type(&self) -> OrderType {
439        match self {
440            Self::Limit(order) => order.order_type,
441            Self::LimitIfTouched(order) => order.order_type,
442            Self::Market(order) => order.order_type,
443            Self::MarketIfTouched(order) => order.order_type,
444            Self::MarketToLimit(order) => order.order_type,
445            Self::StopLimit(order) => order.order_type,
446            Self::StopMarket(order) => order.order_type,
447            Self::TrailingStopLimit(order) => order.order_type,
448            Self::TrailingStopMarket(order) => order.order_type,
449        }
450    }
451
452    #[must_use]
453    pub fn quantity(&self) -> Quantity {
454        match self {
455            Self::Limit(order) => order.quantity,
456            Self::LimitIfTouched(order) => order.quantity,
457            Self::Market(order) => order.quantity,
458            Self::MarketIfTouched(order) => order.quantity,
459            Self::MarketToLimit(order) => order.quantity,
460            Self::StopLimit(order) => order.quantity,
461            Self::StopMarket(order) => order.quantity,
462            Self::TrailingStopLimit(order) => order.quantity,
463            Self::TrailingStopMarket(order) => order.quantity,
464        }
465    }
466
467    #[must_use]
468    pub fn liquidity_side(&self) -> Option<LiquiditySide> {
469        match self {
470            Self::Limit(order) => order.liquidity_side,
471            Self::LimitIfTouched(order) => order.liquidity_side,
472            Self::Market(order) => order.liquidity_side,
473            Self::MarketIfTouched(order) => order.liquidity_side,
474            Self::MarketToLimit(order) => order.liquidity_side,
475            Self::StopLimit(order) => order.liquidity_side,
476            Self::StopMarket(order) => order.liquidity_side,
477            Self::TrailingStopLimit(order) => order.liquidity_side,
478            Self::TrailingStopMarket(order) => order.liquidity_side,
479        }
480    }
481
482    #[must_use]
483    pub fn time_in_force(&self) -> TimeInForce {
484        match self {
485            Self::Limit(order) => order.time_in_force,
486            Self::LimitIfTouched(order) => order.time_in_force,
487            Self::Market(order) => order.time_in_force,
488            Self::MarketIfTouched(order) => order.time_in_force,
489            Self::MarketToLimit(order) => order.time_in_force,
490            Self::StopLimit(order) => order.time_in_force,
491            Self::StopMarket(order) => order.time_in_force,
492            Self::TrailingStopLimit(order) => order.time_in_force,
493            Self::TrailingStopMarket(order) => order.time_in_force,
494        }
495    }
496
497    #[must_use]
498    pub fn expire_time(&self) -> Option<UnixNanos> {
499        match self {
500            Self::Limit(order) => order.expire_time,
501            Self::LimitIfTouched(order) => order.expire_time,
502            Self::Market(_) => None,
503            Self::MarketIfTouched(order) => order.expire_time,
504            Self::MarketToLimit(order) => order.expire_time,
505            Self::StopLimit(order) => order.expire_time,
506            Self::StopMarket(order) => order.expire_time,
507            Self::TrailingStopLimit(order) => order.expire_time,
508            Self::TrailingStopMarket(order) => order.expire_time,
509        }
510    }
511
512    #[must_use]
513    pub fn status(&self) -> OrderStatus {
514        match self {
515            Self::Limit(order) => order.status,
516            Self::LimitIfTouched(order) => order.status,
517            Self::Market(order) => order.status,
518            Self::MarketIfTouched(order) => order.status,
519            Self::MarketToLimit(order) => order.status,
520            Self::StopLimit(order) => order.status,
521            Self::StopMarket(order) => order.status,
522            Self::TrailingStopLimit(order) => order.status,
523            Self::TrailingStopMarket(order) => order.status,
524        }
525    }
526
527    #[must_use]
528    pub fn filled_qty(&self) -> Quantity {
529        match self {
530            Self::Limit(order) => order.filled_qty(),
531            Self::LimitIfTouched(order) => order.filled_qty(),
532            Self::Market(order) => order.filled_qty(),
533            Self::MarketIfTouched(order) => order.filled_qty(),
534            Self::MarketToLimit(order) => order.filled_qty(),
535            Self::StopLimit(order) => order.filled_qty(),
536            Self::StopMarket(order) => order.filled_qty(),
537            Self::TrailingStopLimit(order) => order.filled_qty(),
538            Self::TrailingStopMarket(order) => order.filled_qty(),
539        }
540    }
541
542    #[must_use]
543    pub fn leaves_qty(&self) -> Quantity {
544        match self {
545            Self::Limit(order) => order.leaves_qty(),
546            Self::LimitIfTouched(order) => order.leaves_qty(),
547            Self::Market(order) => order.leaves_qty(),
548            Self::MarketIfTouched(order) => order.leaves_qty(),
549            Self::MarketToLimit(order) => order.leaves_qty(),
550            Self::StopLimit(order) => order.leaves_qty(),
551            Self::StopMarket(order) => order.leaves_qty(),
552            Self::TrailingStopLimit(order) => order.leaves_qty(),
553            Self::TrailingStopMarket(order) => order.leaves_qty(),
554        }
555    }
556
557    #[must_use]
558    pub fn tags(&self) -> Option<Vec<Ustr>> {
559        match self {
560            Self::Limit(order) => order.tags.clone(),
561            Self::LimitIfTouched(order) => order.tags.clone(),
562            Self::Market(order) => order.tags.clone(),
563            Self::MarketIfTouched(order) => order.tags.clone(),
564            Self::MarketToLimit(order) => order.tags.clone(),
565            Self::StopLimit(order) => order.tags.clone(),
566            Self::StopMarket(order) => order.tags.clone(),
567            Self::TrailingStopLimit(order) => order.tags.clone(),
568            Self::TrailingStopMarket(order) => order.tags.clone(),
569        }
570    }
571
572    #[must_use]
573    pub fn emulation_trigger(&self) -> Option<TriggerType> {
574        match self {
575            Self::Limit(order) => order.emulation_trigger,
576            Self::LimitIfTouched(order) => order.emulation_trigger,
577            Self::Market(order) => order.emulation_trigger,
578            Self::MarketIfTouched(order) => order.emulation_trigger,
579            Self::MarketToLimit(order) => order.emulation_trigger,
580            Self::StopLimit(order) => order.emulation_trigger,
581            Self::StopMarket(order) => order.emulation_trigger,
582            Self::TrailingStopLimit(order) => order.emulation_trigger,
583            Self::TrailingStopMarket(order) => order.emulation_trigger,
584        }
585    }
586
587    #[must_use]
588    pub fn trigger_instrument_id(&self) -> Option<InstrumentId> {
589        match self {
590            Self::Limit(order) => order.trigger_instrument_id(),
591            Self::LimitIfTouched(order) => order.trigger_instrument_id(),
592            Self::Market(order) => order.trigger_instrument_id(),
593            Self::MarketIfTouched(order) => order.trigger_instrument_id(),
594            Self::MarketToLimit(order) => order.trigger_instrument_id(),
595            Self::StopLimit(order) => order.trigger_instrument_id(),
596            Self::StopMarket(order) => order.trigger_instrument_id(),
597            Self::TrailingStopLimit(order) => order.trigger_instrument_id(),
598            Self::TrailingStopMarket(order) => order.trigger_instrument_id(),
599        }
600    }
601
602    #[must_use]
603    pub fn avg_px(&self) -> Option<f64> {
604        match self {
605            Self::Limit(order) => order.avg_px,
606            Self::LimitIfTouched(order) => order.avg_px,
607            Self::Market(order) => order.avg_px,
608            Self::MarketIfTouched(order) => order.avg_px,
609            Self::MarketToLimit(order) => order.avg_px,
610            Self::StopLimit(order) => order.avg_px,
611            Self::StopMarket(order) => order.avg_px,
612            Self::TrailingStopLimit(order) => order.avg_px,
613            Self::TrailingStopMarket(order) => order.avg_px,
614        }
615    }
616
617    #[must_use]
618    pub fn slippage(&self) -> Option<f64> {
619        match self {
620            Self::Limit(order) => order.slippage,
621            Self::LimitIfTouched(order) => order.slippage,
622            Self::Market(order) => order.slippage,
623            Self::MarketIfTouched(order) => order.slippage,
624            Self::MarketToLimit(order) => order.slippage,
625            Self::StopLimit(order) => order.slippage,
626            Self::StopMarket(order) => order.slippage,
627            Self::TrailingStopLimit(order) => order.slippage,
628            Self::TrailingStopMarket(order) => order.slippage,
629        }
630    }
631
632    #[must_use]
633    pub fn commissions(&self) -> IndexMap<Currency, Money> {
634        match self {
635            Self::Limit(order) => order.commissions.clone(),
636            Self::LimitIfTouched(order) => order.commissions.clone(),
637            Self::Market(order) => order.commissions.clone(),
638            Self::MarketIfTouched(order) => order.commissions.clone(),
639            Self::MarketToLimit(order) => order.commissions.clone(),
640            Self::StopLimit(order) => order.commissions.clone(),
641            Self::StopMarket(order) => order.commissions.clone(),
642            Self::TrailingStopLimit(order) => order.commissions.clone(),
643            Self::TrailingStopMarket(order) => order.commissions.clone(),
644        }
645    }
646
647    #[must_use]
648    pub fn display_qty(&self) -> Option<Quantity> {
649        match self {
650            Self::Limit(order) => order.display_qty(),
651            Self::LimitIfTouched(order) => order.display_qty(),
652            Self::Market(order) => order.display_qty(),
653            Self::MarketIfTouched(order) => order.display_qty(),
654            Self::MarketToLimit(order) => order.display_qty(),
655            Self::StopLimit(order) => order.display_qty(),
656            Self::StopMarket(order) => order.display_qty(),
657            Self::TrailingStopLimit(order) => order.display_qty(),
658            Self::TrailingStopMarket(order) => order.display_qty(),
659        }
660    }
661
662    #[must_use]
663    pub fn is_buy(&self) -> bool {
664        match self {
665            Self::Limit(order) => order.is_buy(),
666            Self::LimitIfTouched(order) => order.is_buy(),
667            Self::Market(order) => order.is_buy(),
668            Self::MarketIfTouched(order) => order.is_buy(),
669            Self::MarketToLimit(order) => order.is_buy(),
670            Self::StopLimit(order) => order.is_buy(),
671            Self::StopMarket(order) => order.is_buy(),
672            Self::TrailingStopLimit(order) => order.is_buy(),
673            Self::TrailingStopMarket(order) => order.is_buy(),
674        }
675    }
676
677    #[must_use]
678    pub fn is_sell(&self) -> bool {
679        match self {
680            Self::Limit(order) => order.is_sell(),
681            Self::LimitIfTouched(order) => order.is_sell(),
682            Self::Market(order) => order.is_sell(),
683            Self::MarketIfTouched(order) => order.is_sell(),
684            Self::MarketToLimit(order) => order.is_sell(),
685            Self::StopLimit(order) => order.is_sell(),
686            Self::StopMarket(order) => order.is_sell(),
687            Self::TrailingStopLimit(order) => order.is_sell(),
688            Self::TrailingStopMarket(order) => order.is_sell(),
689        }
690    }
691
692    #[must_use]
693    pub fn is_open(&self) -> bool {
694        match self {
695            Self::Limit(order) => order.is_open(),
696            Self::LimitIfTouched(order) => order.is_open(),
697            Self::Market(order) => order.is_open(),
698            Self::MarketIfTouched(order) => order.is_open(),
699            Self::MarketToLimit(order) => order.is_open(),
700            Self::StopLimit(order) => order.is_open(),
701            Self::StopMarket(order) => order.is_open(),
702            Self::TrailingStopLimit(order) => order.is_open(),
703            Self::TrailingStopMarket(order) => order.is_open(),
704        }
705    }
706
707    #[must_use]
708    pub fn is_closed(&self) -> bool {
709        match self {
710            Self::Limit(order) => order.is_closed(),
711            Self::LimitIfTouched(order) => order.is_closed(),
712            Self::Market(order) => order.is_closed(),
713            Self::MarketIfTouched(order) => order.is_closed(),
714            Self::MarketToLimit(order) => order.is_closed(),
715            Self::StopLimit(order) => order.is_closed(),
716            Self::StopMarket(order) => order.is_closed(),
717            Self::TrailingStopLimit(order) => order.is_closed(),
718            Self::TrailingStopMarket(order) => order.is_closed(),
719        }
720    }
721
722    #[must_use]
723    pub fn is_inflight(&self) -> bool {
724        match self {
725            Self::Limit(order) => order.is_inflight(),
726            Self::LimitIfTouched(order) => order.is_inflight(),
727            Self::Market(order) => order.is_inflight(),
728            Self::MarketIfTouched(order) => order.is_inflight(),
729            Self::MarketToLimit(order) => order.is_inflight(),
730            Self::StopLimit(order) => order.is_inflight(),
731            Self::StopMarket(order) => order.is_inflight(),
732            Self::TrailingStopLimit(order) => order.is_inflight(),
733            Self::TrailingStopMarket(order) => order.is_inflight(),
734        }
735    }
736
737    pub fn is_pending_cancel(&self) -> bool {
738        match self {
739            Self::Limit(order) => order.is_pending_cancel(),
740            Self::LimitIfTouched(order) => order.is_pending_cancel(),
741            Self::Market(order) => order.is_pending_cancel(),
742            Self::MarketIfTouched(order) => order.is_pending_cancel(),
743            Self::MarketToLimit(order) => order.is_pending_cancel(),
744            Self::StopLimit(order) => order.is_pending_cancel(),
745            Self::StopMarket(order) => order.is_pending_cancel(),
746            Self::TrailingStopLimit(order) => order.is_pending_cancel(),
747            Self::TrailingStopMarket(order) => order.is_pending_cancel(),
748        }
749    }
750
751    #[must_use]
752    pub fn is_aggressive(&self) -> bool {
753        match self {
754            Self::Limit(order) => order.is_aggressive(),
755            Self::LimitIfTouched(order) => order.is_aggressive(),
756            Self::Market(order) => order.is_aggressive(),
757            Self::MarketIfTouched(order) => order.is_aggressive(),
758            Self::MarketToLimit(order) => order.is_aggressive(),
759            Self::StopLimit(order) => order.is_aggressive(),
760            Self::StopMarket(order) => order.is_aggressive(),
761            Self::TrailingStopLimit(order) => order.is_aggressive(),
762            Self::TrailingStopMarket(order) => order.is_aggressive(),
763        }
764    }
765
766    pub fn is_passive(&self) -> bool {
767        match self {
768            OrderAny::Limit(order) => order.is_passive(),
769            OrderAny::LimitIfTouched(order) => order.is_passive(),
770            OrderAny::Market(order) => order.is_passive(),
771            OrderAny::MarketIfTouched(order) => order.is_passive(),
772            OrderAny::MarketToLimit(order) => order.is_passive(),
773            OrderAny::StopLimit(order) => order.is_passive(),
774            OrderAny::StopMarket(order) => order.is_passive(),
775            OrderAny::TrailingStopLimit(order) => order.is_passive(),
776            OrderAny::TrailingStopMarket(order) => order.is_passive(),
777        }
778    }
779
780    #[must_use]
781    pub fn price(&self) -> Option<Price> {
782        match self {
783            Self::Limit(order) => Some(order.price),
784            Self::LimitIfTouched(order) => Some(order.price),
785            Self::Market(_) => None,
786            Self::MarketIfTouched(_) => None,
787            Self::MarketToLimit(order) => order.price,
788            Self::StopLimit(order) => Some(order.price),
789            Self::StopMarket(_) => None,
790            Self::TrailingStopLimit(order) => Some(order.price),
791            Self::TrailingStopMarket(_) => None,
792        }
793    }
794
795    pub fn has_price(&self) -> bool {
796        match self {
797            Self::Limit(_) => true,
798            Self::LimitIfTouched(_) => true,
799            Self::Market(_) => false,
800            Self::MarketIfTouched(_) => false,
801            Self::MarketToLimit(order) => order.price.is_some(),
802            Self::StopLimit(_) => true,
803            Self::StopMarket(_) => false,
804            Self::TrailingStopLimit(_) => true,
805            Self::TrailingStopMarket(_) => false,
806        }
807    }
808
809    #[must_use]
810    pub fn trigger_price(&self) -> Option<Price> {
811        match self {
812            Self::Limit(_) => None,
813            Self::LimitIfTouched(order) => Some(order.trigger_price),
814            Self::Market(_) => None,
815            Self::MarketIfTouched(order) => Some(order.trigger_price),
816            Self::MarketToLimit(_) => None,
817            Self::StopLimit(order) => Some(order.trigger_price),
818            Self::StopMarket(order) => Some(order.trigger_price),
819            Self::TrailingStopLimit(order) => Some(order.trigger_price),
820            Self::TrailingStopMarket(order) => Some(order.trigger_price),
821        }
822    }
823
824    #[must_use]
825    pub fn trigger_type(&self) -> Option<TriggerType> {
826        match self {
827            Self::Limit(_) => None,
828            Self::LimitIfTouched(order) => Some(order.trigger_type),
829            Self::Market(_) => None,
830            Self::MarketIfTouched(order) => Some(order.trigger_type),
831            Self::MarketToLimit(_) => None,
832            Self::StopLimit(order) => Some(order.trigger_type),
833            Self::StopMarket(order) => Some(order.trigger_type),
834            Self::TrailingStopLimit(order) => Some(order.trigger_type),
835            Self::TrailingStopMarket(order) => Some(order.trigger_type),
836        }
837    }
838
839    #[must_use]
840    pub fn limit_offset(&self) -> Option<Decimal> {
841        match self {
842            Self::Limit(_) => None,
843            Self::LimitIfTouched(_) => None,
844            Self::Market(_) => None,
845            Self::MarketIfTouched(_) => None,
846            Self::MarketToLimit(_) => None,
847            Self::StopLimit(_) => None,
848            Self::StopMarket(_) => None,
849            Self::TrailingStopLimit(order) => Some(order.limit_offset),
850            Self::TrailingStopMarket(_) => None,
851        }
852    }
853
854    #[must_use]
855    pub fn trailing_offset(&self) -> Option<Decimal> {
856        match self {
857            Self::Limit(_) => None,
858            Self::LimitIfTouched(_) => None,
859            Self::Market(_) => None,
860            Self::MarketIfTouched(_) => None,
861            Self::MarketToLimit(_) => None,
862            Self::StopLimit(_) => None,
863            Self::StopMarket(_) => None,
864            Self::TrailingStopLimit(order) => Some(order.trailing_offset),
865            Self::TrailingStopMarket(order) => Some(order.trailing_offset),
866        }
867    }
868
869    #[must_use]
870    pub fn trailing_offset_type(&self) -> Option<TrailingOffsetType> {
871        match self {
872            Self::Limit(_) => None,
873            Self::LimitIfTouched(_) => None,
874            Self::Market(_) => None,
875            Self::MarketIfTouched(_) => None,
876            Self::MarketToLimit(_) => None,
877            Self::StopLimit(_) => None,
878            Self::StopMarket(_) => None,
879            Self::TrailingStopLimit(order) => Some(order.trailing_offset_type),
880            Self::TrailingStopMarket(order) => Some(order.trailing_offset_type),
881        }
882    }
883
884    #[must_use]
885    pub fn would_reduce_only(&self, side: PositionSide, position_qty: Quantity) -> bool {
886        match self {
887            Self::Limit(order) => order.would_reduce_only(side, position_qty),
888            Self::Market(order) => order.would_reduce_only(side, position_qty),
889            Self::MarketToLimit(order) => order.would_reduce_only(side, position_qty),
890            Self::LimitIfTouched(order) => order.would_reduce_only(side, position_qty),
891            Self::MarketIfTouched(order) => order.would_reduce_only(side, position_qty),
892            Self::StopLimit(order) => order.would_reduce_only(side, position_qty),
893            Self::StopMarket(order) => order.would_reduce_only(side, position_qty),
894            Self::TrailingStopLimit(order) => order.would_reduce_only(side, position_qty),
895            Self::TrailingStopMarket(order) => order.would_reduce_only(side, position_qty),
896        }
897    }
898
899    #[must_use]
900    pub fn is_post_only(&self) -> bool {
901        match self {
902            Self::Limit(order) => order.is_post_only,
903            Self::LimitIfTouched(order) => order.is_post_only,
904            Self::Market(_) => false,
905            Self::MarketIfTouched(_) => false,
906            Self::MarketToLimit(order) => order.is_post_only,
907            Self::StopLimit(order) => order.is_post_only,
908            Self::StopMarket(_) => false,
909            Self::TrailingStopLimit(order) => order.is_post_only,
910            Self::TrailingStopMarket(_) => false,
911        }
912    }
913
914    #[must_use]
915    pub fn is_reduce_only(&self) -> bool {
916        match self {
917            Self::Limit(order) => order.is_reduce_only,
918            Self::Market(order) => order.is_reduce_only,
919            Self::MarketToLimit(order) => order.is_reduce_only,
920            Self::LimitIfTouched(order) => order.is_reduce_only,
921            Self::MarketIfTouched(order) => order.is_reduce_only,
922            Self::StopLimit(order) => order.is_reduce_only,
923            Self::StopMarket(order) => order.is_reduce_only,
924            Self::TrailingStopLimit(order) => order.is_reduce_only,
925            Self::TrailingStopMarket(order) => order.is_reduce_only,
926        }
927    }
928
929    pub fn is_quote_quantity(&self) -> bool {
930        match self {
931            Self::Limit(order) => order.is_quote_quantity(),
932            Self::LimitIfTouched(order) => order.is_quote_quantity(),
933            Self::Market(order) => order.is_quote_quantity(),
934            Self::MarketIfTouched(order) => order.is_quote_quantity(),
935            Self::MarketToLimit(order) => order.is_quote_quantity(),
936            Self::StopLimit(order) => order.is_quote_quantity(),
937            Self::StopMarket(order) => order.is_quote_quantity(),
938            Self::TrailingStopLimit(order) => order.is_quote_quantity(),
939            Self::TrailingStopMarket(order) => order.is_quote_quantity(),
940        }
941    }
942
943    pub fn is_active_local(&self) -> bool {
944        matches!(
945            self.status(),
946            OrderStatus::Initialized | OrderStatus::Emulated | OrderStatus::Released
947        )
948    }
949
950    #[must_use]
951    pub fn parent_order_id(&self) -> Option<ClientOrderId> {
952        match self {
953            Self::Limit(order) => order.parent_order_id,
954            Self::LimitIfTouched(order) => order.parent_order_id,
955            Self::Market(order) => order.parent_order_id,
956            Self::MarketIfTouched(order) => order.parent_order_id,
957            Self::MarketToLimit(order) => order.parent_order_id,
958            Self::StopLimit(order) => order.parent_order_id,
959            Self::StopMarket(order) => order.parent_order_id,
960            Self::TrailingStopLimit(order) => order.parent_order_id,
961            Self::TrailingStopMarket(order) => order.parent_order_id,
962        }
963    }
964
965    #[must_use]
966    pub fn contingency_type(&self) -> Option<ContingencyType> {
967        match self {
968            Self::Limit(order) => order.contingency_type,
969            Self::LimitIfTouched(order) => order.contingency_type,
970            Self::Market(order) => order.contingency_type,
971            Self::MarketIfTouched(order) => order.contingency_type,
972            Self::MarketToLimit(order) => order.contingency_type,
973            Self::StopLimit(order) => order.contingency_type,
974            Self::StopMarket(order) => order.contingency_type,
975            Self::TrailingStopLimit(order) => order.contingency_type,
976            Self::TrailingStopMarket(order) => order.contingency_type,
977        }
978    }
979
980    #[must_use]
981    pub fn linked_order_ids(&self) -> Option<Vec<ClientOrderId>> {
982        match self {
983            Self::Limit(order) => order.linked_order_ids.clone(),
984            Self::LimitIfTouched(order) => order.linked_order_ids.clone(),
985            Self::Market(order) => order.linked_order_ids.clone(),
986            Self::MarketIfTouched(order) => order.linked_order_ids.clone(),
987            Self::MarketToLimit(order) => order.linked_order_ids.clone(),
988            Self::StopLimit(order) => order.linked_order_ids.clone(),
989            Self::StopMarket(order) => order.linked_order_ids.clone(),
990            Self::TrailingStopLimit(order) => order.linked_order_ids.clone(),
991            Self::TrailingStopMarket(order) => order.linked_order_ids.clone(),
992        }
993    }
994
995    pub fn set_position_id(&mut self, position_id: Option<PositionId>) {
996        match self {
997            Self::Limit(order) => order.position_id = position_id,
998            Self::LimitIfTouched(order) => order.position_id = position_id,
999            Self::Market(order) => order.position_id = position_id,
1000            Self::MarketIfTouched(order) => order.position_id = position_id,
1001            Self::MarketToLimit(order) => order.position_id = position_id,
1002            Self::StopLimit(order) => order.position_id = position_id,
1003            Self::StopMarket(order) => order.position_id = position_id,
1004            Self::TrailingStopLimit(order) => order.position_id = position_id,
1005            Self::TrailingStopMarket(order) => order.position_id = position_id,
1006        }
1007    }
1008
1009    pub fn set_quantity(&mut self, quantity: Quantity) {
1010        match self {
1011            Self::Limit(order) => order.quantity = quantity,
1012            Self::LimitIfTouched(order) => order.quantity = quantity,
1013            Self::Market(order) => order.quantity = quantity,
1014            Self::MarketIfTouched(order) => order.quantity = quantity,
1015            Self::MarketToLimit(order) => order.quantity = quantity,
1016            Self::StopLimit(order) => order.quantity = quantity,
1017            Self::StopMarket(order) => order.quantity = quantity,
1018            Self::TrailingStopLimit(order) => order.quantity = quantity,
1019            Self::TrailingStopMarket(order) => order.quantity = quantity,
1020        }
1021    }
1022
1023    pub fn set_leaves_qty(&mut self, leaves_qty: Quantity) {
1024        match self {
1025            Self::Limit(order) => order.leaves_qty = leaves_qty,
1026            Self::LimitIfTouched(order) => order.leaves_qty = leaves_qty,
1027            Self::Market(order) => order.leaves_qty = leaves_qty,
1028            Self::MarketIfTouched(order) => order.leaves_qty = leaves_qty,
1029            Self::MarketToLimit(order) => order.leaves_qty = leaves_qty,
1030            Self::StopLimit(order) => order.leaves_qty = leaves_qty,
1031            Self::StopMarket(order) => order.leaves_qty = leaves_qty,
1032            Self::TrailingStopLimit(order) => order.leaves_qty = leaves_qty,
1033            Self::TrailingStopMarket(order) => order.leaves_qty = leaves_qty,
1034        }
1035    }
1036
1037    pub fn set_emulation_trigger(&mut self, emulation_trigger: Option<TriggerType>) {
1038        match self {
1039            Self::Limit(order) => order.emulation_trigger = emulation_trigger,
1040            Self::LimitIfTouched(order) => order.emulation_trigger = emulation_trigger,
1041            Self::Market(order) => order.emulation_trigger = emulation_trigger,
1042            Self::MarketIfTouched(order) => order.emulation_trigger = emulation_trigger,
1043            Self::MarketToLimit(order) => order.emulation_trigger = emulation_trigger,
1044            Self::StopLimit(order) => order.emulation_trigger = emulation_trigger,
1045            Self::StopMarket(order) => order.emulation_trigger = emulation_trigger,
1046            Self::TrailingStopLimit(order) => order.emulation_trigger = emulation_trigger,
1047            Self::TrailingStopMarket(order) => order.emulation_trigger = emulation_trigger,
1048        };
1049    }
1050
1051    pub fn set_is_quote_quantity(&mut self, is_quote_quantity: bool) {
1052        match self {
1053            Self::Limit(order) => order.is_quote_quantity = is_quote_quantity,
1054            Self::LimitIfTouched(order) => order.is_quote_quantity = is_quote_quantity,
1055            Self::Market(order) => order.is_quote_quantity = is_quote_quantity,
1056            Self::MarketIfTouched(order) => order.is_quote_quantity = is_quote_quantity,
1057            Self::MarketToLimit(order) => order.is_quote_quantity = is_quote_quantity,
1058            Self::StopLimit(order) => order.is_quote_quantity = is_quote_quantity,
1059            Self::StopMarket(order) => order.is_quote_quantity = is_quote_quantity,
1060            Self::TrailingStopLimit(order) => order.is_quote_quantity = is_quote_quantity,
1061            Self::TrailingStopMarket(order) => order.is_quote_quantity = is_quote_quantity,
1062        }
1063    }
1064
1065    pub fn set_liquidity_side(&mut self, liquidity_side: LiquiditySide) {
1066        match self {
1067            Self::Limit(order) => order.liquidity_side = Some(liquidity_side),
1068            Self::LimitIfTouched(order) => order.liquidity_side = Some(liquidity_side),
1069            Self::Market(order) => order.liquidity_side = Some(liquidity_side),
1070            Self::MarketIfTouched(order) => order.liquidity_side = Some(liquidity_side),
1071            Self::MarketToLimit(order) => order.liquidity_side = Some(liquidity_side),
1072            Self::StopLimit(order) => order.liquidity_side = Some(liquidity_side),
1073            Self::StopMarket(order) => order.liquidity_side = Some(liquidity_side),
1074            Self::TrailingStopLimit(order) => order.liquidity_side = Some(liquidity_side),
1075            Self::TrailingStopMarket(order) => order.liquidity_side = Some(liquidity_side),
1076        }
1077    }
1078}
1079
1080impl PartialEq for OrderAny {
1081    fn eq(&self, other: &Self) -> bool {
1082        self.client_order_id() == other.client_order_id()
1083    }
1084}
1085
1086// TODO: fix equality
1087impl Eq for OrderAny {}
1088
1089impl Display for OrderAny {
1090    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1091        write!(
1092            f,
1093            "{}",
1094            match self {
1095                Self::Limit(order) => order.to_string(),
1096                Self::LimitIfTouched(order) => format!("{:?}", order), // TODO: Implement
1097                Self::Market(order) => order.to_string(),
1098                Self::MarketIfTouched(order) => format!("{:?}", order), // TODO: Implement
1099                Self::MarketToLimit(order) => format!("{:?}", order),   // TODO: Implement
1100                Self::StopLimit(order) => order.to_string(),
1101                Self::StopMarket(order) => format!("{:?}", order), // TODO: Implement
1102                Self::TrailingStopLimit(order) => format!("{:?}", order), // TODO: Implement
1103                Self::TrailingStopMarket(order) => format!("{:?}", order), // TODO: Implement
1104            }
1105        )
1106    }
1107}
1108
1109impl From<OrderAny> for PassiveOrderAny {
1110    fn from(order: OrderAny) -> PassiveOrderAny {
1111        match order {
1112            OrderAny::Limit(_) => PassiveOrderAny::Limit(order.into()),
1113            OrderAny::LimitIfTouched(_) => PassiveOrderAny::Stop(order.into()),
1114            OrderAny::MarketIfTouched(_) => PassiveOrderAny::Stop(order.into()),
1115            OrderAny::StopLimit(_) => PassiveOrderAny::Stop(order.into()),
1116            OrderAny::StopMarket(_) => PassiveOrderAny::Stop(order.into()),
1117            OrderAny::TrailingStopLimit(_) => PassiveOrderAny::Stop(order.into()),
1118            OrderAny::TrailingStopMarket(_) => PassiveOrderAny::Stop(order.into()),
1119            _ => panic!("WIP: Implement trait bound to require `HasPrice`"),
1120        }
1121    }
1122}
1123
1124impl From<PassiveOrderAny> for OrderAny {
1125    fn from(order: PassiveOrderAny) -> OrderAny {
1126        match order {
1127            PassiveOrderAny::Limit(order) => order.into(),
1128            PassiveOrderAny::Stop(order) => order.into(),
1129        }
1130    }
1131}
1132
1133impl From<StopOrderAny> for PassiveOrderAny {
1134    fn from(order: StopOrderAny) -> PassiveOrderAny {
1135        match order {
1136            StopOrderAny::LimitIfTouched(_) => PassiveOrderAny::Stop(order),
1137            StopOrderAny::MarketIfTouched(_) => PassiveOrderAny::Stop(order),
1138            StopOrderAny::StopLimit(_) => PassiveOrderAny::Stop(order),
1139            StopOrderAny::StopMarket(_) => PassiveOrderAny::Stop(order),
1140            StopOrderAny::TrailingStopLimit(_) => PassiveOrderAny::Stop(order),
1141            StopOrderAny::TrailingStopMarket(_) => PassiveOrderAny::Stop(order),
1142        }
1143    }
1144}
1145
1146impl From<LimitOrderAny> for PassiveOrderAny {
1147    fn from(order: LimitOrderAny) -> PassiveOrderAny {
1148        match order {
1149            LimitOrderAny::Limit(_) => PassiveOrderAny::Limit(order),
1150            LimitOrderAny::MarketToLimit(_) => PassiveOrderAny::Limit(order),
1151            LimitOrderAny::StopLimit(_) => PassiveOrderAny::Limit(order),
1152            LimitOrderAny::TrailingStopLimit(_) => PassiveOrderAny::Limit(order),
1153        }
1154    }
1155}
1156
1157impl From<OrderAny> for StopOrderAny {
1158    fn from(order: OrderAny) -> StopOrderAny {
1159        match order {
1160            OrderAny::LimitIfTouched(order) => StopOrderAny::LimitIfTouched(order),
1161            OrderAny::MarketIfTouched(order) => StopOrderAny::MarketIfTouched(order),
1162            OrderAny::StopLimit(order) => StopOrderAny::StopLimit(order),
1163            OrderAny::StopMarket(order) => StopOrderAny::StopMarket(order),
1164            OrderAny::TrailingStopLimit(order) => StopOrderAny::TrailingStopLimit(order),
1165            OrderAny::TrailingStopMarket(order) => StopOrderAny::TrailingStopMarket(order),
1166            _ => panic!("WIP: Implement trait bound to require `HasStopPrice`"),
1167        }
1168    }
1169}
1170
1171impl From<StopOrderAny> for OrderAny {
1172    fn from(order: StopOrderAny) -> OrderAny {
1173        match order {
1174            StopOrderAny::LimitIfTouched(order) => OrderAny::LimitIfTouched(order),
1175            StopOrderAny::MarketIfTouched(order) => OrderAny::MarketIfTouched(order),
1176            StopOrderAny::StopLimit(order) => OrderAny::StopLimit(order),
1177            StopOrderAny::StopMarket(order) => OrderAny::StopMarket(order),
1178            StopOrderAny::TrailingStopLimit(order) => OrderAny::TrailingStopLimit(order),
1179            StopOrderAny::TrailingStopMarket(order) => OrderAny::TrailingStopMarket(order),
1180        }
1181    }
1182}
1183
1184impl From<OrderAny> for LimitOrderAny {
1185    fn from(order: OrderAny) -> LimitOrderAny {
1186        match order {
1187            OrderAny::Limit(order) => LimitOrderAny::Limit(order),
1188            OrderAny::MarketToLimit(order) => LimitOrderAny::MarketToLimit(order),
1189            OrderAny::StopLimit(order) => LimitOrderAny::StopLimit(order),
1190            OrderAny::TrailingStopLimit(order) => LimitOrderAny::TrailingStopLimit(order),
1191            _ => panic!("WIP: Implement trait bound to require `HasLimitPrice`"),
1192        }
1193    }
1194}
1195
1196impl From<LimitOrderAny> for OrderAny {
1197    fn from(order: LimitOrderAny) -> OrderAny {
1198        match order {
1199            LimitOrderAny::Limit(order) => OrderAny::Limit(order),
1200            LimitOrderAny::MarketToLimit(order) => OrderAny::MarketToLimit(order),
1201            LimitOrderAny::StopLimit(order) => OrderAny::StopLimit(order),
1202            LimitOrderAny::TrailingStopLimit(order) => OrderAny::TrailingStopLimit(order),
1203        }
1204    }
1205}
1206
1207impl AsRef<StopMarketOrder> for OrderAny {
1208    fn as_ref(&self) -> &StopMarketOrder {
1209        match self {
1210            OrderAny::StopMarket(ref order) => order,
1211            _ => panic!(
1212                "Invalid `OrderAny` not `{}`, was {self:?}",
1213                stringify!(StopMarketOrder),
1214            ),
1215        }
1216    }
1217}
1218
1219#[derive(Clone, Debug)]
1220pub enum PassiveOrderAny {
1221    Limit(LimitOrderAny),
1222    Stop(StopOrderAny),
1223}
1224
1225impl PassiveOrderAny {
1226    #[must_use]
1227    pub fn client_order_id(&self) -> ClientOrderId {
1228        match self {
1229            Self::Limit(order) => order.client_order_id(),
1230            Self::Stop(order) => order.client_order_id(),
1231        }
1232    }
1233
1234    #[must_use]
1235    pub fn order_side_specified(&self) -> OrderSideSpecified {
1236        match self {
1237            Self::Limit(order) => order.order_side_specified(),
1238            Self::Stop(order) => order.order_side_specified(),
1239        }
1240    }
1241
1242    #[must_use]
1243    pub fn is_closed(&self) -> bool {
1244        match self {
1245            Self::Limit(order) => order.is_closed(),
1246            Self::Stop(order) => order.is_closed(),
1247        }
1248    }
1249
1250    #[must_use]
1251    pub fn is_open(&self) -> bool {
1252        match self {
1253            Self::Limit(order) => order.is_open(),
1254            Self::Stop(order) => order.is_open(),
1255        }
1256    }
1257
1258    #[must_use]
1259    pub fn is_inflight(&self) -> bool {
1260        match self {
1261            Self::Limit(order) => order.is_inflight(),
1262            Self::Stop(order) => order.is_inflight(),
1263        }
1264    }
1265
1266    #[must_use]
1267    pub fn expire_time(&self) -> Option<UnixNanos> {
1268        match self {
1269            Self::Limit(order) => order.expire_time(),
1270            Self::Stop(order) => order.expire_time(),
1271        }
1272    }
1273
1274    #[must_use]
1275    pub fn contingency_type(&self) -> Option<ContingencyType> {
1276        match self {
1277            Self::Limit(order) => order.contingency_type(),
1278            Self::Stop(order) => order.contingency_type(),
1279        }
1280    }
1281
1282    #[must_use]
1283    pub fn to_any(&self) -> OrderAny {
1284        match self {
1285            Self::Limit(order) => order.clone().into(),
1286            Self::Stop(order) => order.clone().into(),
1287        }
1288    }
1289}
1290
1291impl PartialEq for PassiveOrderAny {
1292    fn eq(&self, rhs: &Self) -> bool {
1293        match self {
1294            Self::Limit(order) => order.client_order_id() == rhs.client_order_id(),
1295            Self::Stop(order) => order.client_order_id() == rhs.client_order_id(),
1296        }
1297    }
1298}
1299
1300#[derive(Clone, Debug)]
1301pub enum LimitOrderAny {
1302    Limit(LimitOrder),
1303    MarketToLimit(MarketToLimitOrder),
1304    StopLimit(StopLimitOrder),
1305    TrailingStopLimit(TrailingStopLimitOrder),
1306}
1307
1308impl LimitOrderAny {
1309    #[must_use]
1310    pub fn client_order_id(&self) -> ClientOrderId {
1311        match self {
1312            Self::Limit(order) => order.client_order_id,
1313            Self::MarketToLimit(order) => order.client_order_id,
1314            Self::StopLimit(order) => order.client_order_id,
1315            Self::TrailingStopLimit(order) => order.client_order_id,
1316        }
1317    }
1318
1319    #[must_use]
1320    pub fn order_side_specified(&self) -> OrderSideSpecified {
1321        match self {
1322            Self::Limit(order) => order.side.as_specified(),
1323            Self::MarketToLimit(order) => order.side.as_specified(),
1324            Self::StopLimit(order) => order.side.as_specified(),
1325            Self::TrailingStopLimit(order) => order.side.as_specified(),
1326        }
1327    }
1328
1329    #[must_use]
1330    pub fn limit_px(&self) -> Price {
1331        match self {
1332            Self::Limit(order) => order.price,
1333            Self::MarketToLimit(order) => order.price.expect("No price for order"), // TBD
1334            Self::StopLimit(order) => order.price,
1335            Self::TrailingStopLimit(order) => order.price,
1336        }
1337    }
1338
1339    #[must_use]
1340    pub fn is_closed(&self) -> bool {
1341        match self {
1342            Self::Limit(order) => order.is_closed(),
1343            Self::MarketToLimit(order) => order.is_closed(),
1344            Self::StopLimit(order) => order.is_closed(),
1345            Self::TrailingStopLimit(order) => order.is_closed(),
1346        }
1347    }
1348
1349    #[must_use]
1350    pub fn is_open(&self) -> bool {
1351        match self {
1352            Self::Limit(order) => order.is_open(),
1353            Self::MarketToLimit(order) => order.is_open(),
1354            Self::StopLimit(order) => order.is_open(),
1355            Self::TrailingStopLimit(order) => order.is_open(),
1356        }
1357    }
1358
1359    #[must_use]
1360    pub fn is_inflight(&self) -> bool {
1361        match self {
1362            Self::Limit(order) => order.is_inflight(),
1363            Self::MarketToLimit(order) => order.is_inflight(),
1364            Self::StopLimit(order) => order.is_inflight(),
1365            Self::TrailingStopLimit(order) => order.is_inflight(),
1366        }
1367    }
1368
1369    #[must_use]
1370    pub fn expire_time(&self) -> Option<UnixNanos> {
1371        match self {
1372            Self::Limit(order) => order.expire_time,
1373            Self::MarketToLimit(order) => order.expire_time,
1374            Self::StopLimit(order) => order.expire_time,
1375            Self::TrailingStopLimit(order) => order.expire_time,
1376        }
1377    }
1378
1379    #[must_use]
1380    pub fn contingency_type(&self) -> Option<ContingencyType> {
1381        match self {
1382            Self::Limit(order) => order.contingency_type,
1383            Self::MarketToLimit(order) => order.contingency_type,
1384            Self::StopLimit(order) => order.contingency_type,
1385            Self::TrailingStopLimit(order) => order.contingency_type,
1386        }
1387    }
1388}
1389
1390impl PartialEq for LimitOrderAny {
1391    fn eq(&self, rhs: &Self) -> bool {
1392        match self {
1393            Self::Limit(order) => order.client_order_id == rhs.client_order_id(),
1394            Self::MarketToLimit(order) => order.client_order_id == rhs.client_order_id(),
1395            Self::StopLimit(order) => order.client_order_id == rhs.client_order_id(),
1396            Self::TrailingStopLimit(order) => order.client_order_id == rhs.client_order_id(),
1397        }
1398    }
1399}
1400
1401#[derive(Clone, Debug)]
1402pub enum StopOrderAny {
1403    LimitIfTouched(LimitIfTouchedOrder),
1404    MarketIfTouched(MarketIfTouchedOrder),
1405    StopLimit(StopLimitOrder),
1406    StopMarket(StopMarketOrder),
1407    TrailingStopLimit(TrailingStopLimitOrder),
1408    TrailingStopMarket(TrailingStopMarketOrder),
1409}
1410
1411impl StopOrderAny {
1412    #[must_use]
1413    pub fn client_order_id(&self) -> ClientOrderId {
1414        match self {
1415            Self::LimitIfTouched(order) => order.client_order_id,
1416            Self::MarketIfTouched(order) => order.client_order_id,
1417            Self::StopLimit(order) => order.client_order_id,
1418            Self::StopMarket(order) => order.client_order_id,
1419            Self::TrailingStopLimit(order) => order.client_order_id,
1420            Self::TrailingStopMarket(order) => order.client_order_id,
1421        }
1422    }
1423
1424    #[must_use]
1425    pub fn order_side_specified(&self) -> OrderSideSpecified {
1426        match self {
1427            Self::LimitIfTouched(order) => order.side.as_specified(),
1428            Self::MarketIfTouched(order) => order.side.as_specified(),
1429            Self::StopLimit(order) => order.side.as_specified(),
1430            Self::StopMarket(order) => order.side.as_specified(),
1431            Self::TrailingStopLimit(order) => order.side.as_specified(),
1432            Self::TrailingStopMarket(order) => order.side.as_specified(),
1433        }
1434    }
1435
1436    #[must_use]
1437    pub fn stop_px(&self) -> Price {
1438        match self {
1439            Self::LimitIfTouched(order) => order.trigger_price,
1440            Self::MarketIfTouched(order) => order.trigger_price,
1441            Self::StopLimit(order) => order.trigger_price,
1442            Self::StopMarket(order) => order.trigger_price,
1443            Self::TrailingStopLimit(order) => order.trigger_price,
1444            Self::TrailingStopMarket(order) => order.trigger_price,
1445        }
1446    }
1447
1448    #[must_use]
1449    pub fn is_closed(&self) -> bool {
1450        match self {
1451            Self::LimitIfTouched(order) => order.is_closed(),
1452            Self::MarketIfTouched(order) => order.is_closed(),
1453            Self::StopLimit(order) => order.is_closed(),
1454            Self::StopMarket(order) => order.is_closed(),
1455            Self::TrailingStopLimit(order) => order.is_closed(),
1456            Self::TrailingStopMarket(order) => order.is_closed(),
1457        }
1458    }
1459
1460    #[must_use]
1461    pub fn is_open(&self) -> bool {
1462        match self {
1463            Self::LimitIfTouched(order) => order.is_open(),
1464            Self::MarketIfTouched(order) => order.is_open(),
1465            Self::StopLimit(order) => order.is_open(),
1466            Self::StopMarket(order) => order.is_open(),
1467            Self::TrailingStopLimit(order) => order.is_open(),
1468            Self::TrailingStopMarket(order) => order.is_open(),
1469        }
1470    }
1471
1472    #[must_use]
1473    pub fn is_inflight(&self) -> bool {
1474        match self {
1475            Self::LimitIfTouched(order) => order.is_inflight(),
1476            Self::MarketIfTouched(order) => order.is_inflight(),
1477            Self::StopLimit(order) => order.is_inflight(),
1478            Self::StopMarket(order) => order.is_inflight(),
1479            Self::TrailingStopLimit(order) => order.is_inflight(),
1480            Self::TrailingStopMarket(order) => order.is_inflight(),
1481        }
1482    }
1483
1484    #[must_use]
1485    pub fn expire_time(&self) -> Option<UnixNanos> {
1486        match self {
1487            Self::LimitIfTouched(order) => order.expire_time,
1488            Self::MarketIfTouched(order) => order.expire_time,
1489            Self::StopLimit(order) => order.expire_time,
1490            Self::StopMarket(order) => order.expire_time,
1491            Self::TrailingStopLimit(order) => order.expire_time,
1492            Self::TrailingStopMarket(order) => order.expire_time,
1493        }
1494    }
1495
1496    #[must_use]
1497    pub fn contingency_type(&self) -> Option<ContingencyType> {
1498        match self {
1499            Self::LimitIfTouched(order) => order.contingency_type,
1500            Self::MarketIfTouched(order) => order.contingency_type,
1501            Self::StopLimit(order) => order.contingency_type,
1502            Self::StopMarket(order) => order.contingency_type,
1503            Self::TrailingStopLimit(order) => order.contingency_type,
1504            Self::TrailingStopMarket(order) => order.contingency_type,
1505        }
1506    }
1507}
1508
1509impl PartialEq for StopOrderAny {
1510    fn eq(&self, rhs: &Self) -> bool {
1511        match self {
1512            Self::LimitIfTouched(order) => order.client_order_id == rhs.client_order_id(),
1513            Self::StopLimit(order) => order.client_order_id == rhs.client_order_id(),
1514            Self::StopMarket(order) => order.client_order_id == rhs.client_order_id(),
1515            Self::MarketIfTouched(order) => order.client_order_id == rhs.client_order_id(),
1516            Self::TrailingStopLimit(order) => order.client_order_id == rhs.client_order_id(),
1517            Self::TrailingStopMarket(order) => order.client_order_id == rhs.client_order_id(),
1518        }
1519    }
1520}