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