use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum OrderType {
#[default]
Gtc,
Ioc,
Fok,
}
impl FromStr for OrderType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"gtc" => Ok(Self::Gtc),
"ioc" => Ok(Self::Ioc),
"fok" => Ok(Self::Fok),
other => Err(format!(
"invalid order_type '{other}' (allowed: gtc, ioc, fok)"
)),
}
}
}
impl fmt::Display for OrderType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Gtc => f.write_str("gtc"),
Self::Ioc => f.write_str("ioc"),
Self::Fok => f.write_str("fok"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum OrderSide {
Buy,
Sell,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum OrderOutcome {
Yes,
No,
Label(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum LiquidityRole {
Maker,
Taker,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum OrderStatus {
Pending,
Open,
Filled,
PartiallyFilled,
Cancelled,
Rejected,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CreateOrderRequest {
pub asset_id: String,
pub outcome: OrderOutcome,
pub side: OrderSide,
pub price: f64,
pub size: f64,
#[serde(default)]
pub order_type: OrderType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct Order {
pub id: String,
pub market_ticker: String,
pub outcome: String,
pub side: OrderSide,
pub price: f64,
pub size: f64,
pub filled: f64,
#[serde(default)]
pub fee: Option<f64>,
pub status: OrderStatus,
pub created_at: DateTime<Utc>,
#[serde(default)]
pub updated_at: Option<DateTime<Utc>>,
}
impl Order {
pub fn remaining(&self) -> f64 {
self.size - self.filled
}
pub fn is_active(&self) -> bool {
matches!(
self.status,
OrderStatus::Open | OrderStatus::PartiallyFilled
)
}
pub fn is_filled(&self) -> bool {
self.status == OrderStatus::Filled || self.filled >= self.size
}
pub fn fill_percentage(&self) -> f64 {
if self.size == 0.0 {
return 0.0;
}
self.filled / self.size
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct Fill {
pub fill_id: String,
pub order_id: String,
pub market_ticker: String,
pub outcome: String,
pub side: OrderSide,
pub price: f64,
pub size: f64,
pub is_taker: bool,
pub fee: f64,
pub created_at: DateTime<Utc>,
}