nautilus_bybit/python/
enums.rs1use std::str::FromStr;
19
20use nautilus_core::python::to_pyvalue_err;
21use pyo3::{PyTypeInfo, prelude::*, types::PyType};
22use strum::IntoEnumIterator;
23
24use crate::common::enums::{
25 BybitAccountType, BybitEnvironment, BybitMarginMode, BybitPositionMode, BybitProductType,
26};
27
28#[pymethods]
29impl BybitProductType {
30 #[new]
31 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
32 let t = Self::type_object(py);
33 Self::py_from_str(&t, value)
34 }
35
36 fn __hash__(&self) -> isize {
37 *self as isize
38 }
39
40 fn __repr__(&self) -> String {
41 format!(
42 "<{}.{}: '{}'>",
43 stringify!(BybitProductType),
44 self.name(),
45 self.value(),
46 )
47 }
48
49 fn __str__(&self) -> String {
50 self.to_string()
51 }
52
53 #[getter]
54 #[must_use]
55 pub fn name(&self) -> &str {
56 self.as_ref()
57 }
58
59 #[getter]
60 #[must_use]
61 pub fn value(&self) -> String {
62 self.to_string().to_lowercase()
63 }
64
65 #[staticmethod]
66 #[must_use]
67 fn variants() -> Vec<String> {
68 Self::iter().map(|x| x.to_string()).collect()
69 }
70
71 #[classmethod]
72 #[pyo3(name = "from_str")]
73 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
74 let data_str: String = data.str()?.extract()?;
75 Self::from_str(&data_str).map_err(to_pyvalue_err)
76 }
77
78 #[classattr]
79 #[pyo3(name = "SPOT")]
80 fn py_spot() -> Self {
81 Self::Spot
82 }
83
84 #[classattr]
85 #[pyo3(name = "LINEAR")]
86 fn py_linear() -> Self {
87 Self::Linear
88 }
89
90 #[classattr]
91 #[pyo3(name = "INVERSE")]
92 fn py_inverse() -> Self {
93 Self::Inverse
94 }
95
96 #[classattr]
97 #[pyo3(name = "OPTION")]
98 fn py_option() -> Self {
99 Self::Option
100 }
101}
102
103#[pymethods]
104impl BybitEnvironment {
105 #[new]
106 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
107 let t = Self::type_object(py);
108 Self::py_from_str(&t, value)
109 }
110
111 fn __hash__(&self) -> isize {
112 *self as isize
113 }
114
115 fn __repr__(&self) -> String {
116 format!(
117 "<{}.{}: {}>",
118 stringify!(BybitEnvironment),
119 self.name(),
120 *self as u8,
121 )
122 }
123
124 fn __str__(&self) -> String {
125 self.to_string()
126 }
127
128 #[getter]
129 #[must_use]
130 pub fn name(&self) -> &str {
131 self.as_ref()
132 }
133
134 #[getter]
135 #[must_use]
136 pub fn value(&self) -> String {
137 self.to_string().to_lowercase()
138 }
139
140 #[staticmethod]
141 #[must_use]
142 fn variants() -> Vec<String> {
143 Self::iter().map(|x| x.to_string()).collect()
144 }
145
146 #[classmethod]
147 #[pyo3(name = "from_str")]
148 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
149 let data_str: String = data.str()?.extract()?;
150 Self::from_str(&data_str).map_err(to_pyvalue_err)
151 }
152
153 #[classattr]
154 #[pyo3(name = "MAINNET")]
155 fn py_mainnet() -> Self {
156 Self::Mainnet
157 }
158
159 #[classattr]
160 #[pyo3(name = "DEMO")]
161 fn py_demo() -> Self {
162 Self::Demo
163 }
164
165 #[classattr]
166 #[pyo3(name = "TESTNET")]
167 fn py_testnet() -> Self {
168 Self::Testnet
169 }
170}
171
172#[pymethods]
173impl BybitAccountType {
174 #[new]
175 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
176 let t = Self::type_object(py);
177 Self::py_from_str(&t, value)
178 }
179
180 fn __hash__(&self) -> isize {
181 *self as isize
182 }
183
184 fn __repr__(&self) -> String {
185 format!(
186 "<{}.{}: {}>",
187 stringify!(BybitAccountType),
188 self.name(),
189 *self as u8,
190 )
191 }
192
193 fn __str__(&self) -> String {
194 self.to_string()
195 }
196
197 #[getter]
198 #[must_use]
199 pub fn name(&self) -> &str {
200 self.as_ref()
201 }
202
203 #[getter]
204 #[must_use]
205 pub fn value(&self) -> String {
206 self.to_string().to_uppercase()
207 }
208
209 #[staticmethod]
210 #[must_use]
211 fn variants() -> Vec<String> {
212 Self::iter().map(|x| x.to_string()).collect()
213 }
214
215 #[classmethod]
216 #[pyo3(name = "from_str")]
217 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
218 let data_str: String = data.str()?.extract()?;
219 Self::from_str(&data_str).map_err(to_pyvalue_err)
220 }
221
222 #[classattr]
223 #[pyo3(name = "UNIFIED")]
224 fn py_unified() -> Self {
225 Self::Unified
226 }
227}
228
229#[pymethods]
230impl BybitMarginMode {
231 #[new]
232 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
233 let t = Self::type_object(py);
234 Self::py_from_str(&t, value)
235 }
236
237 fn __hash__(&self) -> isize {
238 *self as isize
239 }
240
241 fn __repr__(&self) -> String {
242 format!(
243 "<{}.{}: '{}'>",
244 stringify!(BybitMarginMode),
245 self.name(),
246 self.value(),
247 )
248 }
249
250 fn __str__(&self) -> String {
251 self.to_string()
252 }
253
254 #[getter]
255 #[must_use]
256 pub fn name(&self) -> &str {
257 self.as_ref()
258 }
259
260 #[getter]
261 #[must_use]
262 pub fn value(&self) -> String {
263 match self {
264 Self::IsolatedMargin => "ISOLATED_MARGIN".to_string(),
265 Self::RegularMargin => "REGULAR_MARGIN".to_string(),
266 Self::PortfolioMargin => "PORTFOLIO_MARGIN".to_string(),
267 }
268 }
269
270 #[staticmethod]
271 #[must_use]
272 fn variants() -> Vec<String> {
273 Self::iter().map(|x| x.to_string()).collect()
274 }
275
276 #[classmethod]
277 #[pyo3(name = "from_str")]
278 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
279 let data_str: String = data.str()?.extract()?;
280 Self::from_str(&data_str).map_err(to_pyvalue_err)
281 }
282
283 #[classattr]
284 #[pyo3(name = "ISOLATED_MARGIN")]
285 fn py_isolated_margin() -> Self {
286 Self::IsolatedMargin
287 }
288
289 #[classattr]
290 #[pyo3(name = "REGULAR_MARGIN")]
291 fn py_regular_margin() -> Self {
292 Self::RegularMargin
293 }
294
295 #[classattr]
296 #[pyo3(name = "PORTFOLIO_MARGIN")]
297 fn py_portfolio_margin() -> Self {
298 Self::PortfolioMargin
299 }
300}
301
302#[pymethods]
303impl BybitPositionMode {
304 #[new]
305 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
306 let t = Self::type_object(py);
307 Self::py_from_str(&t, value)
308 }
309
310 fn __hash__(&self) -> isize {
311 *self as isize
312 }
313
314 fn __repr__(&self) -> String {
315 format!(
316 "<{}.{}: {}>",
317 stringify!(BybitPositionMode),
318 self.name(),
319 self.value(),
320 )
321 }
322
323 fn __str__(&self) -> String {
324 self.to_string()
325 }
326
327 #[getter]
328 #[must_use]
329 pub fn name(&self) -> &str {
330 self.as_ref()
331 }
332
333 #[getter]
334 #[must_use]
335 pub fn value(&self) -> i32 {
336 *self as i32
337 }
338
339 #[staticmethod]
340 #[must_use]
341 fn variants() -> Vec<String> {
342 Self::iter().map(|x| x.to_string()).collect()
343 }
344
345 #[classmethod]
346 #[pyo3(name = "from_str")]
347 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
348 if let Ok(int_val) = data.extract::<i32>() {
350 return match int_val {
351 0 => Ok(Self::MergedSingle),
352 3 => Ok(Self::BothSides),
353 _ => Err(to_pyvalue_err(anyhow::anyhow!(
354 "Invalid BybitPositionMode value: {int_val}"
355 ))),
356 };
357 }
358
359 let data_str: String = data.str()?.extract()?;
361 Self::from_str(&data_str).map_err(to_pyvalue_err)
362 }
363
364 #[classattr]
365 #[pyo3(name = "MERGED_SINGLE")]
366 fn py_merged_single() -> Self {
367 Self::MergedSingle
368 }
369
370 #[classattr]
371 #[pyo3(name = "BOTH_SIDES")]
372 fn py_both_sides() -> Self {
373 Self::BothSides
374 }
375}