use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use super::common::OrderError;
use super::{
DurationType, OrderSide, OrderStatusType, OrderType, Symbol, option_datetime_rfc3339,
option_timestamp_ms,
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Order {
#[serde(rename = "orderId", alias = "oid")]
pub order_id: String,
#[serde(rename = "strategyId", alias = "sid", default)]
pub strategy_id: Option<i64>,
#[serde(rename = "parentOrderId", alias = "poid", default)]
pub parent_order_id: Option<String>,
#[serde(rename = "accountId", alias = "a")]
pub account_id: String,
#[serde(rename = "exchSym", alias = "s")]
pub exch_sym: Symbol,
#[serde(alias = "st")]
pub status: OrderStatusType,
#[serde(alias = "sd")]
pub side: OrderSide,
#[serde(alias = "q")]
pub quantity: f64,
#[serde(rename = "limitPrice", alias = "lp", default)]
pub limit_price: Option<f64>,
#[serde(rename = "stopPrice", alias = "sp", default)]
pub stop_price: Option<f64>,
#[serde(rename = "orderType", alias = "ot")]
pub order_type: OrderType,
#[serde(alias = "dr")]
pub duration: DurationType,
#[serde(rename = "fillQuantity", alias = "fq", default)]
pub fill_quantity: Option<f64>,
#[serde(rename = "fillPrice", alias = "fp", default)]
pub fill_price: Option<f64>,
#[serde(
rename = "fillDate",
alias = "fd",
default,
with = "option_datetime_rfc3339"
)]
pub fill_date: Option<OffsetDateTime>,
#[serde(rename = "childOrders", alias = "cor", default)]
pub child_orders: Option<Vec<String>>,
#[serde(rename = "orderError", alias = "err", default)]
pub order_error: Option<OrderError>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OrderFill {
#[serde(rename = "orderId", alias = "oid")]
pub order_id: String,
#[serde(rename = "strategyId", alias = "sid", default)]
pub strategy_id: Option<i64>,
#[serde(rename = "accountId", alias = "a")]
pub account_id: String,
#[serde(rename = "exchSym", alias = "s")]
pub exch_sym: Symbol,
#[serde(alias = "st", default)]
pub status: Option<OrderStatusType>,
#[serde(alias = "sd", default)]
pub side: Option<OrderSide>,
#[serde(alias = "q", default)]
pub quantity: Option<f64>,
#[serde(alias = "p", default)]
pub price: Option<f64>,
#[serde(rename = "fillQuantity", alias = "fq", default)]
pub fill_quantity: Option<f64>,
#[serde(rename = "fillTotalQuantity", alias = "ftq", default)]
pub fill_total_quantity: Option<f64>,
#[serde(rename = "fillPrice", alias = "fp", default)]
pub fill_price: Option<f64>,
#[serde(rename = "avgFillPrice", alias = "afp", default)]
pub avg_fill_price: Option<f64>,
#[serde(
rename = "fillDate",
alias = "fd",
default,
with = "option_datetime_rfc3339"
)]
pub fill_date: Option<OffsetDateTime>,
#[serde(
rename = "timeOrderEvent",
alias = "t",
default,
with = "option_timestamp_ms"
)]
pub time_order_event: Option<OffsetDateTime>,
#[serde(rename = "orderUpdateId", alias = "ouid", default)]
pub order_update_id: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn order_from_rest() {
let json = r#"{
"orderId": "ORD001",
"accountId": "ACC001",
"exchSym": "XCME:ES.U16",
"status": "NEW",
"side": "BUY",
"quantity": 5.0,
"orderType": "2",
"duration": "0",
"limitPrice": 4500.0
}"#;
let o: Order = serde_json::from_str(json).unwrap();
assert_eq!(o.order_id, "ORD001");
assert_eq!(o.status, OrderStatusType::New);
assert_eq!(o.order_type, OrderType::Limit);
assert_eq!(o.duration, DurationType::Day);
assert_eq!(o.limit_price, Some(4500.0));
}
#[test]
fn order_from_streaming() {
let json = r#"{
"oid": "ORD001",
"a": "ACC001",
"s": "XCME:ES.U16",
"st": "NEW",
"sd": "BUY",
"q": 5.0,
"ot": "2",
"dr": "0",
"lp": 4500.0
}"#;
let o: Order = serde_json::from_str(json).unwrap();
assert_eq!(o.order_id, "ORD001");
assert_eq!(o.status, OrderStatusType::New);
assert_eq!(o.order_type, OrderType::Limit);
assert_eq!(o.limit_price, Some(4500.0));
}
#[test]
fn order_fill_from_rest() {
let json = r#"{
"orderId": "ORD001",
"accountId": "ACC001",
"exchSym": "XCME:ES.U16",
"status": "FILLED",
"side": "BUY",
"fillQuantity": 5.0,
"fillPrice": 4500.25,
"avgFillPrice": 4500.25
}"#;
let f: OrderFill = serde_json::from_str(json).unwrap();
assert_eq!(f.order_id, "ORD001");
assert_eq!(f.status, Some(OrderStatusType::Filled));
assert_eq!(f.fill_price, Some(4500.25));
}
#[test]
fn order_fill_from_streaming() {
let json = r#"{
"oid": "ORD001",
"a": "ACC001",
"s": "XCME:ES.U16",
"st": "FILLED",
"sd": "BUY",
"fq": 5.0,
"fp": 4500.25,
"afp": 4500.25
}"#;
let f: OrderFill = serde_json::from_str(json).unwrap();
assert_eq!(f.order_id, "ORD001");
assert_eq!(f.fill_quantity, Some(5.0));
assert_eq!(f.avg_fill_price, Some(4500.25));
}
}