1use 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, BybitMarginAction, BybitMarginMode, BybitPositionIdx,
26 BybitPositionMode, BybitProductType,
27};
28
29#[pymethods]
30#[pyo3_stub_gen::derive::gen_stub_pymethods]
31impl BybitProductType {
32 #[new]
34 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
35 let t = Self::type_object(py);
36 Self::py_from_str(&t, value)
37 }
38
39 fn __hash__(&self) -> isize {
40 *self as isize
41 }
42
43 fn __repr__(&self) -> String {
44 format!(
45 "<{}.{}: '{}'>",
46 stringify!(BybitProductType),
47 self.name(),
48 self.value(),
49 )
50 }
51
52 fn __str__(&self) -> String {
53 self.to_string()
54 }
55
56 #[getter]
57 #[must_use]
58 pub fn name(&self) -> &str {
59 self.as_ref()
60 }
61
62 #[getter]
63 #[must_use]
64 pub fn value(&self) -> String {
65 self.to_string().to_lowercase()
66 }
67
68 #[staticmethod]
69 #[must_use]
70 fn variants() -> Vec<String> {
71 Self::iter().map(|x| x.to_string()).collect()
72 }
73
74 #[classmethod]
75 #[pyo3(name = "from_str")]
76 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
77 let data_str: String = data.str()?.extract()?;
78 Self::from_str(&data_str).map_err(to_pyvalue_err)
79 }
80}
81
82#[pymethods]
83#[pyo3_stub_gen::derive::gen_stub_pymethods]
84impl BybitEnvironment {
85 #[new]
87 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
88 let t = Self::type_object(py);
89 Self::py_from_str(&t, value)
90 }
91
92 fn __hash__(&self) -> isize {
93 *self as isize
94 }
95
96 fn __repr__(&self) -> String {
97 format!(
98 "<{}.{}: {}>",
99 stringify!(BybitEnvironment),
100 self.name(),
101 *self as u8,
102 )
103 }
104
105 fn __str__(&self) -> String {
106 self.to_string()
107 }
108
109 #[getter]
110 #[must_use]
111 pub fn name(&self) -> &str {
112 self.as_ref()
113 }
114
115 #[getter]
116 #[must_use]
117 pub fn value(&self) -> String {
118 self.to_string().to_lowercase()
119 }
120
121 #[staticmethod]
122 #[must_use]
123 fn variants() -> Vec<String> {
124 Self::iter().map(|x| x.to_string()).collect()
125 }
126
127 #[classmethod]
128 #[pyo3(name = "from_str")]
129 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
130 let data_str: String = data.str()?.extract()?;
131 Self::from_str(&data_str).map_err(to_pyvalue_err)
132 }
133}
134
135#[pymethods]
136#[pyo3_stub_gen::derive::gen_stub_pymethods]
137impl BybitAccountType {
138 #[new]
140 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
141 let t = Self::type_object(py);
142 Self::py_from_str(&t, value)
143 }
144
145 fn __hash__(&self) -> isize {
146 *self as isize
147 }
148
149 fn __repr__(&self) -> String {
150 format!(
151 "<{}.{}: {}>",
152 stringify!(BybitAccountType),
153 self.name(),
154 *self as u8,
155 )
156 }
157
158 fn __str__(&self) -> String {
159 self.to_string()
160 }
161
162 #[getter]
163 #[must_use]
164 pub fn name(&self) -> &str {
165 self.as_ref()
166 }
167
168 #[getter]
169 #[must_use]
170 pub fn value(&self) -> String {
171 self.to_string().to_uppercase()
172 }
173
174 #[staticmethod]
175 #[must_use]
176 fn variants() -> Vec<String> {
177 Self::iter().map(|x| x.to_string()).collect()
178 }
179
180 #[classmethod]
181 #[pyo3(name = "from_str")]
182 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
183 let data_str: String = data.str()?.extract()?;
184 Self::from_str(&data_str).map_err(to_pyvalue_err)
185 }
186}
187
188#[pymethods]
189#[pyo3_stub_gen::derive::gen_stub_pymethods]
190impl BybitMarginMode {
191 #[new]
193 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
194 let t = Self::type_object(py);
195 Self::py_from_str(&t, value)
196 }
197
198 fn __hash__(&self) -> isize {
199 *self as isize
200 }
201
202 fn __repr__(&self) -> String {
203 format!(
204 "<{}.{}: '{}'>",
205 stringify!(BybitMarginMode),
206 self.name(),
207 self.value(),
208 )
209 }
210
211 fn __str__(&self) -> String {
212 self.to_string()
213 }
214
215 #[getter]
216 #[must_use]
217 pub fn name(&self) -> &str {
218 self.as_ref()
219 }
220
221 #[getter]
222 #[must_use]
223 pub fn value(&self) -> &'static str {
224 match self {
225 Self::IsolatedMargin => "ISOLATED_MARGIN",
226 Self::RegularMargin => "REGULAR_MARGIN",
227 Self::PortfolioMargin => "PORTFOLIO_MARGIN",
228 }
229 }
230
231 #[staticmethod]
232 #[must_use]
233 fn variants() -> Vec<String> {
234 Self::iter().map(|x| x.to_string()).collect()
235 }
236
237 #[classmethod]
238 #[pyo3(name = "from_str")]
239 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
240 let data_str: String = data.str()?.extract()?;
241 Self::from_str(&data_str).map_err(to_pyvalue_err)
242 }
243}
244
245#[pymethods]
246#[pyo3_stub_gen::derive::gen_stub_pymethods]
247impl BybitPositionMode {
248 #[new]
250 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
251 let t = Self::type_object(py);
252 Self::py_from_str(&t, value)
253 }
254
255 fn __hash__(&self) -> isize {
256 *self as isize
257 }
258
259 fn __repr__(&self) -> String {
260 format!(
261 "<{}.{}: {}>",
262 stringify!(BybitPositionMode),
263 self.name(),
264 self.value(),
265 )
266 }
267
268 fn __str__(&self) -> String {
269 self.to_string()
270 }
271
272 #[getter]
273 #[must_use]
274 pub fn name(&self) -> &str {
275 self.as_ref()
276 }
277
278 #[getter]
279 #[must_use]
280 pub fn value(&self) -> i32 {
281 *self as i32
282 }
283
284 #[staticmethod]
285 #[must_use]
286 fn variants() -> Vec<String> {
287 Self::iter().map(|x| x.to_string()).collect()
288 }
289
290 #[classmethod]
291 #[pyo3(name = "from_str")]
292 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
293 if let Ok(int_val) = data.extract::<i32>() {
295 return match int_val {
296 0 => Ok(Self::MergedSingle),
297 3 => Ok(Self::BothSides),
298 _ => Err(to_pyvalue_err(anyhow::anyhow!(
299 "Invalid BybitPositionMode value: {int_val}"
300 ))),
301 };
302 }
303
304 let data_str: String = data.str()?.extract()?;
306 Self::from_str(&data_str).map_err(to_pyvalue_err)
307 }
308}
309
310#[pymethods]
311#[pyo3_stub_gen::derive::gen_stub_pymethods]
312impl BybitPositionIdx {
313 #[new]
315 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
316 let t = Self::type_object(py);
317 Self::py_from_str(&t, value)
318 }
319
320 fn __hash__(&self) -> isize {
321 *self as isize
322 }
323
324 fn __repr__(&self) -> String {
325 format!(
326 "<{}.{}: {}>",
327 stringify!(BybitPositionIdx),
328 self.name(),
329 self.value(),
330 )
331 }
332
333 fn __str__(&self) -> String {
334 self.to_string()
335 }
336
337 #[getter]
338 #[must_use]
339 pub fn name(&self) -> &str {
340 self.as_ref()
341 }
342
343 #[getter]
344 #[must_use]
345 pub fn value(&self) -> i32 {
346 *self as i32
347 }
348
349 #[staticmethod]
350 #[must_use]
351 fn variants() -> Vec<String> {
352 Self::iter().map(|x| x.to_string()).collect()
353 }
354
355 #[classmethod]
356 #[pyo3(name = "from_str")]
357 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
358 if let Ok(int_val) = data.extract::<i32>() {
359 return match int_val {
360 0 => Ok(Self::OneWay),
361 1 => Ok(Self::BuyHedge),
362 2 => Ok(Self::SellHedge),
363 _ => Err(to_pyvalue_err(anyhow::anyhow!(
364 "Invalid BybitPositionIdx value: {int_val}"
365 ))),
366 };
367 }
368
369 let data_str: String = data.str()?.extract()?;
370 Self::from_str(&data_str).map_err(to_pyvalue_err)
371 }
372}
373
374#[pymethods]
375#[pyo3_stub_gen::derive::gen_stub_pymethods]
376impl BybitMarginAction {
377 #[new]
379 fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
380 let t = Self::type_object(py);
381 Self::py_from_str(&t, value)
382 }
383
384 fn __repr__(&self) -> String {
385 format!(
386 "<{}.{}: '{}'>",
387 stringify!(BybitMarginAction),
388 self.name(),
389 self.value(),
390 )
391 }
392
393 fn __str__(&self) -> String {
394 self.to_string()
395 }
396
397 #[getter]
398 #[must_use]
399 pub fn name(&self) -> &str {
400 self.as_ref()
401 }
402
403 #[getter]
404 #[must_use]
405 pub fn value(&self) -> String {
406 self.to_string()
407 }
408
409 #[staticmethod]
410 #[must_use]
411 fn variants() -> Vec<String> {
412 Self::iter().map(|x| x.to_string()).collect()
413 }
414
415 #[classmethod]
416 #[pyo3(name = "from_str")]
417 fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
418 let data_str: String = data.str()?.extract()?;
419 Self::from_str(&data_str).map_err(to_pyvalue_err)
420 }
421}