1#![allow(deprecated)] use std::fmt::{self, Display, Formatter};
6
7#[cfg(not(feature = "python"))]
10use dbn_macros::MockPyo3;
11use num_enum::{IntoPrimitive, TryFromPrimitive};
12
13#[derive(
17 Debug,
18 Clone,
19 Copy,
20 PartialEq,
21 Eq,
22 PartialOrd,
23 Ord,
24 Hash,
25 Default,
26 TryFromPrimitive,
27 IntoPrimitive,
28)]
29#[cfg_attr(
30 feature = "python",
31 derive(strum::EnumIter, strum::AsRefStr),
32 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
33)]
34#[repr(u8)]
35pub enum Side {
36 Ask = b'A',
38 Bid = b'B',
40 #[default]
42 None = b'N',
43}
44
45impl From<Side> for char {
46 fn from(side: Side) -> Self {
47 u8::from(side) as char
48 }
49}
50
51#[derive(
57 Debug,
58 Clone,
59 Copy,
60 PartialEq,
61 Eq,
62 PartialOrd,
63 Ord,
64 Hash,
65 Default,
66 TryFromPrimitive,
67 IntoPrimitive,
68)]
69#[cfg_attr(
70 feature = "python",
71 derive(strum::EnumIter, strum::AsRefStr),
72 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
73)]
74#[repr(u8)]
75pub enum Action {
76 Modify = b'M',
78 Trade = b'T',
80 Fill = b'F',
82 Cancel = b'C',
84 Add = b'A',
86 Clear = b'R',
88 #[default]
90 None = b'N',
91}
92
93impl From<Action> for char {
94 fn from(action: Action) -> Self {
95 u8::from(action) as char
96 }
97}
98
99#[derive(
104 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive, IntoPrimitive,
105)]
106#[cfg_attr(
107 feature = "python",
108 derive(strum::EnumIter),
109 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
110)]
111#[non_exhaustive]
112#[repr(u8)]
113pub enum InstrumentClass {
114 Bond = b'B',
116 Call = b'C',
118 Future = b'F',
120 Stock = b'K',
122 MixedSpread = b'M',
124 Put = b'P',
126 FutureSpread = b'S',
128 OptionSpread = b'T',
130 FxSpot = b'X',
132 CommoditySpot = b'Y',
134}
135
136impl From<InstrumentClass> for char {
137 fn from(class: InstrumentClass) -> Self {
138 u8::from(class) as char
139 }
140}
141
142impl InstrumentClass {
143 pub fn is_option(&self) -> bool {
147 matches!(self, Self::Call | Self::Put | Self::OptionSpread)
148 }
149
150 pub fn is_future(&self) -> bool {
154 matches!(self, Self::Future | Self::FutureSpread)
155 }
156
157 pub fn is_spread(&self) -> bool {
160 matches!(
161 self,
162 Self::FutureSpread | Self::OptionSpread | Self::MixedSpread
163 )
164 }
165}
166
167#[derive(
169 Debug,
170 Clone,
171 Copy,
172 Default,
173 PartialEq,
174 Eq,
175 PartialOrd,
176 Ord,
177 Hash,
178 TryFromPrimitive,
179 IntoPrimitive,
180)]
181#[cfg_attr(
182 feature = "python",
183 derive(strum::EnumIter),
184 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
185)]
186#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
187#[repr(u8)]
188pub enum MatchAlgorithm {
189 #[default]
191 Undefined = b' ',
192 Fifo = b'F',
194 Configurable = b'K',
196 ProRata = b'C',
199 FifoLmm = b'T',
201 ThresholdProRata = b'O',
204 FifoTopLmm = b'S',
207 ThresholdProRataLmm = b'Q',
209 EurodollarFutures = b'Y',
211 TimeProRata = b'P',
214 InstitutionalPrioritization = b'V',
218}
219
220impl From<MatchAlgorithm> for char {
221 fn from(algo: MatchAlgorithm) -> Self {
222 u8::from(algo) as char
223 }
224}
225
226#[derive(
231 Debug,
232 Clone,
233 Copy,
234 PartialEq,
235 Eq,
236 PartialOrd,
237 Ord,
238 Hash,
239 TryFromPrimitive,
240 IntoPrimitive,
241 Default,
242)]
243#[cfg_attr(
244 feature = "python",
245 derive(strum::EnumIter, strum::AsRefStr),
246 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
247)]
248#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
249#[repr(u8)]
250pub enum UserDefinedInstrument {
251 #[default]
253 No = b'N',
254 Yes = b'Y',
256}
257
258impl From<UserDefinedInstrument> for char {
259 fn from(user_defined_instrument: UserDefinedInstrument) -> Self {
260 u8::from(user_defined_instrument) as char
261 }
262}
263
264#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive)]
268#[cfg_attr(
269 feature = "python",
270 derive(strum::EnumIter),
271 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
272)]
273#[repr(u8)]
274pub enum SType {
275 InstrumentId = 0,
277 RawSymbol = 1,
279 #[deprecated(since = "0.5.0", note = "Smart was split into Continuous and Parent.")]
281 Smart = 2,
282 Continuous = 3,
286 Parent = 4,
289 NasdaqSymbol = 5,
291 CmsSymbol = 6,
293 Isin = 7,
295 UsCode = 8,
297 BbgCompId = 9,
299 BbgCompTicker = 10,
301 Figi = 11,
303 FigiTicker = 12,
305}
306
307impl std::str::FromStr for SType {
308 type Err = crate::Error;
309
310 fn from_str(s: &str) -> Result<Self, Self::Err> {
311 match s {
312 "instrument_id" | "product_id" => Ok(SType::InstrumentId),
313 "raw_symbol" | "native" => Ok(SType::RawSymbol),
314 "smart" => Ok(SType::Smart),
315 "continuous" => Ok(SType::Continuous),
316 "parent" => Ok(SType::Parent),
317 "nasdaq_symbol" | "nasdaq" => Ok(SType::NasdaqSymbol),
318 "cms_symbol" | "cms" => Ok(SType::CmsSymbol),
319 "isin" => Ok(SType::Isin),
320 "us_code" => Ok(SType::UsCode),
321 "bbg_comp_id" => Ok(SType::BbgCompId),
322 "bbg_comp_ticker" => Ok(SType::BbgCompTicker),
323 "figi" => Ok(SType::Figi),
324 "figi_ticker" => Ok(SType::FigiTicker),
325 _ => Err(crate::Error::conversion::<Self>(s.to_owned())),
326 }
327 }
328}
329
330impl AsRef<str> for SType {
331 fn as_ref(&self) -> &str {
332 self.as_str()
333 }
334}
335
336impl SType {
337 pub const fn as_str(&self) -> &'static str {
339 match self {
340 SType::InstrumentId => "instrument_id",
341 SType::RawSymbol => "raw_symbol",
342 #[allow(deprecated)]
343 SType::Smart => "smart",
344 SType::Continuous => "continuous",
345 SType::Parent => "parent",
346 SType::NasdaqSymbol => "nasdaq_symbol",
347 SType::CmsSymbol => "cms_symbol",
348 SType::Isin => "isin",
349 SType::UsCode => "us_code",
350 SType::BbgCompId => "bbg_comp_id",
351 SType::BbgCompTicker => "bbg_comp_ticker",
352 SType::Figi => "figi",
353 SType::FigiTicker => "figi_ticker",
354 }
355 }
356}
357
358impl Display for SType {
359 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
360 f.write_str(self.as_str())
361 }
362}
363
364pub use rtype::RType;
365
366#[allow(deprecated)]
368pub mod rtype {
369 #[cfg(not(feature = "python"))]
370 use dbn_macros::MockPyo3;
371 use num_enum::TryFromPrimitive;
372
373 use super::Schema;
374
375 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive)]
382 #[cfg_attr(
383 feature = "python",
384 derive(strum::EnumIter),
385 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
386 )]
387 #[cfg_attr(not(feature = "python"), derive(MockPyo3))]
388 #[repr(u8)]
389 pub enum RType {
390 #[pyo3(name = "MBP_0")]
393 Mbp0 = 0,
394 #[pyo3(name = "MBP_1")]
397 Mbp1 = 0x01,
398 #[pyo3(name = "MBP_10")]
400 Mbp10 = 0x0A,
401 #[deprecated(
403 since = "0.3.3",
404 note = "Separated into separate rtypes for each OHLCV schema."
405 )]
406 OhlcvDeprecated = 0x11,
407 #[pyo3(name = "OHLCV_1S")]
409 Ohlcv1S = 0x20,
410 #[pyo3(name = "OHLCV_1M")]
412 Ohlcv1M = 0x21,
413 #[pyo3(name = "OHLCV_1H")]
415 Ohlcv1H = 0x22,
416 #[pyo3(name = "OHLCV_1D")]
419 Ohlcv1D = 0x23,
420 OhlcvEod = 0x24,
423 Status = 0x12,
425 InstrumentDef = 0x13,
427 Imbalance = 0x14,
429 Error = 0x15,
431 SymbolMapping = 0x16,
433 System = 0x17,
435 Statistics = 0x18,
437 Mbo = 0xA0,
439 #[pyo3(name = "CMBP_1")]
441 Cmbp1 = 0xB1,
442 #[pyo3(name = "CBBO_1S")]
445 Cbbo1S = 0xC0,
446 #[pyo3(name = "CBBO_1M")]
449 Cbbo1M = 0xC1,
450 Tcbbo = 0xC2,
453 #[pyo3(name = "BBO_1S")]
455 Bbo1S = 0xC3,
456 #[pyo3(name = "BBO_1M")]
458 Bbo1M = 0xC4,
459 }
460
461 pub const MBP_0: u8 = RType::Mbp0 as u8;
464 pub const MBP_1: u8 = RType::Mbp1 as u8;
467 pub const MBP_10: u8 = RType::Mbp10 as u8;
469 #[deprecated(
471 since = "0.3.3",
472 note = "Separated into separate rtypes for each OHLCV schema."
473 )]
474 pub const OHLCV_DEPRECATED: u8 = RType::OhlcvDeprecated as u8;
475 pub const OHLCV_1S: u8 = RType::Ohlcv1S as u8;
477 pub const OHLCV_1M: u8 = RType::Ohlcv1M as u8;
479 pub const OHLCV_1H: u8 = RType::Ohlcv1H as u8;
481 pub const OHLCV_1D: u8 = RType::Ohlcv1D as u8;
484 pub const OHLCV_EOD: u8 = RType::OhlcvEod as u8;
487 pub const STATUS: u8 = RType::Status as u8;
489 pub const INSTRUMENT_DEF: u8 = RType::InstrumentDef as u8;
491 pub const IMBALANCE: u8 = RType::Imbalance as u8;
493 pub const ERROR: u8 = RType::Error as u8;
495 pub const SYMBOL_MAPPING: u8 = RType::SymbolMapping as u8;
497 pub const SYSTEM: u8 = RType::System as u8;
499 pub const STATISTICS: u8 = RType::Statistics as u8;
501 pub const MBO: u8 = RType::Mbo as u8;
503 pub const CMBP_1: u8 = RType::Cmbp1 as u8;
505 pub const CBBO_1S: u8 = RType::Cbbo1S as u8;
507 pub const CBBO_1M: u8 = RType::Cbbo1M as u8;
509 pub const TCBBO: u8 = RType::Tcbbo as u8;
511 pub const BBO_1S: u8 = RType::Bbo1S as u8;
513 pub const BBO_1M: u8 = RType::Bbo1M as u8;
515
516 impl From<Schema> for RType {
518 fn from(schema: Schema) -> Self {
519 match schema {
520 Schema::Mbo => RType::Mbo,
521 Schema::Mbp1 | Schema::Tbbo => RType::Mbp1,
522 Schema::Mbp10 => RType::Mbp10,
523 Schema::Trades => RType::Mbp0,
524 Schema::Ohlcv1S => RType::Ohlcv1S,
525 Schema::Ohlcv1M => RType::Ohlcv1M,
526 Schema::Ohlcv1H => RType::Ohlcv1H,
527 Schema::Ohlcv1D => RType::Ohlcv1D,
528 Schema::OhlcvEod => RType::OhlcvEod,
529 Schema::Definition => RType::InstrumentDef,
530 Schema::Statistics => RType::Statistics,
531 Schema::Status => RType::Status,
532 Schema::Imbalance => RType::Imbalance,
533 Schema::Cmbp1 => RType::Cmbp1,
534 Schema::Cbbo1S => RType::Cbbo1S,
535 Schema::Cbbo1M => RType::Cbbo1M,
536 Schema::Tcbbo => RType::Tcbbo,
537 Schema::Bbo1S => RType::Bbo1S,
538 Schema::Bbo1M => RType::Bbo1M,
539 }
540 }
541 }
542
543 pub fn try_into_schema(rtype: u8) -> Option<Schema> {
548 match rtype {
549 MBP_0 => Some(Schema::Trades),
550 MBP_1 => Some(Schema::Mbp1),
551 MBP_10 => Some(Schema::Mbp10),
552 OHLCV_1S => Some(Schema::Ohlcv1S),
553 OHLCV_1M => Some(Schema::Ohlcv1M),
554 OHLCV_1H => Some(Schema::Ohlcv1H),
555 OHLCV_1D => Some(Schema::Ohlcv1D),
556 OHLCV_EOD => Some(Schema::OhlcvEod),
557 STATUS => Some(Schema::Status),
558 INSTRUMENT_DEF => Some(Schema::Definition),
559 IMBALANCE => Some(Schema::Imbalance),
560 STATISTICS => Some(Schema::Statistics),
561 MBO => Some(Schema::Mbo),
562 CMBP_1 => Some(Schema::Cmbp1),
563 CBBO_1S => Some(Schema::Cbbo1S),
564 CBBO_1M => Some(Schema::Cbbo1M),
565 TCBBO => Some(Schema::Tcbbo),
566 BBO_1S => Some(Schema::Bbo1S),
567 BBO_1M => Some(Schema::Bbo1M),
568 _ => None,
569 }
570 }
571
572 impl std::str::FromStr for RType {
573 type Err = crate::Error;
574
575 fn from_str(s: &str) -> Result<Self, Self::Err> {
576 match s {
577 "mbp-0" => Ok(RType::Mbp0),
578 "mbp-1" => Ok(RType::Mbp1),
579 "mbp-10" => Ok(RType::Mbp10),
580 "ohlcv-deprecated" => Ok(RType::OhlcvDeprecated),
581 "ohlcv-1s" => Ok(RType::Ohlcv1S),
582 "ohlcv-1m" => Ok(RType::Ohlcv1M),
583 "ohlcv-1h" => Ok(RType::Ohlcv1H),
584 "ohlcv-1d" => Ok(RType::Ohlcv1D),
585 "ohlcv-eod" => Ok(RType::OhlcvEod),
586 "status" => Ok(RType::Status),
587 "instrument-def" => Ok(RType::InstrumentDef),
588 "imbalance" => Ok(RType::Imbalance),
589 "error" => Ok(RType::Error),
590 "symbol-mapping" => Ok(RType::SymbolMapping),
591 "system" => Ok(RType::System),
592 "statistics" => Ok(RType::Statistics),
593 "mbo" => Ok(RType::Mbo),
594 "cmbp-1" => Ok(RType::Cmbp1),
595 "cbbo-1s" => Ok(RType::Cbbo1S),
596 "cbbo-1m" => Ok(RType::Cbbo1M),
597 "tcbbo" => Ok(RType::Tcbbo),
598 "bbo-1s" => Ok(RType::Bbo1S),
599 "bbo-1m" => Ok(RType::Bbo1M),
600 _ => Err(crate::Error::conversion::<Self>(s.to_owned())),
601 }
602 }
603 }
604
605 impl RType {
606 pub const fn as_str(&self) -> &'static str {
608 match self {
609 RType::Mbp0 => "mbp-0",
610 RType::Mbp1 => "mbp-1",
611 RType::Mbp10 => "mbp-10",
612 RType::OhlcvDeprecated => "ohlcv-deprecated",
613 RType::Ohlcv1S => "ohlcv-1s",
614 RType::Ohlcv1M => "ohlcv-1m",
615 RType::Ohlcv1H => "ohlcv-1h",
616 RType::Ohlcv1D => "ohlcv-1d",
617 RType::OhlcvEod => "ohlcv-eod",
618 RType::Status => "status",
619 RType::InstrumentDef => "instrument-def",
620 RType::Imbalance => "imbalance",
621 RType::Error => "error",
622 RType::SymbolMapping => "symbol-mapping",
623 RType::System => "system",
624 RType::Statistics => "statistics",
625 RType::Mbo => "mbo",
626 RType::Cmbp1 => "cmbp-1",
627 RType::Cbbo1S => "cbbo-1s",
628 RType::Cbbo1M => "cbbo-1m",
629 RType::Tcbbo => "tcbbo",
630 RType::Bbo1S => "bbo-1s",
631 RType::Bbo1M => "bbo-1m",
632 }
633 }
634 }
635}
636
637#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive)]
644#[cfg_attr(
645 feature = "python",
646 derive(strum::EnumIter),
647 pyo3::pyclass(module = "databento_dbn")
648)]
649#[cfg_attr(not(feature = "python"), derive(MockPyo3))]
650#[cfg_attr(test, derive(strum::EnumCount))]
651#[repr(u16)]
652pub enum Schema {
653 #[pyo3(name = "MBO")]
655 Mbo = 0,
656 #[pyo3(name = "MBP_1")]
658 Mbp1 = 1,
659 #[pyo3(name = "MBP_10")]
661 Mbp10 = 2,
662 #[pyo3(name = "TBBO")]
665 Tbbo = 3,
666 #[pyo3(name = "TRADES")]
668 Trades = 4,
669 #[pyo3(name = "OHLCV_1S")]
671 Ohlcv1S = 5,
672 #[pyo3(name = "OHLCV_1M")]
674 Ohlcv1M = 6,
675 #[pyo3(name = "OHLCV_1H")]
677 Ohlcv1H = 7,
678 #[pyo3(name = "OHLCV_1D")]
680 Ohlcv1D = 8,
681 #[pyo3(name = "DEFINITION")]
683 Definition = 9,
684 #[pyo3(name = "STATISTICS")]
686 Statistics = 10,
687 #[pyo3(name = "STATUS")]
689 Status = 11,
690 #[pyo3(name = "IMBALANCE")]
692 Imbalance = 12,
693 #[pyo3(name = "OHLCV_EOD")]
696 OhlcvEod = 13,
697 #[pyo3(name = "CMBP_1")]
699 Cmbp1 = 14,
700 #[pyo3(name = "CBBO_1S")]
703 Cbbo1S = 15,
704 #[pyo3(name = "CBBO_1M")]
707 Cbbo1M = 16,
708 #[pyo3(name = "TCBBO")]
711 Tcbbo = 17,
712 #[pyo3(name = "BBO_1S")]
714 Bbo1S = 18,
715 #[pyo3(name = "BBO_1M")]
717 Bbo1M = 19,
718}
719
720pub const SCHEMA_COUNT: usize = 20;
722
723impl std::str::FromStr for Schema {
724 type Err = crate::Error;
725
726 fn from_str(s: &str) -> Result<Self, Self::Err> {
727 match s {
728 "mbo" => Ok(Schema::Mbo),
729 "mbp-1" => Ok(Schema::Mbp1),
730 "mbp-10" => Ok(Schema::Mbp10),
731 "tbbo" => Ok(Schema::Tbbo),
732 "trades" => Ok(Schema::Trades),
733 "ohlcv-1s" => Ok(Schema::Ohlcv1S),
734 "ohlcv-1m" => Ok(Schema::Ohlcv1M),
735 "ohlcv-1h" => Ok(Schema::Ohlcv1H),
736 "ohlcv-1d" => Ok(Schema::Ohlcv1D),
737 "ohlcv-eod" => Ok(Schema::OhlcvEod),
738 "definition" => Ok(Schema::Definition),
739 "statistics" => Ok(Schema::Statistics),
740 "status" => Ok(Schema::Status),
741 "imbalance" => Ok(Schema::Imbalance),
742 "cmbp-1" => Ok(Schema::Cmbp1),
743 "cbbo-1s" => Ok(Schema::Cbbo1S),
744 "cbbo-1m" => Ok(Schema::Cbbo1M),
745 "tcbbo" => Ok(Schema::Tcbbo),
746 "bbo-1s" => Ok(Schema::Bbo1S),
747 "bbo-1m" => Ok(Schema::Bbo1M),
748 _ => Err(crate::Error::conversion::<Self>(s.to_owned())),
749 }
750 }
751}
752
753impl AsRef<str> for Schema {
754 fn as_ref(&self) -> &str {
755 self.as_str()
756 }
757}
758
759impl Schema {
760 pub const fn as_str(&self) -> &'static str {
762 match self {
763 Schema::Mbo => "mbo",
764 Schema::Mbp1 => "mbp-1",
765 Schema::Mbp10 => "mbp-10",
766 Schema::Tbbo => "tbbo",
767 Schema::Trades => "trades",
768 Schema::Ohlcv1S => "ohlcv-1s",
769 Schema::Ohlcv1M => "ohlcv-1m",
770 Schema::Ohlcv1H => "ohlcv-1h",
771 Schema::Ohlcv1D => "ohlcv-1d",
772 Schema::OhlcvEod => "ohlcv-eod",
773 Schema::Definition => "definition",
774 Schema::Statistics => "statistics",
775 Schema::Status => "status",
776 Schema::Imbalance => "imbalance",
777 Schema::Cmbp1 => "cmbp-1",
778 Schema::Cbbo1S => "cbbo-1s",
779 Schema::Cbbo1M => "cbbo-1m",
780 Schema::Tcbbo => "tcbbo",
781 Schema::Bbo1S => "bbo-1s",
782 Schema::Bbo1M => "bbo-1m",
783 }
784 }
785}
786
787impl Display for Schema {
788 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
789 f.write_str(self.as_str())
790 }
791}
792
793#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive)]
795#[cfg_attr(
796 feature = "python",
797 derive(strum::EnumIter),
798 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
799)]
800#[repr(u8)]
801pub enum Encoding {
802 Dbn = 0,
804 Csv = 1,
806 Json = 2,
808}
809
810impl std::str::FromStr for Encoding {
811 type Err = crate::Error;
812
813 fn from_str(s: &str) -> Result<Self, Self::Err> {
814 match s {
815 "dbn" | "dbz" => Ok(Encoding::Dbn),
816 "csv" => Ok(Encoding::Csv),
817 "json" => Ok(Encoding::Json),
818 _ => Err(crate::Error::conversion::<Self>(s.to_owned())),
819 }
820 }
821}
822
823impl AsRef<str> for Encoding {
824 fn as_ref(&self) -> &str {
825 self.as_str()
826 }
827}
828
829impl Encoding {
830 pub const fn as_str(&self) -> &'static str {
832 match self {
833 Encoding::Dbn => "dbn",
834 Encoding::Csv => "csv",
835 Encoding::Json => "json",
836 }
837 }
838}
839
840impl Display for Encoding {
841 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
842 f.write_str(self.as_str())
843 }
844}
845
846#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive)]
848#[cfg_attr(
849 feature = "python",
850 derive(strum::EnumIter),
851 pyo3::pyclass(module = "databento_dbn")
852)]
853#[cfg_attr(not(feature = "python"), derive(MockPyo3))]
854#[repr(u8)]
855pub enum Compression {
856 #[pyo3(name = "NONE")]
858 None = 0,
859 #[pyo3(name = "ZSTD")]
861 ZStd = 1,
862}
863
864impl std::str::FromStr for Compression {
865 type Err = crate::Error;
866
867 fn from_str(s: &str) -> Result<Self, Self::Err> {
868 match s {
869 "none" => Ok(Compression::None),
870 "zstd" => Ok(Compression::ZStd),
871 _ => Err(crate::Error::conversion::<Self>(s.to_owned())),
872 }
873 }
874}
875
876impl AsRef<str> for Compression {
877 fn as_ref(&self) -> &str {
878 self.as_str()
879 }
880}
881
882impl Compression {
883 pub const fn as_str(&self) -> &'static str {
885 match self {
886 Compression::None => "none",
887 Compression::ZStd => "zstd",
888 }
889 }
890}
891
892impl Display for Compression {
893 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
894 f.write_str(self.as_str())
895 }
896}
897
898pub mod flags {
900 pub const LAST: u8 = 1 << 7;
903 pub const TOB: u8 = 1 << 6;
905 pub const SNAPSHOT: u8 = 1 << 5;
907 pub const MBP: u8 = 1 << 4;
909 pub const BAD_TS_RECV: u8 = 1 << 3;
912 pub const MAYBE_BAD_BOOK: u8 = 1 << 2;
914}
915
916#[allow(clippy::manual_non_exhaustive)] #[derive(
919 Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, TryFromPrimitive,
920)]
921#[cfg_attr(
922 feature = "python",
923 derive(strum::EnumIter, strum::AsRefStr),
924 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
925)]
926#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
927#[repr(u8)]
928pub enum SecurityUpdateAction {
929 Add = b'A',
931 Modify = b'M',
933 Delete = b'D',
935 #[doc(hidden)]
936 #[deprecated = "Still present in legacy files."]
937 Invalid = b'~',
938}
939
940#[derive(
942 Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, TryFromPrimitive,
943)]
944#[cfg_attr(
945 feature = "python",
946 derive(strum::EnumIter),
947 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
948)]
949#[non_exhaustive]
950#[repr(u16)]
951pub enum StatType {
952 OpeningPrice = 1,
955 IndicativeOpeningPrice = 2,
958 SettlementPrice = 3,
962 TradingSessionLowPrice = 4,
965 TradingSessionHighPrice = 5,
968 ClearedVolume = 6,
971 LowestOffer = 7,
974 HighestBid = 8,
977 OpenInterest = 9,
981 FixingPrice = 10,
984 ClosePrice = 11,
987 NetChange = 12,
990 Vwap = 13,
994 Volatility = 14,
997 Delta = 15,
1000 UncrossingPrice = 16,
1004}
1005
1006#[derive(
1008 Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, TryFromPrimitive,
1009)]
1010#[cfg_attr(
1011 feature = "python",
1012 derive(strum::EnumIter),
1013 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1014)]
1015#[repr(u8)]
1016pub enum StatUpdateAction {
1017 New = 1,
1019 Delete = 2,
1021}
1022
1023#[derive(
1025 Clone,
1026 Copy,
1027 Debug,
1028 PartialEq,
1029 Eq,
1030 PartialOrd,
1031 Ord,
1032 Hash,
1033 IntoPrimitive,
1034 TryFromPrimitive,
1035 Default,
1036)]
1037#[cfg_attr(
1038 feature = "python",
1039 derive(strum::EnumIter),
1040 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1041)]
1042#[non_exhaustive]
1043#[repr(u16)]
1044pub enum StatusAction {
1045 #[default]
1047 None = 0,
1048 PreOpen = 1,
1050 PreCross = 2,
1052 Quoting = 3,
1054 Cross = 4,
1056 Rotation = 5,
1058 NewPriceIndication = 6,
1060 Trading = 7,
1062 Halt = 8,
1064 Pause = 9,
1066 Suspend = 10,
1068 PreClose = 11,
1070 Close = 12,
1072 PostClose = 13,
1074 SsrChange = 14,
1076 NotAvailableForTrading = 15,
1079}
1080
1081#[derive(
1084 Clone,
1085 Copy,
1086 Debug,
1087 PartialEq,
1088 Eq,
1089 PartialOrd,
1090 Ord,
1091 Hash,
1092 IntoPrimitive,
1093 TryFromPrimitive,
1094 Default,
1095)]
1096#[cfg_attr(
1097 feature = "python",
1098 derive(strum::EnumIter),
1099 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1100)]
1101#[non_exhaustive]
1102#[repr(u16)]
1103pub enum StatusReason {
1104 #[default]
1106 None = 0,
1107 Scheduled = 1,
1109 SurveillanceIntervention = 2,
1111 MarketEvent = 3,
1113 InstrumentActivation = 4,
1115 InstrumentExpiration = 5,
1117 RecoveryInProcess = 6,
1119 Regulatory = 10,
1121 Administrative = 11,
1123 NonCompliance = 12,
1126 FilingsNotCurrent = 13,
1128 SecTradingSuspension = 14,
1130 NewIssue = 15,
1132 IssueAvailable = 16,
1134 IssuesReviewed = 17,
1136 FilingReqsSatisfied = 18,
1138 NewsPending = 30,
1140 NewsReleased = 31,
1142 NewsAndResumptionTimes = 32,
1145 NewsNotForthcoming = 33,
1147 OrderImbalance = 40,
1149 LuldPause = 50,
1151 Operational = 60,
1153 AdditionalInformationRequested = 70,
1155 MergerEffective = 80,
1157 Etf = 90,
1159 CorporateAction = 100,
1161 NewSecurityOffering = 110,
1163 MarketWideHaltLevel1 = 120,
1165 MarketWideHaltLevel2 = 121,
1167 MarketWideHaltLevel3 = 122,
1169 MarketWideHaltCarryover = 123,
1172 MarketWideHaltResumption = 124,
1174 QuotationNotAvailable = 130,
1176}
1177
1178#[derive(
1180 Clone,
1181 Copy,
1182 Debug,
1183 PartialEq,
1184 Eq,
1185 PartialOrd,
1186 Ord,
1187 Hash,
1188 IntoPrimitive,
1189 TryFromPrimitive,
1190 Default,
1191)]
1192#[cfg_attr(
1193 feature = "python",
1194 derive(strum::EnumIter),
1195 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1196)]
1197#[non_exhaustive]
1198#[repr(u16)]
1199pub enum TradingEvent {
1200 #[default]
1202 None = 0,
1203 NoCancel = 1,
1205 ChangeTradingSession = 2,
1207 ImpliedMatchingOn = 3,
1209 ImpliedMatchingOff = 4,
1211}
1212
1213#[derive(
1216 Clone,
1217 Copy,
1218 Debug,
1219 PartialEq,
1220 Eq,
1221 PartialOrd,
1222 Ord,
1223 Hash,
1224 IntoPrimitive,
1225 TryFromPrimitive,
1226 Default,
1227)]
1228#[cfg_attr(
1229 feature = "python",
1230 derive(strum::EnumIter),
1231 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1232)]
1233#[repr(u8)]
1234pub enum TriState {
1235 #[default]
1237 NotAvailable = b'~',
1238 No = b'N',
1240 Yes = b'Y',
1242}
1243
1244impl From<TriState> for Option<bool> {
1245 fn from(value: TriState) -> Self {
1246 match value {
1247 TriState::NotAvailable => None,
1248 TriState::No => Some(false),
1249 TriState::Yes => Some(true),
1250 }
1251 }
1252}
1253
1254impl From<Option<bool>> for TriState {
1255 fn from(value: Option<bool>) -> Self {
1256 match value {
1257 Some(true) => Self::Yes,
1258 Some(false) => Self::No,
1259 None => Self::NotAvailable,
1260 }
1261 }
1262}
1263
1264#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1266#[cfg_attr(
1267 feature = "python",
1268 derive(strum::EnumIter),
1269 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1270)]
1271#[non_exhaustive]
1272pub enum VersionUpgradePolicy {
1273 AsIs,
1276 UpgradeToV2,
1279 #[default]
1283 UpgradeToV3,
1284}
1285
1286impl VersionUpgradePolicy {
1287 pub fn validate_compatibility(self, version: u8) -> crate::Result<()> {
1293 if version > 2 && self == VersionUpgradePolicy::UpgradeToV2 {
1294 Err(crate::Error::decode("Invalid combination of `VersionUpgradePolicy::UpgradeToV2` and input version 3. Choose either `AsIs` and `UpgradeToV3` as an upgrade policy"))
1295 } else {
1296 Ok(())
1297 }
1298 }
1299
1300 pub(crate) fn is_upgrade_situation(self, version: u8) -> bool {
1301 match (self, version) {
1302 (VersionUpgradePolicy::AsIs, _) => false,
1303 (VersionUpgradePolicy::UpgradeToV2, v) if v < 2 => true,
1304 (VersionUpgradePolicy::UpgradeToV2, _) => false,
1305 (VersionUpgradePolicy::UpgradeToV3, v) if v < 3 => true,
1306 (VersionUpgradePolicy::UpgradeToV3, _) => false,
1307 }
1308 }
1309
1310 pub fn output_version(self, input_version: u8) -> u8 {
1312 match self {
1313 VersionUpgradePolicy::AsIs => input_version,
1314 VersionUpgradePolicy::UpgradeToV2 => 2,
1315 VersionUpgradePolicy::UpgradeToV3 => 3,
1316 }
1317 }
1318}
1319
1320#[derive(
1322 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, TryFromPrimitive,
1323)]
1324#[cfg_attr(
1325 feature = "python",
1326 derive(strum::EnumIter),
1327 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1328)]
1329#[non_exhaustive]
1330#[repr(u8)]
1331pub enum ErrorCode {
1332 AuthFailed = 1,
1334 ApiKeyDeactivated = 2,
1336 ConnectionLimitExceeded = 3,
1338 SymbolResolutionFailed = 4,
1340 InvalidSubscription = 5,
1342 InternalError = 6,
1344}
1345
1346impl AsRef<str> for ErrorCode {
1347 fn as_ref(&self) -> &str {
1348 self.as_str()
1349 }
1350}
1351
1352impl ErrorCode {
1353 pub const fn as_str(&self) -> &'static str {
1355 match self {
1356 ErrorCode::AuthFailed => "auth_failed",
1357 ErrorCode::ApiKeyDeactivated => "api_key_deactivated",
1358 ErrorCode::ConnectionLimitExceeded => "connection_limit_exceeded",
1359 ErrorCode::SymbolResolutionFailed => "symbol_resolution_failed",
1360 ErrorCode::InvalidSubscription => "invalid_subscription",
1361 ErrorCode::InternalError => "internal_error",
1362 }
1363 }
1364}
1365
1366impl Display for ErrorCode {
1367 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1368 f.write_str(self.as_str())
1369 }
1370}
1371
1372#[derive(
1375 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, TryFromPrimitive,
1376)]
1377#[cfg_attr(
1378 feature = "python",
1379 derive(strum::EnumIter),
1380 pyo3::pyclass(module = "databento_dbn", rename_all = "SCREAMING_SNAKE_CASE")
1381)]
1382#[non_exhaustive]
1383#[repr(u8)]
1384pub enum SystemCode {
1385 Heartbeat = 0,
1388 SubscriptionAck = 1,
1390 SlowReaderWarning = 2,
1392 ReplayCompleted = 3,
1394}
1395
1396impl AsRef<str> for SystemCode {
1397 fn as_ref(&self) -> &str {
1398 self.as_str()
1399 }
1400}
1401
1402impl SystemCode {
1403 pub const fn as_str(&self) -> &'static str {
1405 match self {
1406 SystemCode::Heartbeat => "heartbeat",
1407 SystemCode::SubscriptionAck => "subscription_ack",
1408 SystemCode::SlowReaderWarning => "slow_reader_warning",
1409 SystemCode::ReplayCompleted => "replay_completed",
1410 }
1411 }
1412}
1413
1414impl Display for SystemCode {
1415 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1416 f.write_str(self.as_str())
1417 }
1418}
1419
1420#[cfg(feature = "serde")]
1421mod deserialize {
1422 use std::str::FromStr;
1423
1424 use serde::{de, Deserialize, Deserializer, Serialize};
1425
1426 use super::*;
1427
1428 impl<'de> Deserialize<'de> for Compression {
1429 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1430 let str = String::deserialize(deserializer)?;
1431 FromStr::from_str(&str).map_err(de::Error::custom)
1432 }
1433 }
1434
1435 impl Serialize for Compression {
1436 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1437 where
1438 S: serde::Serializer,
1439 {
1440 self.as_str().serialize(serializer)
1441 }
1442 }
1443
1444 impl<'de> Deserialize<'de> for SType {
1445 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1446 let str = String::deserialize(deserializer)?;
1447 FromStr::from_str(&str).map_err(de::Error::custom)
1448 }
1449 }
1450
1451 impl Serialize for SType {
1452 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1453 where
1454 S: serde::Serializer,
1455 {
1456 self.as_str().serialize(serializer)
1457 }
1458 }
1459
1460 impl<'de> Deserialize<'de> for Schema {
1461 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1462 let str = String::deserialize(deserializer)?;
1463 FromStr::from_str(&str).map_err(de::Error::custom)
1464 }
1465 }
1466
1467 impl Serialize for Schema {
1468 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1469 where
1470 S: serde::Serializer,
1471 {
1472 self.as_str().serialize(serializer)
1473 }
1474 }
1475
1476 impl<'de> Deserialize<'de> for Encoding {
1477 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1478 let str = String::deserialize(deserializer)?;
1479 FromStr::from_str(&str).map_err(de::Error::custom)
1480 }
1481 }
1482
1483 impl Serialize for Encoding {
1484 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1485 where
1486 S: serde::Serializer,
1487 {
1488 self.as_str().serialize(serializer)
1489 }
1490 }
1491}
1492
1493#[cfg(test)]
1494mod tests {
1495 use super::*;
1496
1497 #[test]
1498 fn validate_schema_count() {
1499 use strum::EnumCount;
1500
1501 assert_eq!(Schema::COUNT, SCHEMA_COUNT);
1502 }
1503}