use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum BuySell {
Buy,
Sell,
}
impl std::fmt::Display for BuySell {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BuySell::Buy => write!(f, "buy"),
BuySell::Sell => write!(f, "sell"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum OrderType {
Market,
Limit,
StopLoss,
TakeProfit,
StopLossLimit,
TakeProfitLimit,
TrailingStop,
TrailingStopLimit,
SettlePosition,
}
impl std::fmt::Display for OrderType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
OrderType::Market => "market",
OrderType::Limit => "limit",
OrderType::StopLoss => "stop-loss",
OrderType::TakeProfit => "take-profit",
OrderType::StopLossLimit => "stop-loss-limit",
OrderType::TakeProfitLimit => "take-profit-limit",
OrderType::TrailingStop => "trailing-stop",
OrderType::TrailingStopLimit => "trailing-stop-limit",
OrderType::SettlePosition => "settle-position",
};
write!(f, "{}", s)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OrderStatus {
Pending,
Open,
#[serde(alias = "partial")]
PartiallyFilled,
#[serde(alias = "filled")]
Closed,
Canceled,
Expired,
}
impl std::fmt::Display for OrderStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
OrderStatus::Pending => write!(f, "pending"),
OrderStatus::Open => write!(f, "open"),
OrderStatus::PartiallyFilled => write!(f, "partially_filled"),
OrderStatus::Closed => write!(f, "closed"),
OrderStatus::Canceled => write!(f, "canceled"),
OrderStatus::Expired => write!(f, "expired"),
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum TimeInForce {
#[default]
GTC,
IOC,
GTD,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OrderFlag {
Post,
#[serde(rename = "fcib")]
FeeInBase,
#[serde(rename = "fciq")]
FeeInQuote,
#[serde(rename = "nompp")]
NoMarketPriceProtection,
#[serde(rename = "viqc")]
VolumeInQuote,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum TriggerType {
#[default]
Last,
Index,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum SelfTradePrevent {
CancelNewest,
CancelOldest,
CancelBoth,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AssetClass {
Currency,
#[serde(alias = "crypto")]
Cryptocurrency,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LedgerType {
Trade,
Deposit,
Withdrawal,
Transfer,
Margin,
Adjustment,
Rollover,
Credit,
Settled,
Staking,
Dividend,
Sale,
#[serde(rename = "nft")]
Nft,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub enum VerificationTier {
#[default]
Starter,
Intermediate,
Pro,
}
impl VerificationTier {
pub fn rate_limit_params(&self) -> (u32, f64) {
match self {
VerificationTier::Starter => (15, 0.33),
VerificationTier::Intermediate => (20, 0.5),
VerificationTier::Pro => (20, 1.0),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(into = "u32", try_from = "u32")]
pub enum OhlcInterval {
Min1,
Min5,
Min15,
Min30,
Hour1,
Hour4,
Day1,
Week1,
Day15,
}
impl From<OhlcInterval> for u32 {
fn from(interval: OhlcInterval) -> u32 {
match interval {
OhlcInterval::Min1 => 1,
OhlcInterval::Min5 => 5,
OhlcInterval::Min15 => 15,
OhlcInterval::Min30 => 30,
OhlcInterval::Hour1 => 60,
OhlcInterval::Hour4 => 240,
OhlcInterval::Day1 => 1440,
OhlcInterval::Week1 => 10080,
OhlcInterval::Day15 => 21600,
}
}
}
impl TryFrom<u32> for OhlcInterval {
type Error = String;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
1 => Ok(OhlcInterval::Min1),
5 => Ok(OhlcInterval::Min5),
15 => Ok(OhlcInterval::Min15),
30 => Ok(OhlcInterval::Min30),
60 => Ok(OhlcInterval::Hour1),
240 => Ok(OhlcInterval::Hour4),
1440 => Ok(OhlcInterval::Day1),
10080 => Ok(OhlcInterval::Week1),
21600 => Ok(OhlcInterval::Day15),
_ => Err(format!("Invalid OHLC interval: {}", value)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buy_sell_serde() {
assert_eq!(
serde_json::to_string(&BuySell::Buy).unwrap(),
r#""buy""#
);
assert_eq!(
serde_json::from_str::<BuySell>(r#""sell""#).unwrap(),
BuySell::Sell
);
}
#[test]
fn test_order_type_serde() {
assert_eq!(
serde_json::to_string(&OrderType::StopLoss).unwrap(),
r#""stop-loss""#
);
assert_eq!(
serde_json::from_str::<OrderType>(r#""take-profit-limit""#).unwrap(),
OrderType::TakeProfitLimit
);
}
#[test]
fn test_ohlc_interval_conversion() {
assert_eq!(u32::from(OhlcInterval::Hour1), 60);
assert_eq!(OhlcInterval::try_from(1440).unwrap(), OhlcInterval::Day1);
assert!(OhlcInterval::try_from(999).is_err());
}
}