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    ///
385    /// # Panics
386    ///
387    /// Panics if `side` is [`OrderSide::NoOrderSide`].
388    fn from(side: OrderSide) -> Self {
389        match side {
390            OrderSide::Buy => BetSide::Back,
391            OrderSide::Sell => BetSide::Lay,
392            OrderSide::NoOrderSide => panic!("Invalid `OrderSide` for `BetSide`, was {side}"),
393        }
394    }
395}
396
397/// The type of order book action for an order book event.
398#[repr(C)]
399#[derive(
400    Copy,
401    Clone,
402    Debug,
403    Display,
404    Hash,
405    PartialEq,
406    Eq,
407    PartialOrd,
408    Ord,
409    AsRefStr,
410    FromRepr,
411    EnumIter,
412    EnumString,
413)]
414#[strum(ascii_case_insensitive)]
415#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
416#[cfg_attr(
417    feature = "python",
418    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
419)]
420pub enum BookAction {
421    /// An order is added to the book.
422    Add = 1,
423    /// An existing order in the book is updated/modified.
424    Update = 2,
425    /// An existing order in the book is deleted/canceled.
426    Delete = 3,
427    /// The state of the order book is cleared.
428    Clear = 4,
429}
430
431impl FromU8 for BookAction {
432    fn from_u8(value: u8) -> Option<Self> {
433        match value {
434            1 => Some(Self::Add),
435            2 => Some(Self::Update),
436            3 => Some(Self::Delete),
437            4 => Some(Self::Clear),
438            _ => None,
439        }
440    }
441}
442
443/// The order book type, representing the type of levels granularity and delta updating heuristics.
444#[repr(C)]
445#[derive(
446    Copy,
447    Clone,
448    Debug,
449    Display,
450    Hash,
451    PartialEq,
452    Eq,
453    PartialOrd,
454    Ord,
455    AsRefStr,
456    FromRepr,
457    EnumIter,
458    EnumString,
459)]
460#[strum(ascii_case_insensitive)]
461#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
462#[allow(non_camel_case_types)]
463#[cfg_attr(
464    feature = "python",
465    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
466)]
467pub enum BookType {
468    /// Top-of-book best bid/ask, one level per side.
469    L1_MBP = 1,
470    /// Market by price, one order per level (aggregated).
471    L2_MBP = 2,
472    /// Market by order, multiple orders per level (full granularity).
473    L3_MBO = 3,
474}
475
476impl FromU8 for BookType {
477    fn from_u8(value: u8) -> Option<Self> {
478        match value {
479            1 => Some(Self::L1_MBP),
480            2 => Some(Self::L2_MBP),
481            3 => Some(Self::L3_MBO),
482            _ => None,
483        }
484    }
485}
486
487/// The order contigency type which specifies the behavior of linked orders.
488///
489/// [FIX 5.0 SP2 : ContingencyType <1385> field](https://www.onixs.biz/fix-dictionary/5.0.sp2/tagnum_1385.html).
490#[repr(C)]
491#[derive(
492    Copy,
493    Clone,
494    Debug,
495    Default,
496    Display,
497    Hash,
498    PartialEq,
499    Eq,
500    PartialOrd,
501    Ord,
502    AsRefStr,
503    FromRepr,
504    EnumIter,
505    EnumString,
506)]
507#[strum(ascii_case_insensitive)]
508#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
509#[cfg_attr(
510    feature = "python",
511    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
512)]
513pub enum ContingencyType {
514    /// Not a contingent order.
515    #[default]
516    NoContingency = 0,
517    /// One-Cancels-the-Other.
518    Oco = 1,
519    /// One-Triggers-the-Other.
520    Oto = 2,
521    /// One-Updates-the-Other (by proportional quantity).
522    Ouo = 3,
523}
524
525/// The broad currency type.
526#[repr(C)]
527#[derive(
528    Copy,
529    Clone,
530    Debug,
531    Display,
532    Hash,
533    PartialEq,
534    Eq,
535    PartialOrd,
536    Ord,
537    AsRefStr,
538    FromRepr,
539    EnumIter,
540    EnumString,
541)]
542#[strum(ascii_case_insensitive)]
543#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
544#[cfg_attr(
545    feature = "python",
546    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
547)]
548pub enum CurrencyType {
549    /// A type of cryptocurrency or crypto token.
550    Crypto = 1,
551    /// A type of currency issued by governments which is not backed by a commodity.
552    Fiat = 2,
553    /// A type of currency that is based on the value of an underlying commodity.
554    CommodityBacked = 3,
555}
556
557/// The type of event for an instrument close.
558#[repr(C)]
559#[derive(
560    Copy,
561    Clone,
562    Debug,
563    Display,
564    Hash,
565    PartialEq,
566    Eq,
567    PartialOrd,
568    Ord,
569    AsRefStr,
570    FromRepr,
571    EnumIter,
572    EnumString,
573)]
574#[strum(ascii_case_insensitive)]
575#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
576#[cfg_attr(
577    feature = "python",
578    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
579)]
580pub enum InstrumentCloseType {
581    /// When the market session ended.
582    EndOfSession = 1,
583    /// When the instrument expiration was reached.
584    ContractExpired = 2,
585}
586
587/// Convert the given `value` to an [`InstrumentCloseType`].
588impl FromU8 for InstrumentCloseType {
589    fn from_u8(value: u8) -> Option<Self> {
590        match value {
591            1 => Some(Self::EndOfSession),
592            2 => Some(Self::ContractExpired),
593            _ => None,
594        }
595    }
596}
597
598/// The liqudity side for a trade.
599#[repr(C)]
600#[derive(
601    Copy,
602    Clone,
603    Debug,
604    Display,
605    Hash,
606    PartialEq,
607    Eq,
608    PartialOrd,
609    Ord,
610    AsRefStr,
611    FromRepr,
612    EnumIter,
613    EnumString,
614)]
615#[strum(ascii_case_insensitive)]
616#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
617#[cfg_attr(
618    feature = "python",
619    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
620)]
621#[allow(clippy::enum_variant_names)]
622pub enum LiquiditySide {
623    /// No liquidity side specified.
624    NoLiquiditySide = 0,
625    /// The order passively provided liqudity to the market to complete the trade (made a market).
626    Maker = 1,
627    /// The order aggressively took liqudity from the market to complete the trade.
628    Taker = 2,
629}
630
631/// The status of an individual market on a trading venue.
632#[repr(C)]
633#[derive(
634    Copy,
635    Clone,
636    Debug,
637    Display,
638    Hash,
639    PartialEq,
640    Eq,
641    PartialOrd,
642    Ord,
643    AsRefStr,
644    FromRepr,
645    EnumIter,
646    EnumString,
647)]
648#[strum(ascii_case_insensitive)]
649#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
650#[cfg_attr(
651    feature = "python",
652    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
653)]
654pub enum MarketStatus {
655    /// The instrument is trading.
656    Open = 1,
657    /// The instrument is in a pre-open period.
658    Closed = 2,
659    /// Trading in the instrument has been paused.
660    Paused = 3,
661    /// Trading in the instrument has been halted.
662    // Halted = 4,  # TODO: Unfortunately can't use this yet due to Cython (C enum namespacing)
663    /// Trading in the instrument has been suspended.
664    Suspended = 5,
665    /// Trading in the instrument is not available.
666    NotAvailable = 6,
667}
668
669/// An action affecting the status of an individual market on a trading venue.
670#[repr(C)]
671#[derive(
672    Copy,
673    Clone,
674    Debug,
675    Display,
676    Hash,
677    PartialEq,
678    Eq,
679    PartialOrd,
680    Ord,
681    AsRefStr,
682    FromRepr,
683    EnumIter,
684    EnumString,
685)]
686#[strum(ascii_case_insensitive)]
687#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
688#[cfg_attr(
689    feature = "python",
690    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
691)]
692pub enum MarketStatusAction {
693    /// No change.
694    None = 0,
695    /// The instrument is in a pre-open period.
696    PreOpen = 1,
697    /// The instrument is in a pre-cross period.
698    PreCross = 2,
699    /// The instrument is quoting but not trading.
700    Quoting = 3,
701    /// The instrument is in a cross/auction.
702    Cross = 4,
703    /// The instrument is being opened through a trading rotation.
704    Rotation = 5,
705    /// A new price indication is available for the instrument.
706    NewPriceIndication = 6,
707    /// The instrument is trading.
708    Trading = 7,
709    /// Trading in the instrument has been halted.
710    Halt = 8,
711    /// Trading in the instrument has been paused.
712    Pause = 9,
713    /// Trading in the instrument has been suspended.
714    Suspend = 10,
715    /// The instrument is in a pre-close period.
716    PreClose = 11,
717    /// Trading in the instrument has closed.
718    Close = 12,
719    /// The instrument is in a post-close period.
720    PostClose = 13,
721    /// A change in short-selling restrictions.
722    ShortSellRestrictionChange = 14,
723    /// The instrument is not available for trading, either trading has closed or been halted.
724    NotAvailableForTrading = 15,
725}
726
727/// Convert the given `value` to an [`OrderSide`].
728impl FromU16 for MarketStatusAction {
729    fn from_u16(value: u16) -> Option<Self> {
730        match value {
731            0 => Some(Self::None),
732            1 => Some(Self::PreOpen),
733            2 => Some(Self::PreCross),
734            3 => Some(Self::Quoting),
735            4 => Some(Self::Cross),
736            5 => Some(Self::Rotation),
737            6 => Some(Self::NewPriceIndication),
738            7 => Some(Self::Trading),
739            8 => Some(Self::Halt),
740            9 => Some(Self::Pause),
741            10 => Some(Self::Suspend),
742            11 => Some(Self::PreClose),
743            12 => Some(Self::Close),
744            13 => Some(Self::PostClose),
745            14 => Some(Self::ShortSellRestrictionChange),
746            15 => Some(Self::NotAvailableForTrading),
747            _ => None,
748        }
749    }
750}
751
752/// The order management system (OMS) type for a trading venue or trading strategy.
753#[repr(C)]
754#[derive(
755    Copy,
756    Clone,
757    Debug,
758    Default,
759    Display,
760    Hash,
761    PartialEq,
762    Eq,
763    PartialOrd,
764    Ord,
765    AsRefStr,
766    FromRepr,
767    EnumIter,
768    EnumString,
769)]
770#[strum(ascii_case_insensitive)]
771#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
772#[cfg_attr(
773    feature = "python",
774    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
775)]
776pub enum OmsType {
777    /// There is no specific type of order management specified (will defer to the venue OMS).
778    #[default]
779    Unspecified = 0,
780    /// The netting type where there is one position per instrument.
781    Netting = 1,
782    /// The hedging type where there can be multiple positions per instrument.
783    /// This can be in LONG/SHORT directions, by position/ticket ID, or tracked virtually by
784    /// Nautilus.
785    Hedging = 2,
786}
787
788/// The kind of option contract.
789#[repr(C)]
790#[derive(
791    Copy,
792    Clone,
793    Debug,
794    Display,
795    Hash,
796    PartialEq,
797    Eq,
798    PartialOrd,
799    Ord,
800    AsRefStr,
801    FromRepr,
802    EnumIter,
803    EnumString,
804)]
805#[strum(ascii_case_insensitive)]
806#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
807#[cfg_attr(
808    feature = "python",
809    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
810)]
811pub enum OptionKind {
812    /// 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.
813    Call = 1,
814    /// 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.
815    Put = 2,
816}
817
818/// The order side for a specific order, or action related to orders.
819#[repr(C)]
820#[derive(
821    Copy,
822    Clone,
823    Debug,
824    Default,
825    Display,
826    Hash,
827    PartialEq,
828    Eq,
829    PartialOrd,
830    Ord,
831    AsRefStr,
832    FromRepr,
833    EnumIter,
834    EnumString,
835)]
836#[strum(ascii_case_insensitive)]
837#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
838#[allow(clippy::enum_variant_names)]
839#[cfg_attr(
840    feature = "python",
841    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
842)]
843pub enum OrderSide {
844    /// No order side is specified.
845    #[default]
846    NoOrderSide = 0,
847    /// The order is a BUY.
848    Buy = 1,
849    /// The order is a SELL.
850    Sell = 2,
851}
852
853impl OrderSide {
854    /// Returns the specified [`OrderSideSpecified`] (BUY or SELL) for this side.
855    ///
856    /// # Panics
857    ///
858    /// Panics if `self` is [`OrderSide::NoOrderSide`].
859    #[must_use]
860    pub fn as_specified(&self) -> OrderSideSpecified {
861        match &self {
862            Self::Buy => OrderSideSpecified::Buy,
863            Self::Sell => OrderSideSpecified::Sell,
864            _ => panic!("Order invariant failed: side must be `Buy` or `Sell`"),
865        }
866    }
867}
868
869/// Convert the given `value` to an [`OrderSide`].
870impl FromU8 for OrderSide {
871    fn from_u8(value: u8) -> Option<Self> {
872        match value {
873            0 => Some(Self::NoOrderSide),
874            1 => Some(Self::Buy),
875            2 => Some(Self::Sell),
876            _ => None,
877        }
878    }
879}
880
881/// The specified order side (BUY or SELL).
882#[repr(C)]
883#[derive(
884    Copy,
885    Clone,
886    Debug,
887    Display,
888    Hash,
889    PartialEq,
890    Eq,
891    PartialOrd,
892    Ord,
893    AsRefStr,
894    FromRepr,
895    EnumIter,
896    EnumString,
897)]
898#[strum(ascii_case_insensitive)]
899#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
900#[allow(clippy::enum_variant_names)]
901pub enum OrderSideSpecified {
902    /// The order is a BUY.
903    Buy = 1,
904    /// The order is a SELL.
905    Sell = 2,
906}
907
908impl OrderSideSpecified {
909    /// Returns the opposite order side.
910    #[must_use]
911    pub fn opposite(&self) -> Self {
912        match &self {
913            Self::Buy => Self::Sell,
914            Self::Sell => Self::Buy,
915        }
916    }
917
918    /// Converts this specified side into an [`OrderSide`].
919    #[must_use]
920    pub fn as_order_side(&self) -> OrderSide {
921        match &self {
922            Self::Buy => OrderSide::Buy,
923            Self::Sell => OrderSide::Sell,
924        }
925    }
926}
927
928/// The status for a specific order.
929///
930/// An order is considered _open_ for the following status:
931///  - `ACCEPTED`
932///  - `TRIGGERED`
933///  - `PENDING_UPDATE`
934///  - `PENDING_CANCEL`
935///  - `PARTIALLY_FILLED`
936///
937/// An order is considered _in-flight_ for the following status:
938///  - `SUBMITTED`
939///  - `PENDING_UPDATE`
940///  - `PENDING_CANCEL`
941///
942/// An order is considered _closed_ for the following status:
943///  - `DENIED`
944///  - `REJECTED`
945///  - `CANCELED`
946///  - `EXPIRED`
947///  - `FILLED`
948#[repr(C)]
949#[derive(
950    Copy,
951    Clone,
952    Debug,
953    Display,
954    Hash,
955    PartialEq,
956    Eq,
957    PartialOrd,
958    Ord,
959    AsRefStr,
960    FromRepr,
961    EnumIter,
962    EnumString,
963)]
964#[strum(ascii_case_insensitive)]
965#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
966#[cfg_attr(
967    feature = "python",
968    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
969)]
970pub enum OrderStatus {
971    /// The order is initialized (instantiated) within the Nautilus system.
972    Initialized = 1,
973    /// The order was denied by the Nautilus system, either for being invalid, unprocessable or exceeding a risk limit.
974    Denied = 2,
975    /// The order became emulated by the Nautilus system in the `OrderEmulator` component.
976    Emulated = 3,
977    /// The order was released by the Nautilus system from the `OrderEmulator` component.
978    Released = 4,
979    /// The order was submitted by the Nautilus system to the external service or trading venue (awaiting acknowledgement).
980    Submitted = 5,
981    /// The order was acknowledged by the trading venue as being received and valid (may now be working).
982    Accepted = 6,
983    /// The order was rejected by the trading venue.
984    Rejected = 7,
985    /// The order was canceled (closed/done).
986    Canceled = 8,
987    /// The order reached a GTD expiration (closed/done).
988    Expired = 9,
989    /// The order STOP price was triggered on a trading venue.
990    Triggered = 10,
991    /// The order is currently pending a request to modify on a trading venue.
992    PendingUpdate = 11,
993    /// The order is currently pending a request to cancel on a trading venue.
994    PendingCancel = 12,
995    /// The order has been partially filled on a trading venue.
996    PartiallyFilled = 13,
997    /// The order has been completely filled on a trading venue (closed/done).
998    Filled = 14,
999}
1000
1001/// The type of order.
1002#[repr(C)]
1003#[derive(
1004    Copy,
1005    Clone,
1006    Debug,
1007    Display,
1008    Hash,
1009    PartialEq,
1010    Eq,
1011    PartialOrd,
1012    Ord,
1013    AsRefStr,
1014    FromRepr,
1015    EnumIter,
1016    EnumString,
1017)]
1018#[strum(ascii_case_insensitive)]
1019#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1020#[cfg_attr(
1021    feature = "python",
1022    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1023)]
1024pub enum OrderType {
1025    /// A market order to buy or sell at the best available price in the current market.
1026    Market = 1,
1027    /// A limit order to buy or sell at a specific price or better.
1028    Limit = 2,
1029    /// 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.
1030    StopMarket = 3,
1031    /// 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.
1032    StopLimit = 4,
1033    /// 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.
1034    MarketToLimit = 5,
1035    /// A market-if-touched order effectively becomes a market order when the specified trigger price is reached.
1036    MarketIfTouched = 6,
1037    /// A limit-if-touched order effectively becomes a limit order when the specified trigger price is reached.
1038    LimitIfTouched = 7,
1039    /// A trailing stop market order sets the stop/trigger price at a fixed "trailing offset" amount from the market.
1040    TrailingStopMarket = 8,
1041    /// A trailing stop limit order combines the features of a trailing stop order with those of a limit order.
1042    TrailingStopLimit = 9,
1043}
1044
1045/// The market side for a specific position, or action related to positions.
1046#[repr(C)]
1047#[derive(
1048    Copy,
1049    Clone,
1050    Debug,
1051    Default,
1052    Display,
1053    Hash,
1054    PartialEq,
1055    Eq,
1056    PartialOrd,
1057    Ord,
1058    AsRefStr,
1059    FromRepr,
1060    EnumIter,
1061    EnumString,
1062)]
1063#[strum(ascii_case_insensitive)]
1064#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1065#[allow(clippy::enum_variant_names)]
1066#[cfg_attr(
1067    feature = "python",
1068    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1069)]
1070pub enum PositionSide {
1071    /// No position side is specified (only valid in the context of a filter for actions involving positions).
1072    #[default]
1073    NoPositionSide = 0,
1074    /// A neural/flat position, where no position is currently held in the market.
1075    Flat = 1,
1076    /// A long position in the market, typically acquired through one or many BUY orders.
1077    Long = 2,
1078    /// A short position in the market, typically acquired through one or many SELL orders.
1079    Short = 3,
1080}
1081
1082/// The type of price for an instrument in a market.
1083#[repr(C)]
1084#[derive(
1085    Copy,
1086    Clone,
1087    Debug,
1088    Display,
1089    Hash,
1090    PartialEq,
1091    Eq,
1092    PartialOrd,
1093    Ord,
1094    AsRefStr,
1095    FromRepr,
1096    EnumIter,
1097    EnumString,
1098)]
1099#[strum(ascii_case_insensitive)]
1100#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1101#[cfg_attr(
1102    feature = "python",
1103    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1104)]
1105pub enum PriceType {
1106    /// The best quoted price at which buyers are willing to buy a quantity of an instrument.
1107    /// Often considered the best bid in the order book.
1108    Bid = 1,
1109    /// The best quoted price at which sellers are willing to sell a quantity of an instrument.
1110    /// Often considered the best ask in the order book.
1111    Ask = 2,
1112    /// The arithmetic midpoint between the best bid and ask quotes.
1113    Mid = 3,
1114    /// The price at which the last trade of an instrument was executed.
1115    Last = 4,
1116    /// A reference price reflecting an instrument's fair value, often used for portfolio
1117    /// calculations and risk management.
1118    Mark = 5,
1119}
1120
1121/// A record flag bit field, indicating event end and data information.
1122#[repr(C)]
1123#[derive(
1124    Copy,
1125    Clone,
1126    Debug,
1127    Display,
1128    Hash,
1129    PartialEq,
1130    Eq,
1131    PartialOrd,
1132    Ord,
1133    AsRefStr,
1134    FromRepr,
1135    EnumIter,
1136    EnumString,
1137)]
1138#[strum(ascii_case_insensitive)]
1139#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1140#[cfg_attr(
1141    feature = "python",
1142    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1143)]
1144#[allow(non_camel_case_types)]
1145pub enum RecordFlag {
1146    /// Last message in the book event or packet from the venue for a given `instrument_id`.
1147    F_LAST = 1 << 7, // 128
1148    /// Top-of-book message, not an individual order.
1149    F_TOB = 1 << 6, // 64
1150    /// Message sourced from a replay, such as a snapshot server.
1151    F_SNAPSHOT = 1 << 5, // 32
1152    /// Aggregated price level message, not an individual order.
1153    F_MBP = 1 << 4, // 16
1154    /// Reserved for future use.
1155    RESERVED_2 = 1 << 3, // 8
1156    /// Reserved for future use.
1157    RESERVED_1 = 1 << 2, // 4
1158}
1159
1160impl RecordFlag {
1161    /// Checks if the flag matches a given value.
1162    #[must_use]
1163    pub fn matches(self, value: u8) -> bool {
1164        (self as u8) & value != 0
1165    }
1166}
1167
1168/// The 'Time in Force' instruction for an order.
1169#[repr(C)]
1170#[derive(
1171    Copy,
1172    Clone,
1173    Debug,
1174    Display,
1175    Hash,
1176    PartialEq,
1177    Eq,
1178    PartialOrd,
1179    Ord,
1180    AsRefStr,
1181    FromRepr,
1182    EnumIter,
1183    EnumString,
1184)]
1185#[strum(ascii_case_insensitive)]
1186#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1187#[cfg_attr(
1188    feature = "python",
1189    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1190)]
1191pub enum TimeInForce {
1192    /// Good Till Cancel (GTC) - Remains active until canceled.
1193    Gtc = 1,
1194    /// Immediate or Cancel (IOC) - Executes immediately to the extent possible, with any unfilled portion canceled.
1195    Ioc = 2,
1196    /// Fill or Kill (FOK) - Executes in its entirety immediately or is canceled if full execution is not possible.
1197    Fok = 3,
1198    /// Good Till Date (GTD) - Remains active until the specified expiration date or time is reached.
1199    Gtd = 4,
1200    /// Day - Remains active until the close of the current trading session.
1201    Day = 5,
1202    /// At the Opening (ATO) - Executes at the market opening or expires if not filled.
1203    AtTheOpen = 6,
1204    /// At the Closing (ATC) - Executes at the market close or expires if not filled.
1205    AtTheClose = 7,
1206}
1207
1208/// The trading state for a node.
1209#[repr(C)]
1210#[derive(
1211    Copy,
1212    Clone,
1213    Debug,
1214    Display,
1215    Hash,
1216    PartialEq,
1217    Eq,
1218    PartialOrd,
1219    Ord,
1220    AsRefStr,
1221    FromRepr,
1222    EnumIter,
1223    EnumString,
1224)]
1225#[strum(ascii_case_insensitive)]
1226#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1227#[cfg_attr(
1228    feature = "python",
1229    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1230)]
1231pub enum TradingState {
1232    /// Normal trading operations.
1233    Active = 1,
1234    /// Trading is completely halted, no new order commands will be emitted.
1235    Halted = 2,
1236    /// Only order commands which would cancel order, or reduce position sizes are permitted.
1237    Reducing = 3,
1238}
1239
1240/// The trailing offset type for an order type which specifies a trailing stop/trigger or limit price.
1241#[repr(C)]
1242#[derive(
1243    Copy,
1244    Clone,
1245    Debug,
1246    Default,
1247    Display,
1248    Hash,
1249    PartialEq,
1250    Eq,
1251    PartialOrd,
1252    Ord,
1253    AsRefStr,
1254    FromRepr,
1255    EnumIter,
1256    EnumString,
1257)]
1258#[strum(ascii_case_insensitive)]
1259#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1260#[cfg_attr(
1261    feature = "python",
1262    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1263)]
1264pub enum TrailingOffsetType {
1265    /// No trailing offset type is specified (invalid for trailing type orders).
1266    #[default]
1267    NoTrailingOffset = 0,
1268    /// The trailing offset is based on a market price.
1269    Price = 1,
1270    /// The trailing offset is based on a percentage represented in basis points, of a market price.
1271    BasisPoints = 2,
1272    /// The trailing offset is based on the number of ticks from a market price.
1273    Ticks = 3,
1274    /// The trailing offset is based on a price tier set by a specific trading venue.
1275    PriceTier = 4,
1276}
1277
1278/// The trigger type for the stop/trigger price of an order.
1279#[repr(C)]
1280#[derive(
1281    Copy,
1282    Clone,
1283    Debug,
1284    Default,
1285    Display,
1286    Hash,
1287    PartialEq,
1288    Eq,
1289    PartialOrd,
1290    Ord,
1291    AsRefStr,
1292    FromRepr,
1293    EnumIter,
1294    EnumString,
1295)]
1296#[strum(ascii_case_insensitive)]
1297#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1298#[cfg_attr(
1299    feature = "python",
1300    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.model.enums")
1301)]
1302pub enum TriggerType {
1303    /// No trigger type is specified (invalid for orders with a trigger).
1304    #[default]
1305    NoTrigger = 0,
1306    /// The default trigger type set by the trading venue.
1307    Default = 1,
1308    /// Based on the last traded price for the instrument.
1309    LastPrice = 2,
1310    /// Based on the mark price for the instrument.
1311    MarkPrice = 3,
1312    /// Based on the index price for the instrument.
1313    IndexPrice = 4,
1314    /// Based on the top-of-book quoted prices for the instrument.
1315    BidAsk = 5,
1316    /// Based on a 'double match' of the last traded price for the instrument
1317    DoubleLast = 6,
1318    /// Based on a 'double match' of the bid/ask price for the instrument
1319    DoubleBidAsk = 7,
1320    /// Based on both the [`TriggerType::LastPrice`] and [`TriggerType::BidAsk`].
1321    LastOrBidAsk = 8,
1322    /// Based on the mid-point of the [`TriggerType::BidAsk`].
1323    MidPoint = 9,
1324}
1325
1326enum_strum_serde!(AccountType);
1327enum_strum_serde!(AggregationSource);
1328enum_strum_serde!(AggressorSide);
1329enum_strum_serde!(AssetClass);
1330enum_strum_serde!(InstrumentClass);
1331enum_strum_serde!(BarAggregation);
1332enum_strum_serde!(BarIntervalType);
1333enum_strum_serde!(BookAction);
1334enum_strum_serde!(BookType);
1335enum_strum_serde!(ContingencyType);
1336enum_strum_serde!(CurrencyType);
1337enum_strum_serde!(InstrumentCloseType);
1338enum_strum_serde!(LiquiditySide);
1339enum_strum_serde!(MarketStatus);
1340enum_strum_serde!(MarketStatusAction);
1341enum_strum_serde!(OmsType);
1342enum_strum_serde!(OptionKind);
1343enum_strum_serde!(OrderSide);
1344enum_strum_serde!(OrderSideSpecified);
1345enum_strum_serde!(OrderStatus);
1346enum_strum_serde!(OrderType);
1347enum_strum_serde!(PositionSide);
1348enum_strum_serde!(PriceType);
1349enum_strum_serde!(RecordFlag);
1350enum_strum_serde!(TimeInForce);
1351enum_strum_serde!(TradingState);
1352enum_strum_serde!(TrailingOffsetType);
1353enum_strum_serde!(TriggerType);