1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum Category {
9 Spot,
11 Linear,
13 Inverse,
15 Option,
17}
18
19impl Category {
20 pub fn as_str(&self) -> &'static str {
22 match self {
23 Category::Spot => "spot",
24 Category::Linear => "linear",
25 Category::Inverse => "inverse",
26 Category::Option => "option",
27 }
28 }
29}
30
31impl std::fmt::Display for Category {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "{}", self.as_str())
34 }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
39pub enum Side {
40 Buy,
41 Sell,
42}
43
44impl Side {
45 pub fn as_str(&self) -> &'static str {
46 match self {
47 Side::Buy => "Buy",
48 Side::Sell => "Sell",
49 }
50 }
51}
52
53impl std::fmt::Display for Side {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(f, "{}", self.as_str())
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
61pub enum OrderType {
62 Market,
63 Limit,
64}
65
66impl OrderType {
67 pub fn as_str(&self) -> &'static str {
68 match self {
69 OrderType::Market => "Market",
70 OrderType::Limit => "Limit",
71 }
72 }
73}
74
75impl std::fmt::Display for OrderType {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "{}", self.as_str())
78 }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
83pub enum TimeInForce {
84 GTC,
86 IOC,
88 FOK,
90 PostOnly,
92}
93
94impl TimeInForce {
95 pub fn as_str(&self) -> &'static str {
96 match self {
97 TimeInForce::GTC => "GTC",
98 TimeInForce::IOC => "IOC",
99 TimeInForce::FOK => "FOK",
100 TimeInForce::PostOnly => "PostOnly",
101 }
102 }
103}
104
105impl std::fmt::Display for TimeInForce {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 write!(f, "{}", self.as_str())
108 }
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
113pub enum OrderStatus {
114 Created,
116 New,
118 Rejected,
120 PartiallyFilled,
122 PartiallyFilledCanceled,
124 Filled,
126 Cancelled,
128 Untriggered,
130 Triggered,
132 Deactivated,
134}
135
136impl OrderStatus {
137 pub fn as_str(&self) -> &'static str {
138 match self {
139 OrderStatus::Created => "Created",
140 OrderStatus::New => "New",
141 OrderStatus::Rejected => "Rejected",
142 OrderStatus::PartiallyFilled => "PartiallyFilled",
143 OrderStatus::PartiallyFilledCanceled => "PartiallyFilledCanceled",
144 OrderStatus::Filled => "Filled",
145 OrderStatus::Cancelled => "Cancelled",
146 OrderStatus::Untriggered => "Untriggered",
147 OrderStatus::Triggered => "Triggered",
148 OrderStatus::Deactivated => "Deactivated",
149 }
150 }
151
152 pub fn is_final(&self) -> bool {
154 matches!(
155 self,
156 OrderStatus::Rejected
157 | OrderStatus::PartiallyFilledCanceled
158 | OrderStatus::Filled
159 | OrderStatus::Cancelled
160 | OrderStatus::Deactivated
161 )
162 }
163
164 pub fn is_active(&self) -> bool {
166 matches!(
167 self,
168 OrderStatus::Created
169 | OrderStatus::New
170 | OrderStatus::PartiallyFilled
171 | OrderStatus::Untriggered
172 | OrderStatus::Triggered
173 )
174 }
175}
176
177impl std::fmt::Display for OrderStatus {
178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179 write!(f, "{}", self.as_str())
180 }
181}
182
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
185#[repr(i32)]
186pub enum PositionIdx {
187 OneWay = 0,
189 HedgeBuy = 1,
191 HedgeSell = 2,
193}
194
195impl From<PositionIdx> for i32 {
196 fn from(idx: PositionIdx) -> Self {
197 idx as i32
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
203#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
204pub enum AccountType {
205 Unified,
207 Contract,
209 Spot,
211 Investment,
213 Option,
215 Fund,
217}
218
219impl AccountType {
220 pub fn as_str(&self) -> &'static str {
221 match self {
222 AccountType::Unified => "UNIFIED",
223 AccountType::Contract => "CONTRACT",
224 AccountType::Spot => "SPOT",
225 AccountType::Investment => "INVESTMENT",
226 AccountType::Option => "OPTION",
227 AccountType::Fund => "FUND",
228 }
229 }
230}
231
232impl std::fmt::Display for AccountType {
233 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 write!(f, "{}", self.as_str())
235 }
236}
237
238#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
240pub enum TriggerBy {
241 LastPrice,
242 IndexPrice,
243 MarkPrice,
244}
245
246impl TriggerBy {
247 pub fn as_str(&self) -> &'static str {
248 match self {
249 TriggerBy::LastPrice => "LastPrice",
250 TriggerBy::IndexPrice => "IndexPrice",
251 TriggerBy::MarkPrice => "MarkPrice",
252 }
253 }
254}
255
256impl std::fmt::Display for TriggerBy {
257 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
258 write!(f, "{}", self.as_str())
259 }
260}
261
262#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
264pub enum KlineInterval {
265 #[serde(rename = "1")]
267 Min1,
268 #[serde(rename = "3")]
270 Min3,
271 #[serde(rename = "5")]
273 Min5,
274 #[serde(rename = "15")]
276 Min15,
277 #[serde(rename = "30")]
279 Min30,
280 #[serde(rename = "60")]
282 Hour1,
283 #[serde(rename = "120")]
285 Hour2,
286 #[serde(rename = "240")]
288 Hour4,
289 #[serde(rename = "360")]
291 Hour6,
292 #[serde(rename = "720")]
294 Hour12,
295 #[serde(rename = "D")]
297 Day1,
298 #[serde(rename = "W")]
300 Week1,
301 #[serde(rename = "M")]
303 Month1,
304}
305
306impl KlineInterval {
307 pub fn as_str(&self) -> &'static str {
308 match self {
309 KlineInterval::Min1 => "1",
310 KlineInterval::Min3 => "3",
311 KlineInterval::Min5 => "5",
312 KlineInterval::Min15 => "15",
313 KlineInterval::Min30 => "30",
314 KlineInterval::Hour1 => "60",
315 KlineInterval::Hour2 => "120",
316 KlineInterval::Hour4 => "240",
317 KlineInterval::Hour6 => "360",
318 KlineInterval::Hour12 => "720",
319 KlineInterval::Day1 => "D",
320 KlineInterval::Week1 => "W",
321 KlineInterval::Month1 => "M",
322 }
323 }
324}
325
326impl std::fmt::Display for KlineInterval {
327 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
328 write!(f, "{}", self.as_str())
329 }
330}
331
332#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
334pub enum StopOrderType {
335 TakeProfit,
336 StopLoss,
337 TrailingStop,
338 Stop,
339 PartialTakeProfit,
340 PartialStopLoss,
341}
342
343#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
345#[repr(i32)]
346pub enum TradeMode {
347 CrossMargin = 0,
349 IsolatedMargin = 1,
351}
352
353#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
355#[repr(i32)]
356pub enum PositionMode {
357 MergedSingle = 0,
359 BothSide = 3,
361}
362
363#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
365#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
366pub enum MarginMode {
367 RegularMargin,
368 PortfolioMargin,
369}
370
371#[cfg(test)]
372mod tests {
373 use super::*;
374
375 #[test]
376 fn test_category_serialization() {
377 let serialized = match serde_json::to_string(&Category::Linear) {
378 Ok(serialized) => serialized,
379 Err(err) => panic!("Failed to serialize category: {}", err),
380 };
381 assert_eq!(serialized, "\"linear\"");
382
383 let parsed = match serde_json::from_str::<Category>("\"spot\"") {
384 Ok(parsed) => parsed,
385 Err(err) => panic!("Failed to deserialize category: {}", err),
386 };
387 assert_eq!(parsed, Category::Spot);
388 }
389
390 #[test]
391 fn test_order_status_helpers() {
392 assert!(OrderStatus::Filled.is_final());
393 assert!(!OrderStatus::New.is_final());
394 assert!(OrderStatus::New.is_active());
395 assert!(!OrderStatus::Cancelled.is_active());
396 }
397
398 #[test]
399 fn test_kline_interval() {
400 assert_eq!(KlineInterval::Hour1.as_str(), "60");
401 assert_eq!(KlineInterval::Day1.as_str(), "D");
402 }
403}