1use serde::{Deserialize, Serialize};
19
20#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
25#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
26#[cfg_attr(
27 feature = "python",
28 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.binance", eq)
29)]
30pub enum BinanceProductType {
31 #[default]
33 Spot,
34 Margin,
36 UsdM,
38 CoinM,
40 Options,
42}
43
44impl BinanceProductType {
45 #[must_use]
47 pub const fn as_str(self) -> &'static str {
48 match self {
49 Self::Spot => "SPOT",
50 Self::Margin => "MARGIN",
51 Self::UsdM => "USD_M",
52 Self::CoinM => "COIN_M",
53 Self::Options => "OPTIONS",
54 }
55 }
56
57 #[must_use]
59 pub const fn suffix(self) -> &'static str {
60 match self {
61 Self::Spot => "-SPOT",
62 Self::Margin => "-MARGIN",
63 Self::UsdM => "-LINEAR",
64 Self::CoinM => "-INVERSE",
65 Self::Options => "-OPTION",
66 }
67 }
68
69 #[must_use]
71 pub const fn is_spot(self) -> bool {
72 matches!(self, Self::Spot | Self::Margin)
73 }
74
75 #[must_use]
77 pub const fn is_futures(self) -> bool {
78 matches!(self, Self::UsdM | Self::CoinM)
79 }
80
81 #[must_use]
83 pub const fn is_linear(self) -> bool {
84 matches!(self, Self::Spot | Self::Margin | Self::UsdM)
85 }
86
87 #[must_use]
89 pub const fn is_inverse(self) -> bool {
90 matches!(self, Self::CoinM)
91 }
92
93 #[must_use]
95 pub const fn is_options(self) -> bool {
96 matches!(self, Self::Options)
97 }
98}
99
100impl std::fmt::Display for BinanceProductType {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 write!(f, "{}", self.as_str())
103 }
104}
105
106#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
108#[cfg_attr(
109 feature = "python",
110 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.binance", eq)
111)]
112pub enum BinanceEnvironment {
113 #[default]
115 Mainnet,
116 Testnet,
118}
119
120impl BinanceEnvironment {
121 #[must_use]
123 pub const fn is_testnet(self) -> bool {
124 matches!(self, Self::Testnet)
125 }
126}
127
128#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
130#[serde(rename_all = "UPPERCASE")]
131pub enum BinanceSide {
132 Buy,
134 Sell,
136}
137
138#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
140#[serde(rename_all = "UPPERCASE")]
141pub enum BinancePositionSide {
142 Both,
144 Long,
146 Short,
148 #[serde(other)]
150 Unknown,
151}
152
153#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
155#[serde(rename_all = "lowercase")]
156pub enum BinanceMarginType {
157 Cross,
159 Isolated,
161 #[serde(other)]
163 Unknown,
164}
165
166#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
168#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
169pub enum BinanceWorkingType {
170 ContractPrice,
172 MarkPrice,
174 #[serde(other)]
176 Unknown,
177}
178
179#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
181#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
182pub enum BinanceOrderStatus {
183 New,
185 PartiallyFilled,
187 Filled,
189 Canceled,
191 PendingCancel,
193 Rejected,
195 Expired,
197 ExpiredInMatch,
199 #[serde(other)]
201 Unknown,
202}
203
204#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
206#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
207pub enum BinanceFuturesOrderType {
208 Limit,
210 Market,
212 Stop,
214 StopMarket,
216 TakeProfit,
218 TakeProfitMarket,
220 TrailingStopMarket,
222 Liquidation,
224 Adl,
226 #[serde(other)]
228 Unknown,
229}
230
231#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
233#[serde(rename_all = "UPPERCASE")]
234pub enum BinanceTimeInForce {
235 Gtc,
237 Ioc,
239 Fok,
241 Gtx,
243 Gtd,
245 #[serde(other)]
247 Unknown,
248}
249
250#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
252#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
253pub enum BinanceIncomeType {
254 Transfer,
256 WelcomeBonus,
258 RealizedPnl,
260 FundingFee,
262 Commission,
264 InsuranceClear,
266 ReferralKickback,
268 #[serde(other)]
270 Unknown,
271}
272
273#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
275#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
276pub enum BinancePriceMatch {
277 Opponent,
279 Opponent5,
281 Opponent10,
283 Opponent20,
285 Queue,
287 Queue5,
289 Queue10,
291 Queue20,
293 #[serde(other)]
295 Unknown,
296}
297
298#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
300#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
301pub enum BinanceSelfTradePreventionMode {
302 ExpireMaker,
304 ExpireTaker,
306 ExpireBoth,
308 #[serde(other)]
310 Unknown,
311}
312
313#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
315#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
316pub enum BinanceTradingStatus {
317 Trading,
319 PendingTrading,
321 PreTrading,
323 PostTrading,
325 EndOfDay,
327 Halt,
329 AuctionMatch,
331 Break,
333 #[serde(other)]
335 Unknown,
336}
337
338#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
340#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
341pub enum BinanceContractStatus {
342 Trading,
344 PendingTrading,
346 PreDelivering,
348 Delivering,
350 Delivered,
352 PreDelisting,
354 Delisting,
356 Down,
358 #[serde(other)]
360 Unknown,
361}
362
363#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
367#[serde(rename_all = "camelCase")]
368pub enum BinanceWsEventType {
369 AggTrade,
371 Trade,
373 BookTicker,
375 DepthUpdate,
377 MarkPriceUpdate,
379 Kline,
381 ForceOrder,
383 #[serde(rename = "24hrTicker")]
385 Ticker24Hr,
386 #[serde(rename = "24hrMiniTicker")]
388 MiniTicker24Hr,
389 #[serde(other)]
391 Unknown,
392}
393
394impl BinanceWsEventType {
395 #[must_use]
397 pub const fn as_str(self) -> &'static str {
398 match self {
399 Self::AggTrade => "aggTrade",
400 Self::Trade => "trade",
401 Self::BookTicker => "bookTicker",
402 Self::DepthUpdate => "depthUpdate",
403 Self::MarkPriceUpdate => "markPriceUpdate",
404 Self::Kline => "kline",
405 Self::ForceOrder => "forceOrder",
406 Self::Ticker24Hr => "24hrTicker",
407 Self::MiniTicker24Hr => "24hrMiniTicker",
408 Self::Unknown => "unknown",
409 }
410 }
411}
412
413impl std::fmt::Display for BinanceWsEventType {
414 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
415 write!(f, "{}", self.as_str())
416 }
417}
418
419#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
423#[serde(rename_all = "UPPERCASE")]
424pub enum BinanceWsMethod {
425 Subscribe,
427 Unsubscribe,
429}
430
431#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
433#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
434pub enum BinanceFilterType {
435 PriceFilter,
437 PercentPrice,
439 LotSize,
441 MarketLotSize,
443 Notional,
445 MinNotional,
447 MaxNumOrders,
449 MaxNumAlgoOrders,
451 #[serde(other)]
453 Unknown,
454}
455
456impl std::fmt::Display for BinanceEnvironment {
457 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
458 match self {
459 Self::Mainnet => write!(f, "Mainnet"),
460 Self::Testnet => write!(f, "Testnet"),
461 }
462 }
463}
464
465#[cfg(test)]
466mod tests {
467 use rstest::rstest;
468
469 use super::*;
470
471 #[rstest]
472 fn test_product_type_as_str() {
473 assert_eq!(BinanceProductType::Spot.as_str(), "SPOT");
474 assert_eq!(BinanceProductType::Margin.as_str(), "MARGIN");
475 assert_eq!(BinanceProductType::UsdM.as_str(), "USD_M");
476 assert_eq!(BinanceProductType::CoinM.as_str(), "COIN_M");
477 assert_eq!(BinanceProductType::Options.as_str(), "OPTIONS");
478 }
479
480 #[rstest]
481 fn test_product_type_suffix() {
482 assert_eq!(BinanceProductType::Spot.suffix(), "-SPOT");
483 assert_eq!(BinanceProductType::Margin.suffix(), "-MARGIN");
484 assert_eq!(BinanceProductType::UsdM.suffix(), "-LINEAR");
485 assert_eq!(BinanceProductType::CoinM.suffix(), "-INVERSE");
486 assert_eq!(BinanceProductType::Options.suffix(), "-OPTION");
487 }
488
489 #[rstest]
490 fn test_product_type_predicates() {
491 assert!(BinanceProductType::Spot.is_spot());
492 assert!(BinanceProductType::Margin.is_spot());
493 assert!(!BinanceProductType::UsdM.is_spot());
494
495 assert!(BinanceProductType::UsdM.is_futures());
496 assert!(BinanceProductType::CoinM.is_futures());
497 assert!(!BinanceProductType::Spot.is_futures());
498
499 assert!(BinanceProductType::CoinM.is_inverse());
500 assert!(!BinanceProductType::UsdM.is_inverse());
501
502 assert!(BinanceProductType::Options.is_options());
503 assert!(!BinanceProductType::Spot.is_options());
504 }
505}