Skip to main content

nautilus_interactive_brokers/common/enums/
contracts.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 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//! Interactive Brokers contract enumerations.
17
18use std::{fmt::Display, str::FromStr};
19
20use nautilus_model::enums::OptionKind;
21
22/// Interactive Brokers security type values used by the adapter.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
24#[serde(try_from = "String", into = "String")]
25#[cfg_attr(
26    feature = "python",
27    pyo3::pyclass(
28        module = "nautilus_trader.adapters.interactive_brokers",
29        from_py_object,
30        rename_all = "SCREAMING_SNAKE_CASE"
31    )
32)]
33#[cfg_attr(
34    feature = "python",
35    pyo3_stub_gen::derive::gen_stub_pyclass_enum(
36        module = "nautilus_trader.adapters.interactive_brokers"
37    )
38)]
39pub enum IbSecurityType {
40    /// Stock or ETF.
41    Stock,
42    /// Equity/index option.
43    Option,
44    /// Future.
45    Future,
46    /// Continuous future.
47    ContinuousFuture,
48    /// Index.
49    Index,
50    /// Futures option.
51    FuturesOption,
52    /// Forex pair.
53    ForexPair,
54    /// Combo/spread.
55    Spread,
56    /// Warrant.
57    Warrant,
58    /// Bond.
59    Bond,
60    /// Commodity.
61    Commodity,
62    /// News.
63    News,
64    /// Mutual fund.
65    MutualFund,
66    /// Crypto currency.
67    Crypto,
68    /// Contract for difference.
69    Cfd,
70}
71
72impl IbSecurityType {
73    /// Returns the IB wire string.
74    #[must_use]
75    pub const fn as_str(self) -> &'static str {
76        match self {
77            Self::Stock => "STK",
78            Self::Option => "OPT",
79            Self::Future => "FUT",
80            Self::ContinuousFuture => "CONTFUT",
81            Self::Index => "IND",
82            Self::FuturesOption => "FOP",
83            Self::ForexPair => "CASH",
84            Self::Spread => "BAG",
85            Self::Warrant => "WAR",
86            Self::Bond => "BOND",
87            Self::Commodity => "CMDTY",
88            Self::News => "NEWS",
89            Self::MutualFund => "FUND",
90            Self::Crypto => "CRYPTO",
91            Self::Cfd => "CFD",
92        }
93    }
94
95    /// Converts to the rust-ibapi security type.
96    #[must_use]
97    pub const fn ibapi_security_type(self) -> ibapi::contracts::SecurityType {
98        match self {
99            Self::Stock => ibapi::contracts::SecurityType::Stock,
100            Self::Option => ibapi::contracts::SecurityType::Option,
101            Self::Future => ibapi::contracts::SecurityType::Future,
102            Self::ContinuousFuture => ibapi::contracts::SecurityType::ContinuousFuture,
103            Self::Index => ibapi::contracts::SecurityType::Index,
104            Self::FuturesOption => ibapi::contracts::SecurityType::FuturesOption,
105            Self::ForexPair => ibapi::contracts::SecurityType::ForexPair,
106            Self::Spread => ibapi::contracts::SecurityType::Spread,
107            Self::Warrant => ibapi::contracts::SecurityType::Warrant,
108            Self::Bond => ibapi::contracts::SecurityType::Bond,
109            Self::Commodity => ibapi::contracts::SecurityType::Commodity,
110            Self::News => ibapi::contracts::SecurityType::News,
111            Self::MutualFund => ibapi::contracts::SecurityType::MutualFund,
112            Self::Crypto => ibapi::contracts::SecurityType::Crypto,
113            Self::Cfd => ibapi::contracts::SecurityType::CFD,
114        }
115    }
116}
117
118impl TryFrom<&ibapi::contracts::SecurityType> for IbSecurityType {
119    type Error = anyhow::Error;
120
121    fn try_from(value: &ibapi::contracts::SecurityType) -> Result<Self, Self::Error> {
122        match value {
123            ibapi::contracts::SecurityType::Stock => Ok(Self::Stock),
124            ibapi::contracts::SecurityType::Option => Ok(Self::Option),
125            ibapi::contracts::SecurityType::Future => Ok(Self::Future),
126            ibapi::contracts::SecurityType::ContinuousFuture => Ok(Self::ContinuousFuture),
127            ibapi::contracts::SecurityType::Index => Ok(Self::Index),
128            ibapi::contracts::SecurityType::FuturesOption => Ok(Self::FuturesOption),
129            ibapi::contracts::SecurityType::ForexPair => Ok(Self::ForexPair),
130            ibapi::contracts::SecurityType::Spread => Ok(Self::Spread),
131            ibapi::contracts::SecurityType::Warrant => Ok(Self::Warrant),
132            ibapi::contracts::SecurityType::Bond => Ok(Self::Bond),
133            ibapi::contracts::SecurityType::Commodity => Ok(Self::Commodity),
134            ibapi::contracts::SecurityType::News => Ok(Self::News),
135            ibapi::contracts::SecurityType::MutualFund => Ok(Self::MutualFund),
136            ibapi::contracts::SecurityType::Crypto => Ok(Self::Crypto),
137            ibapi::contracts::SecurityType::CFD => Ok(Self::Cfd),
138            ibapi::contracts::SecurityType::Other(value) => {
139                anyhow::bail!("Unknown IB security type: {value}")
140            }
141        }
142    }
143}
144
145impl FromStr for IbSecurityType {
146    type Err = anyhow::Error;
147
148    fn from_str(value: &str) -> Result<Self, Self::Err> {
149        match value.to_ascii_uppercase().as_str() {
150            "STK" => Ok(Self::Stock),
151            "OPT" => Ok(Self::Option),
152            "FUT" => Ok(Self::Future),
153            "CONTFUT" => Ok(Self::ContinuousFuture),
154            "IND" => Ok(Self::Index),
155            "FOP" => Ok(Self::FuturesOption),
156            "CASH" => Ok(Self::ForexPair),
157            "BAG" => Ok(Self::Spread),
158            "WAR" => Ok(Self::Warrant),
159            "BOND" => Ok(Self::Bond),
160            "CMDTY" => Ok(Self::Commodity),
161            "NEWS" => Ok(Self::News),
162            "FUND" => Ok(Self::MutualFund),
163            "CRYPTO" => Ok(Self::Crypto),
164            "CFD" => Ok(Self::Cfd),
165            _ => anyhow::bail!("Unknown IB security type: {value}"),
166        }
167    }
168}
169
170impl TryFrom<String> for IbSecurityType {
171    type Error = anyhow::Error;
172
173    fn try_from(value: String) -> Result<Self, Self::Error> {
174        Self::from_str(&value)
175    }
176}
177
178impl From<IbSecurityType> for String {
179    fn from(value: IbSecurityType) -> Self {
180        value.as_str().to_string()
181    }
182}
183
184impl Display for IbSecurityType {
185    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
186        f.write_str(self.as_str())
187    }
188}
189
190/// Interactive Brokers option right values.
191#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192#[cfg_attr(
193    feature = "python",
194    pyo3::pyclass(
195        module = "nautilus_trader.adapters.interactive_brokers",
196        from_py_object,
197        rename_all = "SCREAMING_SNAKE_CASE"
198    )
199)]
200#[cfg_attr(
201    feature = "python",
202    pyo3_stub_gen::derive::gen_stub_pyclass_enum(
203        module = "nautilus_trader.adapters.interactive_brokers"
204    )
205)]
206pub enum IbOptionRight {
207    /// Call option.
208    Call,
209    /// Put option.
210    Put,
211}
212
213impl IbOptionRight {
214    /// Returns the IB wire string.
215    #[must_use]
216    pub const fn as_str(self) -> &'static str {
217        match self {
218            Self::Call => "C",
219            Self::Put => "P",
220        }
221    }
222
223    /// Converts this option right to a Nautilus option kind.
224    #[must_use]
225    pub const fn option_kind(self) -> OptionKind {
226        match self {
227            Self::Call => OptionKind::Call,
228            Self::Put => OptionKind::Put,
229        }
230    }
231}
232
233impl FromStr for IbOptionRight {
234    type Err = anyhow::Error;
235
236    fn from_str(value: &str) -> Result<Self, Self::Err> {
237        match value.to_ascii_uppercase().as_str() {
238            "C" | "CALL" => Ok(Self::Call),
239            "P" | "PUT" => Ok(Self::Put),
240            _ => anyhow::bail!("Unknown IB option right: {value}"),
241        }
242    }
243}
244
245impl Display for IbOptionRight {
246    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247        f.write_str(self.as_str())
248    }
249}