nautilus_model/
enums.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
16//! Enumerations for the trading domain model.
17
18use std::str::FromStr;
19
20use serde::{Deserialize, Deserializer, Serialize, Serializer};
21use strum::{AsRefStr, Display, EnumIter, EnumString, FromRepr};
22
23use crate::enum_strum_serde;
24
25/// Provides conversion from a `u8` value to an enum type.
26pub trait FromU8 {
27    /// Converts a `u8` value to the implementing type.
28    ///
29    /// Returns `None` if the value is not a valid representation.
30    fn from_u8(value: u8) -> Option<Self>
31    where
32        Self: Sized;
33}
34
35/// Provides conversion from a `u16` value to an enum type.
36pub trait FromU16 {
37    /// Converts a `u16` value to the implementing type.
38    ///
39    /// Returns `None` if the value is not a valid representation.
40    fn from_u16(value: u16) -> Option<Self>
41    where
42        Self: Sized;
43}
44
45/// An account type provided by a trading venue or broker.
46#[repr(C)]
47#[derive(
48    Copy,
49    Clone,
50    Debug,
51    Display,
52    Hash,
53    PartialEq,
54    Eq,
55    PartialOrd,
56    Ord,
57    AsRefStr,
58    FromRepr,
59    EnumIter,
60    EnumString,
61)]
62#[strum(ascii_case_insensitive)]
63#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
64#[cfg_attr(
65    feature = "python",
66    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
67)]
68pub enum AccountType {
69    /// An account with unleveraged cash assets only.
70    Cash = 1,
71    /// An account which facilitates trading on margin, using account assets as collateral.
72    Margin = 2,
73    /// An account specific to betting markets.
74    Betting = 3,
75}
76
77/// An aggregation source for derived data.
78#[repr(C)]
79#[derive(
80    Copy,
81    Clone,
82    Debug,
83    Display,
84    Hash,
85    PartialEq,
86    Eq,
87    PartialOrd,
88    Ord,
89    AsRefStr,
90    FromRepr,
91    EnumIter,
92    EnumString,
93)]
94#[strum(ascii_case_insensitive)]
95#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
96#[cfg_attr(
97    feature = "python",
98    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
99)]
100pub enum AggregationSource {
101    /// The data is externally aggregated (outside the Nautilus system boundary).
102    External = 1,
103    /// The data is internally aggregated (inside the Nautilus system boundary).
104    Internal = 2,
105}
106
107/// The side for the aggressing order of a trade in a market.
108#[repr(C)]
109#[derive(
110    Copy,
111    Clone,
112    Debug,
113    Default,
114    Display,
115    Hash,
116    PartialEq,
117    Eq,
118    PartialOrd,
119    Ord,
120    AsRefStr,
121    FromRepr,
122    EnumIter,
123    EnumString,
124)]
125#[strum(ascii_case_insensitive)]
126#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
127#[cfg_attr(
128    feature = "python",
129    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
130)]
131pub enum AggressorSide {
132    /// There was no specific aggressor for the trade.
133    #[default]
134    NoAggressor = 0,
135    /// The BUY order was the aggressor for the trade.
136    Buyer = 1,
137    /// The SELL order was the aggressor for the trade.
138    Seller = 2,
139}
140
141impl FromU8 for AggressorSide {
142    fn from_u8(value: u8) -> Option<Self> {
143        match value {
144            0 => Some(Self::NoAggressor),
145            1 => Some(Self::Buyer),
146            2 => Some(Self::Seller),
147            _ => None,
148        }
149    }
150}
151
152/// A broad financial market asset class.
153#[repr(C)]
154#[derive(
155    Copy,
156    Clone,
157    Debug,
158    Display,
159    Hash,
160    PartialEq,
161    Eq,
162    PartialOrd,
163    Ord,
164    AsRefStr,
165    FromRepr,
166    EnumIter,
167    EnumString,
168)]
169#[strum(ascii_case_insensitive)]
170#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
171#[cfg_attr(
172    feature = "python",
173    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
174)]
175#[allow(non_camel_case_types)]
176pub enum AssetClass {
177    /// Foreign exchange (FOREX) assets.
178    FX = 1,
179    /// Equity / stock assets.
180    Equity = 2,
181    /// Commodity assets.
182    Commodity = 3,
183    /// Debt based assets.
184    Debt = 4,
185    /// Index based assets (baskets).
186    Index = 5,
187    /// Cryptocurrency or crypto token assets.
188    Cryptocurrency = 6,
189    /// Alternative assets.
190    Alternative = 7,
191}
192
193impl FromU8 for AssetClass {
194    fn from_u8(value: u8) -> Option<Self> {
195        match value {
196            1 => Some(Self::FX),
197            2 => Some(Self::Equity),
198            3 => Some(Self::Commodity),
199            4 => Some(Self::Debt),
200            5 => Some(Self::Index),
201            6 => Some(Self::Cryptocurrency),
202            7 => Some(Self::Alternative),
203            _ => None,
204        }
205    }
206}
207
208/// The instrument class.
209#[repr(C)]
210#[derive(
211    Copy,
212    Clone,
213    Debug,
214    Display,
215    Hash,
216    PartialEq,
217    Eq,
218    PartialOrd,
219    Ord,
220    AsRefStr,
221    FromRepr,
222    EnumIter,
223    EnumString,
224)]
225#[strum(ascii_case_insensitive)]
226#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
227#[cfg_attr(
228    feature = "python",
229    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
230)]
231pub enum InstrumentClass {
232    /// A spot market instrument class. The current market price of an instrument that is bought or sold for immediate delivery and payment.
233    Spot = 1,
234    /// A swap instrument class. A derivative contract through which two parties exchange the cash flows or liabilities from two different financial instruments.
235    Swap = 2,
236    /// A futures contract instrument class. A legal agreement to buy or sell an asset at a predetermined price at a specified time in the future.
237    Future = 3,
238    /// A futures spread instrument class. A strategy involving the use of futures contracts to take advantage of price differentials between different contract months, underlying assets, or marketplaces.
239    FuturesSpread = 4,
240    /// A forward derivative instrument class. A customized contract between two parties to buy or sell an asset at a specified price on a future date.
241    Forward = 5,
242    /// A contract-for-difference (CFD) instrument class. A contract between an investor and a CFD broker to exchange the difference in the value of a financial product between the time the contract opens and closes.
243    Cfd = 6,
244    /// A bond instrument class. A type of debt investment where an investor loans money to an entity (typically corporate or governmental) which borrows the funds for a defined period of time at a variable or fixed interest rate.
245    Bond = 7,
246    /// An option contract instrument class. A type of derivative that gives the holder the right, but not the obligation, to buy or sell an underlying asset at a predetermined price before or at a certain future date.
247    Option = 8,
248    /// An option spread instrument class. A strategy involving the purchase and/or sale of multiple option contracts on the same underlying asset with different strike prices or expiration dates to hedge risk or speculate on price movements.
249    OptionSpread = 9,
250    /// A warrant instrument class. A derivative that gives the holder the right, but not the obligation, to buy or sell a security—most commonly an equity—at a certain price before expiration.
251    Warrant = 10,
252    /// A sports betting instrument class. A financialized derivative that allows wagering on the outcome of sports events using structured contracts or prediction markets.
253    SportsBetting = 11,
254    /// A binary option instrument class. A type of derivative where the payoff is either a fixed monetary amount or nothing, depending on whether the price of an underlying asset is above or below a predetermined level at expiration.
255    /// A binary option instrument class. A type of derivative where the payoff is either a fixed monetary amount or nothing, based on a yes/no proposition about an underlying event.
256    BinaryOption = 12,
257}
258
259/// The aggregation method through which a bar is generated and closed.
260#[repr(C)]
261#[derive(
262    Copy,
263    Clone,
264    Debug,
265    Display,
266    Hash,
267    PartialEq,
268    Eq,
269    PartialOrd,
270    Ord,
271    AsRefStr,
272    FromRepr,
273    EnumIter,
274    EnumString,
275)]
276#[strum(ascii_case_insensitive)]
277#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
278#[cfg_attr(
279    feature = "python",
280    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
281)]
282pub enum BarAggregation {
283    /// Based on a number of ticks.
284    Tick = 1,
285    /// Based on the buy/sell imbalance of ticks.
286    TickImbalance = 2,
287    /// Based on sequential buy/sell runs of ticks.
288    TickRuns = 3,
289    /// Based on traded volume.
290    Volume = 4,
291    /// Based on the buy/sell imbalance of traded volume.
292    VolumeImbalance = 5,
293    /// Based on sequential runs of buy/sell traded volume.
294    VolumeRuns = 6,
295    /// Based on the 'notional' value of the instrument.
296    Value = 7,
297    /// Based on the buy/sell imbalance of trading by notional value.
298    ValueImbalance = 8,
299    /// Based on sequential buy/sell runs of trading by notional value.
300    ValueRuns = 9,
301    /// Based on time intervals with millisecond granularity.
302    Millisecond = 10,
303    /// Based on time intervals with second granularity.
304    Second = 11,
305    /// Based on time intervals with minute granularity.
306    Minute = 12,
307    /// Based on time intervals with hour granularity.
308    Hour = 13,
309    /// Based on time intervals with day granularity.
310    Day = 14,
311    /// Based on time intervals with week granularity.
312    Week = 15,
313    /// Based on time intervals with month granularity.
314    Month = 16,
315    /// Based on time intervals with year granularity.
316    Year = 17,
317}
318
319/// The interval type for bar aggregation.
320#[repr(C)]
321#[derive(
322    Copy,
323    Clone,
324    Debug,
325    Default,
326    Display,
327    Hash,
328    PartialEq,
329    Eq,
330    PartialOrd,
331    Ord,
332    AsRefStr,
333    FromRepr,
334    EnumIter,
335    EnumString,
336)]
337#[strum(ascii_case_insensitive)]
338#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
339#[cfg_attr(
340    feature = "python",
341    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
342)]
343pub enum BarIntervalType {
344    /// Left-open interval `(start, end]`: start is exclusive, end is inclusive (default).
345    #[default]
346    LeftOpen = 1,
347    /// Right-open interval `[start, end)`: start is inclusive, end is exclusive.
348    RightOpen = 2,
349}
350
351/// Represents the side of a bet in a betting market.
352#[repr(C)]
353#[derive(
354    Copy,
355    Clone,
356    Debug,
357    Display,
358    Hash,
359    PartialEq,
360    Eq,
361    PartialOrd,
362    Ord,
363    AsRefStr,
364    FromRepr,
365    EnumIter,
366    EnumString,
367)]
368#[strum(ascii_case_insensitive)]
369#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
370#[cfg_attr(
371    feature = "python",
372    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
373)]
374pub enum BetSide {
375    /// A "Back" bet signifies support for a specific outcome.
376    Back = 1,
377    /// A "Lay" bet signifies opposition to a specific outcome.
378    Lay = 2,
379}
380
381impl BetSide {
382    /// Returns the opposite betting side.
383    #[must_use]
384    pub fn opposite(&self) -> Self {
385        match self {
386            Self::Back => Self::Lay,
387            Self::Lay => Self::Back,
388        }
389    }
390}
391
392impl From<OrderSide> for BetSide {
393    /// Returns the equivalent [`BetSide`] for a given [`OrderSide`].
394    ///
395    /// # Panics
396    ///
397    /// Panics if `side` is [`OrderSide::NoOrderSide`].
398    fn from(side: OrderSide) -> Self {
399        match side {
400            OrderSide::Buy => BetSide::Back,
401            OrderSide::Sell => BetSide::Lay,
402            OrderSide::NoOrderSide => panic!("Invalid `OrderSide` for `BetSide`, was {side}"),
403        }
404    }
405}
406
407/// The type of order book action for an order book event.
408#[repr(C)]
409#[derive(
410    Copy,
411    Clone,
412    Debug,
413    Display,
414    Hash,
415    PartialEq,
416    Eq,
417    PartialOrd,
418    Ord,
419    AsRefStr,
420    FromRepr,
421    EnumIter,
422    EnumString,
423)]
424#[strum(ascii_case_insensitive)]
425#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
426#[cfg_attr(
427    feature = "python",
428    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
429)]
430pub enum BookAction {
431    /// An order is added to the book.
432    Add = 1,
433    /// An existing order in the book is updated/modified.
434    Update = 2,
435    /// An existing order in the book is deleted/canceled.
436    Delete = 3,
437    /// The state of the order book is cleared.
438    Clear = 4,
439}
440
441impl FromU8 for BookAction {
442    fn from_u8(value: u8) -> Option<Self> {
443        match value {
444            1 => Some(Self::Add),
445            2 => Some(Self::Update),
446            3 => Some(Self::Delete),
447            4 => Some(Self::Clear),
448            _ => None,
449        }
450    }
451}
452
453/// The order book type, representing the type of levels granularity and delta updating heuristics.
454#[repr(C)]
455#[derive(
456    Copy,
457    Clone,
458    Debug,
459    Display,
460    Hash,
461    PartialEq,
462    Eq,
463    PartialOrd,
464    Ord,
465    AsRefStr,
466    FromRepr,
467    EnumIter,
468    EnumString,
469)]
470#[strum(ascii_case_insensitive)]
471#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
472#[allow(non_camel_case_types)]
473#[cfg_attr(
474    feature = "python",
475    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
476)]
477pub enum BookType {
478    /// Top-of-book best bid/ask, one level per side.
479    L1_MBP = 1,
480    /// Market by price, one order per level (aggregated).
481    L2_MBP = 2,
482    /// Market by order, multiple orders per level (full granularity).
483    L3_MBO = 3,
484}
485
486impl FromU8 for BookType {
487    fn from_u8(value: u8) -> Option<Self> {
488        match value {
489            1 => Some(Self::L1_MBP),
490            2 => Some(Self::L2_MBP),
491            3 => Some(Self::L3_MBO),
492            _ => None,
493        }
494    }
495}
496
497/// The order contigency type which specifies the behavior of linked orders.
498///
499/// [FIX 5.0 SP2 : ContingencyType <1385> field](https://www.onixs.biz/fix-dictionary/5.0.sp2/tagnum_1385.html).
500#[repr(C)]
501#[derive(
502    Copy,
503    Clone,
504    Debug,
505    Default,
506    Display,
507    Hash,
508    PartialEq,
509    Eq,
510    PartialOrd,
511    Ord,
512    AsRefStr,
513    FromRepr,
514    EnumIter,
515    EnumString,
516)]
517#[strum(ascii_case_insensitive)]
518#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
519#[cfg_attr(
520    feature = "python",
521    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
522)]
523pub enum ContingencyType {
524    /// Not a contingent order.
525    #[default]
526    NoContingency = 0,
527    /// One-Cancels-the-Other.
528    Oco = 1,
529    /// One-Triggers-the-Other.
530    Oto = 2,
531    /// One-Updates-the-Other (by proportional quantity).
532    Ouo = 3,
533}
534
535/// The broad currency type.
536#[repr(C)]
537#[derive(
538    Copy,
539    Clone,
540    Debug,
541    Display,
542    Hash,
543    PartialEq,
544    Eq,
545    PartialOrd,
546    Ord,
547    AsRefStr,
548    FromRepr,
549    EnumIter,
550    EnumString,
551)]
552#[strum(ascii_case_insensitive)]
553#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
554#[cfg_attr(
555    feature = "python",
556    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
557)]
558pub enum CurrencyType {
559    /// A type of cryptocurrency or crypto token.
560    Crypto = 1,
561    /// A type of currency issued by governments which is not backed by a commodity.
562    Fiat = 2,
563    /// A type of currency that is based on the value of an underlying commodity.
564    CommodityBacked = 3,
565}
566
567/// The type of event for an instrument close.
568#[repr(C)]
569#[derive(
570    Copy,
571    Clone,
572    Debug,
573    Display,
574    Hash,
575    PartialEq,
576    Eq,
577    PartialOrd,
578    Ord,
579    AsRefStr,
580    FromRepr,
581    EnumIter,
582    EnumString,
583)]
584#[strum(ascii_case_insensitive)]
585#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
586#[cfg_attr(
587    feature = "python",
588    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
589)]
590pub enum InstrumentCloseType {
591    /// When the market session ended.
592    EndOfSession = 1,
593    /// When the instrument expiration was reached.
594    ContractExpired = 2,
595}
596
597/// Convert the given `value` to an [`InstrumentCloseType`].
598impl FromU8 for InstrumentCloseType {
599    fn from_u8(value: u8) -> Option<Self> {
600        match value {
601            1 => Some(Self::EndOfSession),
602            2 => Some(Self::ContractExpired),
603            _ => None,
604        }
605    }
606}
607
608/// The liqudity side for a trade.
609#[repr(C)]
610#[derive(
611    Copy,
612    Clone,
613    Debug,
614    Display,
615    Hash,
616    PartialEq,
617    Eq,
618    PartialOrd,
619    Ord,
620    AsRefStr,
621    FromRepr,
622    EnumIter,
623    EnumString,
624)]
625#[strum(ascii_case_insensitive)]
626#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
627#[cfg_attr(
628    feature = "python",
629    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
630)]
631#[allow(clippy::enum_variant_names)]
632pub enum LiquiditySide {
633    /// No liquidity side specified.
634    NoLiquiditySide = 0,
635    /// The order passively provided liqudity to the market to complete the trade (made a market).
636    Maker = 1,
637    /// The order aggressively took liqudity from the market to complete the trade.
638    Taker = 2,
639}
640
641/// The status of an individual market on a trading venue.
642#[repr(C)]
643#[derive(
644    Copy,
645    Clone,
646    Debug,
647    Display,
648    Hash,
649    PartialEq,
650    Eq,
651    PartialOrd,
652    Ord,
653    AsRefStr,
654    FromRepr,
655    EnumIter,
656    EnumString,
657)]
658#[strum(ascii_case_insensitive)]
659#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
660#[cfg_attr(
661    feature = "python",
662    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
663)]
664pub enum MarketStatus {
665    /// The instrument is trading.
666    Open = 1,
667    /// The instrument is in a pre-open period.
668    Closed = 2,
669    /// Trading in the instrument has been paused.
670    Paused = 3,
671    /// Trading in the instrument has been halted.
672    // Halted = 4,  # TODO: Unfortunately can't use this yet due to Cython (C enum namespacing)
673    /// Trading in the instrument has been suspended.
674    Suspended = 5,
675    /// Trading in the instrument is not available.
676    NotAvailable = 6,
677}
678
679/// An action affecting the status of an individual market on a trading venue.
680#[repr(C)]
681#[derive(
682    Copy,
683    Clone,
684    Debug,
685    Display,
686    Hash,
687    PartialEq,
688    Eq,
689    PartialOrd,
690    Ord,
691    AsRefStr,
692    FromRepr,
693    EnumIter,
694    EnumString,
695)]
696#[strum(ascii_case_insensitive)]
697#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
698#[cfg_attr(
699    feature = "python",
700    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
701)]
702pub enum MarketStatusAction {
703    /// No change.
704    None = 0,
705    /// The instrument is in a pre-open period.
706    PreOpen = 1,
707    /// The instrument is in a pre-cross period.
708    PreCross = 2,
709    /// The instrument is quoting but not trading.
710    Quoting = 3,
711    /// The instrument is in a cross/auction.
712    Cross = 4,
713    /// The instrument is being opened through a trading rotation.
714    Rotation = 5,
715    /// A new price indication is available for the instrument.
716    NewPriceIndication = 6,
717    /// The instrument is trading.
718    Trading = 7,
719    /// Trading in the instrument has been halted.
720    Halt = 8,
721    /// Trading in the instrument has been paused.
722    Pause = 9,
723    /// Trading in the instrument has been suspended.
724    Suspend = 10,
725    /// The instrument is in a pre-close period.
726    PreClose = 11,
727    /// Trading in the instrument has closed.
728    Close = 12,
729    /// The instrument is in a post-close period.
730    PostClose = 13,
731    /// A change in short-selling restrictions.
732    ShortSellRestrictionChange = 14,
733    /// The instrument is not available for trading, either trading has closed or been halted.
734    NotAvailableForTrading = 15,
735}
736
737/// Convert the given `value` to an [`OrderSide`].
738impl FromU16 for MarketStatusAction {
739    fn from_u16(value: u16) -> Option<Self> {
740        match value {
741            0 => Some(Self::None),
742            1 => Some(Self::PreOpen),
743            2 => Some(Self::PreCross),
744            3 => Some(Self::Quoting),
745            4 => Some(Self::Cross),
746            5 => Some(Self::Rotation),
747            6 => Some(Self::NewPriceIndication),
748            7 => Some(Self::Trading),
749            8 => Some(Self::Halt),
750            9 => Some(Self::Pause),
751            10 => Some(Self::Suspend),
752            11 => Some(Self::PreClose),
753            12 => Some(Self::Close),
754            13 => Some(Self::PostClose),
755            14 => Some(Self::ShortSellRestrictionChange),
756            15 => Some(Self::NotAvailableForTrading),
757            _ => None,
758        }
759    }
760}
761
762/// The order management system (OMS) type for a trading venue or trading strategy.
763#[repr(C)]
764#[derive(
765    Copy,
766    Clone,
767    Debug,
768    Default,
769    Display,
770    Hash,
771    PartialEq,
772    Eq,
773    PartialOrd,
774    Ord,
775    AsRefStr,
776    FromRepr,
777    EnumIter,
778    EnumString,
779)]
780#[strum(ascii_case_insensitive)]
781#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
782#[cfg_attr(
783    feature = "python",
784    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
785)]
786pub enum OmsType {
787    /// There is no specific type of order management specified (will defer to the venue OMS).
788    #[default]
789    Unspecified = 0,
790    /// The netting type where there is one position per instrument.
791    Netting = 1,
792    /// The hedging type where there can be multiple positions per instrument.
793    /// This can be in LONG/SHORT directions, by position/ticket ID, or tracked virtually by
794    /// Nautilus.
795    Hedging = 2,
796}
797
798/// The kind of option contract.
799#[repr(C)]
800#[derive(
801    Copy,
802    Clone,
803    Debug,
804    Display,
805    Hash,
806    PartialEq,
807    Eq,
808    PartialOrd,
809    Ord,
810    AsRefStr,
811    FromRepr,
812    EnumIter,
813    EnumString,
814)]
815#[strum(ascii_case_insensitive)]
816#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
817#[cfg_attr(
818    feature = "python",
819    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
820)]
821pub enum OptionKind {
822    /// A Call option gives the holder the right, but not the obligation, to buy an underlying asset at a specified strike price within a specified period of time.
823    Call = 1,
824    /// A Put option gives the holder the right, but not the obligation, to sell an underlying asset at a specified strike price within a specified period of time.
825    Put = 2,
826}
827
828/// The order side for a specific order, or action related to orders.
829#[repr(C)]
830#[derive(
831    Copy,
832    Clone,
833    Debug,
834    Default,
835    Display,
836    Hash,
837    PartialEq,
838    Eq,
839    PartialOrd,
840    Ord,
841    AsRefStr,
842    FromRepr,
843    EnumIter,
844    EnumString,
845)]
846#[strum(ascii_case_insensitive)]
847#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
848#[allow(clippy::enum_variant_names)]
849#[cfg_attr(
850    feature = "python",
851    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
852)]
853pub enum OrderSide {
854    /// No order side is specified.
855    #[default]
856    NoOrderSide = 0,
857    /// The order is a BUY.
858    Buy = 1,
859    /// The order is a SELL.
860    Sell = 2,
861}
862
863impl OrderSide {
864    /// Returns the specified [`OrderSideSpecified`] (BUY or SELL) for this side.
865    ///
866    /// # Panics
867    ///
868    /// Panics if `self` is [`OrderSide::NoOrderSide`].
869    #[must_use]
870    pub fn as_specified(&self) -> OrderSideSpecified {
871        match &self {
872            Self::Buy => OrderSideSpecified::Buy,
873            Self::Sell => OrderSideSpecified::Sell,
874            _ => panic!("Order invariant failed: side must be `Buy` or `Sell`"),
875        }
876    }
877}
878
879/// Convert the given `value` to an [`OrderSide`].
880impl FromU8 for OrderSide {
881    fn from_u8(value: u8) -> Option<Self> {
882        match value {
883            0 => Some(Self::NoOrderSide),
884            1 => Some(Self::Buy),
885            2 => Some(Self::Sell),
886            _ => None,
887        }
888    }
889}
890
891/// The specified order side (BUY or SELL).
892#[repr(C)]
893#[derive(
894    Copy,
895    Clone,
896    Debug,
897    Display,
898    Hash,
899    PartialEq,
900    Eq,
901    PartialOrd,
902    Ord,
903    AsRefStr,
904    FromRepr,
905    EnumIter,
906    EnumString,
907)]
908#[strum(ascii_case_insensitive)]
909#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
910#[allow(clippy::enum_variant_names)]
911pub enum OrderSideSpecified {
912    /// The order is a BUY.
913    Buy = 1,
914    /// The order is a SELL.
915    Sell = 2,
916}
917
918impl OrderSideSpecified {
919    /// Returns the opposite order side.
920    #[must_use]
921    pub fn opposite(&self) -> Self {
922        match &self {
923            Self::Buy => Self::Sell,
924            Self::Sell => Self::Buy,
925        }
926    }
927
928    /// Converts this specified side into an [`OrderSide`].
929    #[must_use]
930    pub fn as_order_side(&self) -> OrderSide {
931        match &self {
932            Self::Buy => OrderSide::Buy,
933            Self::Sell => OrderSide::Sell,
934        }
935    }
936}
937
938/// The status for a specific order.
939///
940/// An order is considered _open_ for the following status:
941///  - `ACCEPTED`
942///  - `TRIGGERED`
943///  - `PENDING_UPDATE`
944///  - `PENDING_CANCEL`
945///  - `PARTIALLY_FILLED`
946///
947/// An order is considered _in-flight_ for the following status:
948///  - `SUBMITTED`
949///  - `PENDING_UPDATE`
950///  - `PENDING_CANCEL`
951///
952/// An order is considered _closed_ for the following status:
953///  - `DENIED`
954///  - `REJECTED`
955///  - `CANCELED`
956///  - `EXPIRED`
957///  - `FILLED`
958#[repr(C)]
959#[derive(
960    Copy,
961    Clone,
962    Debug,
963    Display,
964    Hash,
965    PartialEq,
966    Eq,
967    PartialOrd,
968    Ord,
969    AsRefStr,
970    FromRepr,
971    EnumIter,
972    EnumString,
973)]
974#[strum(ascii_case_insensitive)]
975#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
976#[cfg_attr(
977    feature = "python",
978    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
979)]
980pub enum OrderStatus {
981    /// The order is initialized (instantiated) within the Nautilus system.
982    Initialized = 1,
983    /// The order was denied by the Nautilus system, either for being invalid, unprocessable or exceeding a risk limit.
984    Denied = 2,
985    /// The order became emulated by the Nautilus system in the `OrderEmulator` component.
986    Emulated = 3,
987    /// The order was released by the Nautilus system from the `OrderEmulator` component.
988    Released = 4,
989    /// The order was submitted by the Nautilus system to the external service or trading venue (awaiting acknowledgement).
990    Submitted = 5,
991    /// The order was acknowledged by the trading venue as being received and valid (may now be working).
992    Accepted = 6,
993    /// The order was rejected by the trading venue.
994    Rejected = 7,
995    /// The order was canceled (closed/done).
996    Canceled = 8,
997    /// The order reached a GTD expiration (closed/done).
998    Expired = 9,
999    /// The order STOP price was triggered on a trading venue.
1000    Triggered = 10,
1001    /// The order is currently pending a request to modify on a trading venue.
1002    PendingUpdate = 11,
1003    /// The order is currently pending a request to cancel on a trading venue.
1004    PendingCancel = 12,
1005    /// The order has been partially filled on a trading venue.
1006    PartiallyFilled = 13,
1007    /// The order has been completely filled on a trading venue (closed/done).
1008    Filled = 14,
1009}
1010
1011/// The type of order.
1012#[repr(C)]
1013#[derive(
1014    Copy,
1015    Clone,
1016    Debug,
1017    Display,
1018    Hash,
1019    PartialEq,
1020    Eq,
1021    PartialOrd,
1022    Ord,
1023    AsRefStr,
1024    FromRepr,
1025    EnumIter,
1026    EnumString,
1027)]
1028#[strum(ascii_case_insensitive)]
1029#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1030#[cfg_attr(
1031    feature = "python",
1032    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1033)]
1034pub enum OrderType {
1035    /// A market order to buy or sell at the best available price in the current market.
1036    Market = 1,
1037    /// A limit order to buy or sell at a specific price or better.
1038    Limit = 2,
1039    /// A stop market order to buy or sell once the price reaches the specified stop/trigger price. When the stop price is reached, the order effectively becomes a market order.
1040    StopMarket = 3,
1041    /// A stop limit order to buy or sell which combines the features of a stop order and a limit order. Once the stop/trigger price is reached, a stop-limit order effectively becomes a limit order.
1042    StopLimit = 4,
1043    /// A market-to-limit order is a market order that is to be executed as a limit order at the current best market price after reaching the market.
1044    MarketToLimit = 5,
1045    /// A market-if-touched order effectively becomes a market order when the specified trigger price is reached.
1046    MarketIfTouched = 6,
1047    /// A limit-if-touched order effectively becomes a limit order when the specified trigger price is reached.
1048    LimitIfTouched = 7,
1049    /// A trailing stop market order sets the stop/trigger price at a fixed "trailing offset" amount from the market.
1050    TrailingStopMarket = 8,
1051    /// A trailing stop limit order combines the features of a trailing stop order with those of a limit order.
1052    TrailingStopLimit = 9,
1053}
1054
1055/// The market side for a specific position, or action related to positions.
1056#[repr(C)]
1057#[derive(
1058    Copy,
1059    Clone,
1060    Debug,
1061    Default,
1062    Display,
1063    Hash,
1064    PartialEq,
1065    Eq,
1066    PartialOrd,
1067    Ord,
1068    AsRefStr,
1069    FromRepr,
1070    EnumIter,
1071    EnumString,
1072)]
1073#[strum(ascii_case_insensitive)]
1074#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1075#[allow(clippy::enum_variant_names)]
1076#[cfg_attr(
1077    feature = "python",
1078    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1079)]
1080pub enum PositionSide {
1081    /// No position side is specified (only valid in the context of a filter for actions involving positions).
1082    #[default]
1083    NoPositionSide = 0,
1084    /// A neural/flat position, where no position is currently held in the market.
1085    Flat = 1,
1086    /// A long position in the market, typically acquired through one or many BUY orders.
1087    Long = 2,
1088    /// A short position in the market, typically acquired through one or many SELL orders.
1089    Short = 3,
1090}
1091
1092impl PositionSide {
1093    /// Returns the specified [`PositionSideSpecified`] (`Long`, `Short`, or `Flat`) for this side.
1094    ///
1095    /// # Panics
1096    ///
1097    /// Panics if `self` is [`PositionSide::NoPositionSide`].
1098    #[must_use]
1099    pub fn as_specified(&self) -> PositionSideSpecified {
1100        match &self {
1101            Self::Long => PositionSideSpecified::Long,
1102            Self::Short => PositionSideSpecified::Short,
1103            Self::Flat => PositionSideSpecified::Flat,
1104            _ => panic!("Position invariant failed: side must be `Long`, `Short`, or `Flat`"),
1105        }
1106    }
1107}
1108
1109/// The market side for a specific position, or action related to positions.
1110#[repr(C)]
1111#[derive(
1112    Copy,
1113    Clone,
1114    Debug,
1115    Display,
1116    Hash,
1117    PartialEq,
1118    Eq,
1119    PartialOrd,
1120    Ord,
1121    AsRefStr,
1122    FromRepr,
1123    EnumIter,
1124    EnumString,
1125)]
1126#[strum(ascii_case_insensitive)]
1127#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1128#[allow(clippy::enum_variant_names)]
1129#[cfg_attr(
1130    feature = "python",
1131    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1132)]
1133pub enum PositionSideSpecified {
1134    /// A neural/flat position, where no position is currently held in the market.
1135    Flat = 1,
1136    /// A long position in the market, typically acquired through one or many BUY orders.
1137    Long = 2,
1138    /// A short position in the market, typically acquired through one or many SELL orders.
1139    Short = 3,
1140}
1141
1142impl PositionSideSpecified {
1143    /// Converts this specified side into a [`PositionSide`].
1144    #[must_use]
1145    pub fn as_position_side(&self) -> PositionSide {
1146        match &self {
1147            Self::Long => PositionSide::Long,
1148            Self::Short => PositionSide::Short,
1149            Self::Flat => PositionSide::Flat,
1150        }
1151    }
1152}
1153
1154/// The type of price for an instrument in a market.
1155#[repr(C)]
1156#[derive(
1157    Copy,
1158    Clone,
1159    Debug,
1160    Display,
1161    Hash,
1162    PartialEq,
1163    Eq,
1164    PartialOrd,
1165    Ord,
1166    AsRefStr,
1167    FromRepr,
1168    EnumIter,
1169    EnumString,
1170)]
1171#[strum(ascii_case_insensitive)]
1172#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1173#[cfg_attr(
1174    feature = "python",
1175    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1176)]
1177pub enum PriceType {
1178    /// The best quoted price at which buyers are willing to buy a quantity of an instrument.
1179    /// Often considered the best bid in the order book.
1180    Bid = 1,
1181    /// The best quoted price at which sellers are willing to sell a quantity of an instrument.
1182    /// Often considered the best ask in the order book.
1183    Ask = 2,
1184    /// The arithmetic midpoint between the best bid and ask quotes.
1185    Mid = 3,
1186    /// The price at which the last trade of an instrument was executed.
1187    Last = 4,
1188    /// A reference price reflecting an instrument's fair value, often used for portfolio
1189    /// calculations and risk management.
1190    Mark = 5,
1191}
1192
1193/// A record flag bit field, indicating event end and data information.
1194#[repr(C)]
1195#[derive(
1196    Copy,
1197    Clone,
1198    Debug,
1199    Display,
1200    Hash,
1201    PartialEq,
1202    Eq,
1203    PartialOrd,
1204    Ord,
1205    AsRefStr,
1206    FromRepr,
1207    EnumIter,
1208    EnumString,
1209)]
1210#[strum(ascii_case_insensitive)]
1211#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1212#[cfg_attr(
1213    feature = "python",
1214    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1215)]
1216#[allow(non_camel_case_types)]
1217pub enum RecordFlag {
1218    /// Last message in the book event or packet from the venue for a given `instrument_id`.
1219    F_LAST = 1 << 7, // 128
1220    /// Top-of-book message, not an individual order.
1221    F_TOB = 1 << 6, // 64
1222    /// Message sourced from a replay, such as a snapshot server.
1223    F_SNAPSHOT = 1 << 5, // 32
1224    /// Aggregated price level message, not an individual order.
1225    F_MBP = 1 << 4, // 16
1226    /// Reserved for future use.
1227    RESERVED_2 = 1 << 3, // 8
1228    /// Reserved for future use.
1229    RESERVED_1 = 1 << 2, // 4
1230}
1231
1232impl RecordFlag {
1233    /// Checks if the flag matches a given value.
1234    #[must_use]
1235    pub fn matches(self, value: u8) -> bool {
1236        (self as u8) & value != 0
1237    }
1238}
1239
1240/// The 'Time in Force' instruction for an order.
1241#[repr(C)]
1242#[derive(
1243    Copy,
1244    Clone,
1245    Debug,
1246    Display,
1247    Hash,
1248    PartialEq,
1249    Eq,
1250    PartialOrd,
1251    Ord,
1252    AsRefStr,
1253    FromRepr,
1254    EnumIter,
1255    EnumString,
1256)]
1257#[strum(ascii_case_insensitive)]
1258#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1259#[cfg_attr(
1260    feature = "python",
1261    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1262)]
1263pub enum TimeInForce {
1264    /// Good Till Cancel (GTC) - Remains active until canceled.
1265    Gtc = 1,
1266    /// Immediate or Cancel (IOC) - Executes immediately to the extent possible, with any unfilled portion canceled.
1267    Ioc = 2,
1268    /// Fill or Kill (FOK) - Executes in its entirety immediately or is canceled if full execution is not possible.
1269    Fok = 3,
1270    /// Good Till Date (GTD) - Remains active until the specified expiration date or time is reached.
1271    Gtd = 4,
1272    /// Day - Remains active until the close of the current trading session.
1273    Day = 5,
1274    /// At the Opening (ATO) - Executes at the market opening or expires if not filled.
1275    AtTheOpen = 6,
1276    /// At the Closing (ATC) - Executes at the market close or expires if not filled.
1277    AtTheClose = 7,
1278}
1279
1280/// The trading state for a node.
1281#[repr(C)]
1282#[derive(
1283    Copy,
1284    Clone,
1285    Debug,
1286    Display,
1287    Hash,
1288    PartialEq,
1289    Eq,
1290    PartialOrd,
1291    Ord,
1292    AsRefStr,
1293    FromRepr,
1294    EnumIter,
1295    EnumString,
1296)]
1297#[strum(ascii_case_insensitive)]
1298#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1299#[cfg_attr(
1300    feature = "python",
1301    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1302)]
1303pub enum TradingState {
1304    /// Normal trading operations.
1305    Active = 1,
1306    /// Trading is completely halted, no new order commands will be emitted.
1307    Halted = 2,
1308    /// Only order commands which would cancel order, or reduce position sizes are permitted.
1309    Reducing = 3,
1310}
1311
1312/// The trailing offset type for an order type which specifies a trailing stop/trigger or limit price.
1313#[repr(C)]
1314#[derive(
1315    Copy,
1316    Clone,
1317    Debug,
1318    Default,
1319    Display,
1320    Hash,
1321    PartialEq,
1322    Eq,
1323    PartialOrd,
1324    Ord,
1325    AsRefStr,
1326    FromRepr,
1327    EnumIter,
1328    EnumString,
1329)]
1330#[strum(ascii_case_insensitive)]
1331#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1332#[cfg_attr(
1333    feature = "python",
1334    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1335)]
1336pub enum TrailingOffsetType {
1337    /// No trailing offset type is specified (invalid for trailing type orders).
1338    #[default]
1339    NoTrailingOffset = 0,
1340    /// The trailing offset is based on a market price.
1341    Price = 1,
1342    /// The trailing offset is based on a percentage represented in basis points, of a market price.
1343    BasisPoints = 2,
1344    /// The trailing offset is based on the number of ticks from a market price.
1345    Ticks = 3,
1346    /// The trailing offset is based on a price tier set by a specific trading venue.
1347    PriceTier = 4,
1348}
1349
1350/// The trigger type for the stop/trigger price of an order.
1351#[repr(C)]
1352#[derive(
1353    Copy,
1354    Clone,
1355    Debug,
1356    Default,
1357    Display,
1358    Hash,
1359    PartialEq,
1360    Eq,
1361    PartialOrd,
1362    Ord,
1363    AsRefStr,
1364    FromRepr,
1365    EnumIter,
1366    EnumString,
1367)]
1368#[strum(ascii_case_insensitive)]
1369#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1370#[cfg_attr(
1371    feature = "python",
1372    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1373)]
1374pub enum TriggerType {
1375    /// No trigger type is specified (invalid for orders with a trigger).
1376    #[default]
1377    NoTrigger = 0,
1378    /// The default trigger type set by the trading venue.
1379    Default = 1,
1380    /// Based on the last traded price for the instrument.
1381    LastPrice = 2,
1382    /// Based on the mark price for the instrument.
1383    MarkPrice = 3,
1384    /// Based on the index price for the instrument.
1385    IndexPrice = 4,
1386    /// Based on the top-of-book quoted prices for the instrument.
1387    BidAsk = 5,
1388    /// Based on a 'double match' of the last traded price for the instrument
1389    DoubleLast = 6,
1390    /// Based on a 'double match' of the bid/ask price for the instrument
1391    DoubleBidAsk = 7,
1392    /// Based on both the [`TriggerType::LastPrice`] and [`TriggerType::BidAsk`].
1393    LastOrBidAsk = 8,
1394    /// Based on the mid-point of the [`TriggerType::BidAsk`].
1395    MidPoint = 9,
1396}
1397
1398enum_strum_serde!(AccountType);
1399enum_strum_serde!(AggregationSource);
1400enum_strum_serde!(AggressorSide);
1401enum_strum_serde!(AssetClass);
1402enum_strum_serde!(InstrumentClass);
1403enum_strum_serde!(BarAggregation);
1404enum_strum_serde!(BarIntervalType);
1405enum_strum_serde!(BookAction);
1406enum_strum_serde!(BookType);
1407enum_strum_serde!(ContingencyType);
1408enum_strum_serde!(CurrencyType);
1409enum_strum_serde!(InstrumentCloseType);
1410enum_strum_serde!(LiquiditySide);
1411enum_strum_serde!(MarketStatus);
1412enum_strum_serde!(MarketStatusAction);
1413enum_strum_serde!(OmsType);
1414enum_strum_serde!(OptionKind);
1415enum_strum_serde!(OrderSide);
1416enum_strum_serde!(OrderSideSpecified);
1417enum_strum_serde!(OrderStatus);
1418enum_strum_serde!(OrderType);
1419enum_strum_serde!(PositionSide);
1420enum_strum_serde!(PositionSideSpecified);
1421enum_strum_serde!(PriceType);
1422enum_strum_serde!(RecordFlag);
1423enum_strum_serde!(TimeInForce);
1424enum_strum_serde!(TradingState);
1425enum_strum_serde!(TrailingOffsetType);
1426enum_strum_serde!(TriggerType);