1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum BuySell {
9 Buy,
11 Sell,
13}
14
15impl std::fmt::Display for BuySell {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 match self {
18 BuySell::Buy => write!(f, "buy"),
19 BuySell::Sell => write!(f, "sell"),
20 }
21 }
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
26#[serde(rename_all = "kebab-case")]
27pub enum OrderType {
28 Market,
30 Limit,
32 StopLoss,
34 TakeProfit,
36 StopLossLimit,
38 TakeProfitLimit,
40 TrailingStop,
42 TrailingStopLimit,
44 SettlePosition,
46}
47
48impl std::fmt::Display for OrderType {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 let s = match self {
51 OrderType::Market => "market",
52 OrderType::Limit => "limit",
53 OrderType::StopLoss => "stop-loss",
54 OrderType::TakeProfit => "take-profit",
55 OrderType::StopLossLimit => "stop-loss-limit",
56 OrderType::TakeProfitLimit => "take-profit-limit",
57 OrderType::TrailingStop => "trailing-stop",
58 OrderType::TrailingStopLimit => "trailing-stop-limit",
59 OrderType::SettlePosition => "settle-position",
60 };
61 write!(f, "{}", s)
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
67#[serde(rename_all = "lowercase")]
68pub enum OrderStatus {
69 Pending,
71 Open,
73 #[serde(alias = "partial")]
75 PartiallyFilled,
76 #[serde(alias = "filled")]
78 Closed,
79 Canceled,
81 Expired,
83}
84
85impl std::fmt::Display for OrderStatus {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 match self {
88 OrderStatus::Pending => write!(f, "pending"),
89 OrderStatus::Open => write!(f, "open"),
90 OrderStatus::PartiallyFilled => write!(f, "partially_filled"),
91 OrderStatus::Closed => write!(f, "closed"),
92 OrderStatus::Canceled => write!(f, "canceled"),
93 OrderStatus::Expired => write!(f, "expired"),
94 }
95 }
96}
97
98#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
100#[serde(rename_all = "UPPERCASE")]
101pub enum TimeInForce {
102 #[default]
104 GTC,
105 IOC,
107 GTD,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
113#[serde(rename_all = "lowercase")]
114pub enum OrderFlag {
115 Post,
117 #[serde(rename = "fcib")]
119 FeeInBase,
120 #[serde(rename = "fciq")]
122 FeeInQuote,
123 #[serde(rename = "nompp")]
125 NoMarketPriceProtection,
126 #[serde(rename = "viqc")]
128 VolumeInQuote,
129}
130
131#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
133#[serde(rename_all = "lowercase")]
134pub enum TriggerType {
135 #[default]
137 Last,
138 Index,
140}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
144#[serde(rename_all = "kebab-case")]
145pub enum SelfTradePrevent {
146 CancelNewest,
148 CancelOldest,
150 CancelBoth,
152}
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
156#[serde(rename_all = "lowercase")]
157pub enum AssetClass {
158 Currency,
160 #[serde(alias = "crypto")]
162 Cryptocurrency,
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
167#[serde(rename_all = "lowercase")]
168pub enum LedgerType {
169 Trade,
171 Deposit,
173 Withdrawal,
175 Transfer,
177 Margin,
179 Adjustment,
181 Rollover,
183 Credit,
185 Settled,
187 Staking,
189 Dividend,
191 Sale,
193 #[serde(rename = "nft")]
195 Nft,
196}
197
198#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
200pub enum VerificationTier {
201 #[default]
203 Starter,
204 Intermediate,
206 Pro,
208}
209
210impl VerificationTier {
211 pub fn rate_limit_params(&self) -> (u32, f64) {
215 match self {
216 VerificationTier::Starter => (15, 0.33),
217 VerificationTier::Intermediate => (20, 0.5),
218 VerificationTier::Pro => (20, 1.0),
219 }
220 }
221}
222
223#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
225#[serde(into = "u32", try_from = "u32")]
226pub enum OhlcInterval {
227 Min1,
229 Min5,
231 Min15,
233 Min30,
235 Hour1,
237 Hour4,
239 Day1,
241 Week1,
243 Day15,
245}
246
247impl From<OhlcInterval> for u32 {
248 fn from(interval: OhlcInterval) -> u32 {
249 match interval {
250 OhlcInterval::Min1 => 1,
251 OhlcInterval::Min5 => 5,
252 OhlcInterval::Min15 => 15,
253 OhlcInterval::Min30 => 30,
254 OhlcInterval::Hour1 => 60,
255 OhlcInterval::Hour4 => 240,
256 OhlcInterval::Day1 => 1440,
257 OhlcInterval::Week1 => 10080,
258 OhlcInterval::Day15 => 21600,
259 }
260 }
261}
262
263impl TryFrom<u32> for OhlcInterval {
264 type Error = String;
265
266 fn try_from(value: u32) -> Result<Self, Self::Error> {
267 match value {
268 1 => Ok(OhlcInterval::Min1),
269 5 => Ok(OhlcInterval::Min5),
270 15 => Ok(OhlcInterval::Min15),
271 30 => Ok(OhlcInterval::Min30),
272 60 => Ok(OhlcInterval::Hour1),
273 240 => Ok(OhlcInterval::Hour4),
274 1440 => Ok(OhlcInterval::Day1),
275 10080 => Ok(OhlcInterval::Week1),
276 21600 => Ok(OhlcInterval::Day15),
277 _ => Err(format!("Invalid OHLC interval: {}", value)),
278 }
279 }
280}
281
282#[cfg(test)]
283mod tests {
284 use super::*;
285
286 #[test]
287 fn test_buy_sell_serde() {
288 assert_eq!(
289 serde_json::to_string(&BuySell::Buy).unwrap(),
290 r#""buy""#
291 );
292 assert_eq!(
293 serde_json::from_str::<BuySell>(r#""sell""#).unwrap(),
294 BuySell::Sell
295 );
296 }
297
298 #[test]
299 fn test_order_type_serde() {
300 assert_eq!(
301 serde_json::to_string(&OrderType::StopLoss).unwrap(),
302 r#""stop-loss""#
303 );
304 assert_eq!(
305 serde_json::from_str::<OrderType>(r#""take-profit-limit""#).unwrap(),
306 OrderType::TakeProfitLimit
307 );
308 }
309
310 #[test]
311 fn test_ohlc_interval_conversion() {
312 assert_eq!(u32::from(OhlcInterval::Hour1), 60);
313 assert_eq!(OhlcInterval::try_from(1440).unwrap(), OhlcInterval::Day1);
314 assert!(OhlcInterval::try_from(999).is_err());
315 }
316}