1use std::{fmt::Display, str::FromStr};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20#[cfg_attr(
21 feature = "python",
22 pyo3::pyclass(
23 module = "nautilus_trader.adapters.interactive_brokers",
24 from_py_object,
25 rename_all = "SCREAMING_SNAKE_CASE"
26 )
27)]
28#[cfg_attr(
29 feature = "python",
30 pyo3_stub_gen::derive::gen_stub_pyclass_enum(
31 module = "nautilus_trader.adapters.interactive_brokers"
32 )
33)]
34pub enum IbHistoricalTickType {
35 Trades,
37 BidAsk,
39}
40
41impl IbHistoricalTickType {
42 #[must_use]
44 pub const fn as_str(self) -> &'static str {
45 match self {
46 Self::Trades => "TRADES",
47 Self::BidAsk => "BID_ASK",
48 }
49 }
50}
51
52impl FromStr for IbHistoricalTickType {
53 type Err = anyhow::Error;
54
55 fn from_str(value: &str) -> Result<Self, Self::Err> {
56 match value.to_ascii_uppercase().as_str() {
57 "TRADES" => Ok(Self::Trades),
58 "BID_ASK" => Ok(Self::BidAsk),
59 _ => anyhow::bail!("Unknown IB historical tick type: {value}"),
60 }
61 }
62}
63
64impl Display for IbHistoricalTickType {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 f.write_str(self.as_str())
67 }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72#[cfg_attr(
73 feature = "python",
74 pyo3::pyclass(
75 module = "nautilus_trader.adapters.interactive_brokers",
76 from_py_object,
77 rename_all = "SCREAMING_SNAKE_CASE"
78 )
79)]
80#[cfg_attr(
81 feature = "python",
82 pyo3_stub_gen::derive::gen_stub_pyclass_enum(
83 module = "nautilus_trader.adapters.interactive_brokers"
84 )
85)]
86pub enum IbTradingHours {
87 Regular,
89 Extended,
91}
92
93impl IbTradingHours {
94 #[must_use]
96 pub const fn use_rth(self) -> bool {
97 matches!(self, Self::Regular)
98 }
99
100 #[must_use]
102 pub const fn ibapi_trading_hours(self) -> ibapi::market_data::TradingHours {
103 match self {
104 Self::Regular => ibapi::market_data::TradingHours::Regular,
105 Self::Extended => ibapi::market_data::TradingHours::Extended,
106 }
107 }
108}
109
110impl From<bool> for IbTradingHours {
111 fn from(use_rth: bool) -> Self {
112 if use_rth {
113 Self::Regular
114 } else {
115 Self::Extended
116 }
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122#[cfg_attr(
123 feature = "python",
124 pyo3::pyclass(
125 module = "nautilus_trader.adapters.interactive_brokers",
126 from_py_object,
127 rename_all = "SCREAMING_SNAKE_CASE"
128 )
129)]
130#[cfg_attr(
131 feature = "python",
132 pyo3_stub_gen::derive::gen_stub_pyclass_enum(
133 module = "nautilus_trader.adapters.interactive_brokers"
134 )
135)]
136pub enum IbHistoricalBarSize {
137 Sec,
138 Sec5,
139 Sec10,
140 Sec15,
141 Sec30,
142 Min,
143 Min2,
144 Min3,
145 Min5,
146 Min10,
147 Min15,
148 Min20,
149 Min30,
150 Hour,
151 Hour2,
152 Hour3,
153 Hour4,
154 Hour8,
155 Day,
156 Week,
157 Month,
158}
159
160impl IbHistoricalBarSize {
161 #[must_use]
163 pub const fn ibapi_bar_size(self) -> ibapi::market_data::historical::BarSize {
164 match self {
165 Self::Sec => ibapi::market_data::historical::BarSize::Sec,
166 Self::Sec5 => ibapi::market_data::historical::BarSize::Sec5,
167 Self::Sec10 => ibapi::market_data::historical::BarSize::Sec10,
168 Self::Sec15 => ibapi::market_data::historical::BarSize::Sec15,
169 Self::Sec30 => ibapi::market_data::historical::BarSize::Sec30,
170 Self::Min => ibapi::market_data::historical::BarSize::Min,
171 Self::Min2 => ibapi::market_data::historical::BarSize::Min2,
172 Self::Min3 => ibapi::market_data::historical::BarSize::Min3,
173 Self::Min5 => ibapi::market_data::historical::BarSize::Min5,
174 Self::Min10 => ibapi::market_data::historical::BarSize::Min10,
175 Self::Min15 => ibapi::market_data::historical::BarSize::Min15,
176 Self::Min20 => ibapi::market_data::historical::BarSize::Min20,
177 Self::Min30 => ibapi::market_data::historical::BarSize::Min30,
178 Self::Hour => ibapi::market_data::historical::BarSize::Hour,
179 Self::Hour2 => ibapi::market_data::historical::BarSize::Hour2,
180 Self::Hour3 => ibapi::market_data::historical::BarSize::Hour3,
181 Self::Hour4 => ibapi::market_data::historical::BarSize::Hour4,
182 Self::Hour8 => ibapi::market_data::historical::BarSize::Hour8,
183 Self::Day => ibapi::market_data::historical::BarSize::Day,
184 Self::Week => ibapi::market_data::historical::BarSize::Week,
185 Self::Month => ibapi::market_data::historical::BarSize::Month,
186 }
187 }
188}
189
190impl Display for IbHistoricalBarSize {
191 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
192 write!(f, "{}", self.ibapi_bar_size())
193 }
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198#[cfg_attr(
199 feature = "python",
200 pyo3::pyclass(
201 module = "nautilus_trader.adapters.interactive_brokers",
202 from_py_object,
203 rename_all = "SCREAMING_SNAKE_CASE"
204 )
205)]
206#[cfg_attr(
207 feature = "python",
208 pyo3_stub_gen::derive::gen_stub_pyclass_enum(
209 module = "nautilus_trader.adapters.interactive_brokers"
210 )
211)]
212pub enum IbHistoricalWhatToShow {
213 Trades,
214 Midpoint,
215 Bid,
216 Ask,
217 BidAsk,
218 HistoricalVolatility,
219 OptionImpliedVolatility,
220 FeeRate,
221 Schedule,
222 AdjustedLast,
223}
224
225impl IbHistoricalWhatToShow {
226 #[must_use]
228 pub const fn as_str(self) -> &'static str {
229 match self {
230 Self::Trades => "TRADES",
231 Self::Midpoint => "MIDPOINT",
232 Self::Bid => "BID",
233 Self::Ask => "ASK",
234 Self::BidAsk => "BID_ASK",
235 Self::HistoricalVolatility => "HISTORICAL_VOLATILITY",
236 Self::OptionImpliedVolatility => "OPTION_IMPLIED_VOLATILITY",
237 Self::FeeRate => "FEE_RATE",
238 Self::Schedule => "SCHEDULE",
239 Self::AdjustedLast => "ADJUSTED_LAST",
240 }
241 }
242
243 #[must_use]
245 pub const fn ibapi_what_to_show(self) -> ibapi::market_data::historical::WhatToShow {
246 match self {
247 Self::Trades => ibapi::market_data::historical::WhatToShow::Trades,
248 Self::Midpoint => ibapi::market_data::historical::WhatToShow::MidPoint,
249 Self::Bid => ibapi::market_data::historical::WhatToShow::Bid,
250 Self::Ask => ibapi::market_data::historical::WhatToShow::Ask,
251 Self::BidAsk => ibapi::market_data::historical::WhatToShow::BidAsk,
252 Self::HistoricalVolatility => {
253 ibapi::market_data::historical::WhatToShow::HistoricalVolatility
254 }
255 Self::OptionImpliedVolatility => {
256 ibapi::market_data::historical::WhatToShow::OptionImpliedVolatility
257 }
258 Self::FeeRate => ibapi::market_data::historical::WhatToShow::FeeRate,
259 Self::Schedule => ibapi::market_data::historical::WhatToShow::Schedule,
260 Self::AdjustedLast => ibapi::market_data::historical::WhatToShow::AdjustedLast,
261 }
262 }
263}
264
265impl Display for IbHistoricalWhatToShow {
266 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267 f.write_str(self.as_str())
268 }
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq)]
273#[cfg_attr(
274 feature = "python",
275 pyo3::pyclass(
276 module = "nautilus_trader.adapters.interactive_brokers",
277 from_py_object,
278 rename_all = "SCREAMING_SNAKE_CASE"
279 )
280)]
281#[cfg_attr(
282 feature = "python",
283 pyo3_stub_gen::derive::gen_stub_pyclass_enum(
284 module = "nautilus_trader.adapters.interactive_brokers"
285 )
286)]
287pub enum IbRealtimeBarSize {
288 Sec5,
289}
290
291impl IbRealtimeBarSize {
292 #[must_use]
294 pub const fn ibapi_bar_size(self) -> ibapi::market_data::realtime::BarSize {
295 match self {
296 Self::Sec5 => ibapi::market_data::realtime::BarSize::Sec5,
297 }
298 }
299}
300
301impl Display for IbRealtimeBarSize {
302 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
303 match self {
304 Self::Sec5 => f.write_str("5 secs"),
305 }
306 }
307}
308
309#[derive(Debug, Clone, Copy, PartialEq, Eq)]
311#[cfg_attr(
312 feature = "python",
313 pyo3::pyclass(
314 module = "nautilus_trader.adapters.interactive_brokers",
315 from_py_object,
316 rename_all = "SCREAMING_SNAKE_CASE"
317 )
318)]
319#[cfg_attr(
320 feature = "python",
321 pyo3_stub_gen::derive::gen_stub_pyclass_enum(
322 module = "nautilus_trader.adapters.interactive_brokers"
323 )
324)]
325pub enum IbRealtimeWhatToShow {
326 Trades,
327 Midpoint,
328 Bid,
329 Ask,
330}
331
332impl IbRealtimeWhatToShow {
333 #[must_use]
335 pub const fn as_str(self) -> &'static str {
336 match self {
337 Self::Trades => "TRADES",
338 Self::Midpoint => "MIDPOINT",
339 Self::Bid => "BID",
340 Self::Ask => "ASK",
341 }
342 }
343
344 #[must_use]
346 pub const fn ibapi_what_to_show(self) -> ibapi::market_data::realtime::WhatToShow {
347 match self {
348 Self::Trades => ibapi::market_data::realtime::WhatToShow::Trades,
349 Self::Midpoint => ibapi::market_data::realtime::WhatToShow::MidPoint,
350 Self::Bid => ibapi::market_data::realtime::WhatToShow::Bid,
351 Self::Ask => ibapi::market_data::realtime::WhatToShow::Ask,
352 }
353 }
354}
355
356impl Display for IbRealtimeWhatToShow {
357 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
358 f.write_str(self.as_str())
359 }
360}
361
362#[derive(Debug, Clone, Copy, PartialEq, Eq)]
364#[cfg_attr(
365 feature = "python",
366 pyo3::pyclass(
367 module = "nautilus_trader.adapters.interactive_brokers",
368 from_py_object,
369 rename_all = "SCREAMING_SNAKE_CASE"
370 )
371)]
372#[cfg_attr(
373 feature = "python",
374 pyo3_stub_gen::derive::gen_stub_pyclass_enum(
375 module = "nautilus_trader.adapters.interactive_brokers"
376 )
377)]
378pub enum IbTickType {
379 Unknown,
380 BidSize,
381 Bid,
382 Ask,
383 AskSize,
384 Last,
385 LastSize,
386 High,
387 Low,
388 Volume,
389 Close,
390 BidOption,
391 AskOption,
392 LastOption,
393 ModelOption,
394 Open,
395 Low13Week,
396 High13Week,
397 Low26Week,
398 High26Week,
399 Low52Week,
400 High52Week,
401 AvgVolume,
402 OpenInterest,
403 OptionHistoricalVol,
404 OptionImpliedVol,
405 OptionBidExch,
406 OptionAskExch,
407 OptionCallOpenInterest,
408 OptionPutOpenInterest,
409 OptionCallVolume,
410 OptionPutVolume,
411 IndexFuturePremium,
412 BidExch,
413 AskExch,
414 AuctionVolume,
415 AuctionPrice,
416 AuctionImbalance,
417 MarkPrice,
418 BidEfpComputation,
419 AskEfpComputation,
420 LastEfpComputation,
421 OpenEfpComputation,
422 HighEfpComputation,
423 LowEfpComputation,
424 CloseEfpComputation,
425 LastTimestamp,
426 Shortable,
427 FundamentalRatios,
428 RtVolume,
429 Halted,
430 BidYield,
431 AskYield,
432 LastYield,
433 CustOptionComputation,
434 TradeCount,
435 TradeRate,
436 VolumeRate,
437 LastRthTrade,
438 RtHistoricalVol,
439 IbDividends,
440 BondFactorMultiplier,
441 RegulatoryImbalance,
442 NewsTick,
443 ShortTermVolume3Min,
444 ShortTermVolume5Min,
445 ShortTermVolume10Min,
446 DelayedBid,
447 DelayedAsk,
448 DelayedLast,
449 DelayedBidSize,
450 DelayedAskSize,
451 DelayedLastSize,
452 DelayedHigh,
453 DelayedLow,
454 DelayedVolume,
455 DelayedClose,
456 DelayedOpen,
457 RtTrdVolume,
458 CreditmanMarkPrice,
459 CreditmanSlowMarkPrice,
460 DelayedBidOption,
461 DelayedAskOption,
462 DelayedLastOption,
463 DelayedModelOption,
464 LastExch,
465 LastRegTime,
466 FuturesOpenInterest,
467 AvgOptVolume,
468 DelayedLastTimestamp,
469 ShortableShares,
470 DelayedHalted,
471 Reuters2MutualFunds,
472 EtfNavClose,
473 EtfNavPriorClose,
474 EtfNavBid,
475 EtfNavAsk,
476 EtfNavLast,
477 EtfFrozenNavLast,
478 EtfNavHigh,
479 EtfNavLow,
480 SocialMarketAnalytics,
481 EstimatedIpoMidpoint,
482 FinalIpoLast,
483 DelayedYieldBid,
484 DelayedYieldAsk,
485}
486
487impl IbTickType {
488 #[must_use]
490 pub const fn as_i32(self) -> i32 {
491 match self {
492 Self::Unknown => -1,
493 Self::BidSize => 0,
494 Self::Bid => 1,
495 Self::Ask => 2,
496 Self::AskSize => 3,
497 Self::Last => 4,
498 Self::LastSize => 5,
499 Self::High => 6,
500 Self::Low => 7,
501 Self::Volume => 8,
502 Self::Close => 9,
503 Self::BidOption => 10,
504 Self::AskOption => 11,
505 Self::LastOption => 12,
506 Self::ModelOption => 13,
507 Self::Open => 14,
508 Self::Low13Week => 15,
509 Self::High13Week => 16,
510 Self::Low26Week => 17,
511 Self::High26Week => 18,
512 Self::Low52Week => 19,
513 Self::High52Week => 20,
514 Self::AvgVolume => 21,
515 Self::OpenInterest => 22,
516 Self::OptionHistoricalVol => 23,
517 Self::OptionImpliedVol => 24,
518 Self::OptionBidExch => 25,
519 Self::OptionAskExch => 26,
520 Self::OptionCallOpenInterest => 27,
521 Self::OptionPutOpenInterest => 28,
522 Self::OptionCallVolume => 29,
523 Self::OptionPutVolume => 30,
524 Self::IndexFuturePremium => 31,
525 Self::BidExch => 32,
526 Self::AskExch => 33,
527 Self::AuctionVolume => 34,
528 Self::AuctionPrice => 35,
529 Self::AuctionImbalance => 36,
530 Self::MarkPrice => 37,
531 Self::BidEfpComputation => 38,
532 Self::AskEfpComputation => 39,
533 Self::LastEfpComputation => 40,
534 Self::OpenEfpComputation => 41,
535 Self::HighEfpComputation => 42,
536 Self::LowEfpComputation => 43,
537 Self::CloseEfpComputation => 44,
538 Self::LastTimestamp => 45,
539 Self::Shortable => 46,
540 Self::FundamentalRatios => 47,
541 Self::RtVolume => 48,
542 Self::Halted => 49,
543 Self::BidYield => 50,
544 Self::AskYield => 51,
545 Self::LastYield => 52,
546 Self::CustOptionComputation => 53,
547 Self::TradeCount => 54,
548 Self::TradeRate => 55,
549 Self::VolumeRate => 56,
550 Self::LastRthTrade => 57,
551 Self::RtHistoricalVol => 58,
552 Self::IbDividends => 59,
553 Self::BondFactorMultiplier => 60,
554 Self::RegulatoryImbalance => 61,
555 Self::NewsTick => 62,
556 Self::ShortTermVolume3Min => 63,
557 Self::ShortTermVolume5Min => 64,
558 Self::ShortTermVolume10Min => 65,
559 Self::DelayedBid => 66,
560 Self::DelayedAsk => 67,
561 Self::DelayedLast => 68,
562 Self::DelayedBidSize => 69,
563 Self::DelayedAskSize => 70,
564 Self::DelayedLastSize => 71,
565 Self::DelayedHigh => 72,
566 Self::DelayedLow => 73,
567 Self::DelayedVolume => 74,
568 Self::DelayedClose => 75,
569 Self::DelayedOpen => 76,
570 Self::RtTrdVolume => 77,
571 Self::CreditmanMarkPrice => 78,
572 Self::CreditmanSlowMarkPrice => 79,
573 Self::DelayedBidOption => 80,
574 Self::DelayedAskOption => 81,
575 Self::DelayedLastOption => 82,
576 Self::DelayedModelOption => 83,
577 Self::LastExch => 84,
578 Self::LastRegTime => 85,
579 Self::FuturesOpenInterest => 86,
580 Self::AvgOptVolume => 87,
581 Self::DelayedLastTimestamp => 88,
582 Self::ShortableShares => 89,
583 Self::DelayedHalted => 90,
584 Self::Reuters2MutualFunds => 91,
585 Self::EtfNavClose => 92,
586 Self::EtfNavPriorClose => 93,
587 Self::EtfNavBid => 94,
588 Self::EtfNavAsk => 95,
589 Self::EtfNavLast => 96,
590 Self::EtfFrozenNavLast => 97,
591 Self::EtfNavHigh => 98,
592 Self::EtfNavLow => 99,
593 Self::SocialMarketAnalytics => 100,
594 Self::EstimatedIpoMidpoint => 101,
595 Self::FinalIpoLast => 102,
596 Self::DelayedYieldBid => 103,
597 Self::DelayedYieldAsk => 104,
598 }
599 }
600
601 #[must_use]
603 pub fn ibapi_tick_type(self) -> ibapi::contracts::tick_types::TickType {
604 ibapi::contracts::tick_types::TickType::from(self.as_i32())
605 }
606}
607
608impl From<i32> for IbTickType {
609 fn from(value: i32) -> Self {
610 match value {
611 0 => Self::BidSize,
612 1 => Self::Bid,
613 2 => Self::Ask,
614 3 => Self::AskSize,
615 4 => Self::Last,
616 5 => Self::LastSize,
617 6 => Self::High,
618 7 => Self::Low,
619 8 => Self::Volume,
620 9 => Self::Close,
621 10 => Self::BidOption,
622 11 => Self::AskOption,
623 12 => Self::LastOption,
624 13 => Self::ModelOption,
625 14 => Self::Open,
626 15 => Self::Low13Week,
627 16 => Self::High13Week,
628 17 => Self::Low26Week,
629 18 => Self::High26Week,
630 19 => Self::Low52Week,
631 20 => Self::High52Week,
632 21 => Self::AvgVolume,
633 22 => Self::OpenInterest,
634 23 => Self::OptionHistoricalVol,
635 24 => Self::OptionImpliedVol,
636 25 => Self::OptionBidExch,
637 26 => Self::OptionAskExch,
638 27 => Self::OptionCallOpenInterest,
639 28 => Self::OptionPutOpenInterest,
640 29 => Self::OptionCallVolume,
641 30 => Self::OptionPutVolume,
642 31 => Self::IndexFuturePremium,
643 32 => Self::BidExch,
644 33 => Self::AskExch,
645 34 => Self::AuctionVolume,
646 35 => Self::AuctionPrice,
647 36 => Self::AuctionImbalance,
648 37 => Self::MarkPrice,
649 38 => Self::BidEfpComputation,
650 39 => Self::AskEfpComputation,
651 40 => Self::LastEfpComputation,
652 41 => Self::OpenEfpComputation,
653 42 => Self::HighEfpComputation,
654 43 => Self::LowEfpComputation,
655 44 => Self::CloseEfpComputation,
656 45 => Self::LastTimestamp,
657 46 => Self::Shortable,
658 47 => Self::FundamentalRatios,
659 48 => Self::RtVolume,
660 49 => Self::Halted,
661 50 => Self::BidYield,
662 51 => Self::AskYield,
663 52 => Self::LastYield,
664 53 => Self::CustOptionComputation,
665 54 => Self::TradeCount,
666 55 => Self::TradeRate,
667 56 => Self::VolumeRate,
668 57 => Self::LastRthTrade,
669 58 => Self::RtHistoricalVol,
670 59 => Self::IbDividends,
671 60 => Self::BondFactorMultiplier,
672 61 => Self::RegulatoryImbalance,
673 62 => Self::NewsTick,
674 63 => Self::ShortTermVolume3Min,
675 64 => Self::ShortTermVolume5Min,
676 65 => Self::ShortTermVolume10Min,
677 66 => Self::DelayedBid,
678 67 => Self::DelayedAsk,
679 68 => Self::DelayedLast,
680 69 => Self::DelayedBidSize,
681 70 => Self::DelayedAskSize,
682 71 => Self::DelayedLastSize,
683 72 => Self::DelayedHigh,
684 73 => Self::DelayedLow,
685 74 => Self::DelayedVolume,
686 75 => Self::DelayedClose,
687 76 => Self::DelayedOpen,
688 77 => Self::RtTrdVolume,
689 78 => Self::CreditmanMarkPrice,
690 79 => Self::CreditmanSlowMarkPrice,
691 80 => Self::DelayedBidOption,
692 81 => Self::DelayedAskOption,
693 82 => Self::DelayedLastOption,
694 83 => Self::DelayedModelOption,
695 84 => Self::LastExch,
696 85 => Self::LastRegTime,
697 86 => Self::FuturesOpenInterest,
698 87 => Self::AvgOptVolume,
699 88 => Self::DelayedLastTimestamp,
700 89 => Self::ShortableShares,
701 90 => Self::DelayedHalted,
702 91 => Self::Reuters2MutualFunds,
703 92 => Self::EtfNavClose,
704 93 => Self::EtfNavPriorClose,
705 94 => Self::EtfNavBid,
706 95 => Self::EtfNavAsk,
707 96 => Self::EtfNavLast,
708 97 => Self::EtfFrozenNavLast,
709 98 => Self::EtfNavHigh,
710 99 => Self::EtfNavLow,
711 100 => Self::SocialMarketAnalytics,
712 101 => Self::EstimatedIpoMidpoint,
713 102 => Self::FinalIpoLast,
714 103 => Self::DelayedYieldBid,
715 104 => Self::DelayedYieldAsk,
716 _ => Self::Unknown,
717 }
718 }
719}
720
721impl Display for IbTickType {
722 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
723 write!(f, "{}", self.as_i32())
724 }
725}