1use crate::{error::OrderError, order::id::OrderId};
2use barter_instrument::{
3 asset::{AssetIndex, name::AssetNameExchange},
4 instrument::{InstrumentIndex, name::InstrumentNameExchange},
5};
6use chrono::{DateTime, Utc};
7use derive_more::{Constructor, From};
8use rust_decimal::Decimal;
9use serde::{Deserialize, Serialize};
10
11pub type UnindexedOrderState = OrderState<AssetNameExchange, InstrumentNameExchange>;
14
15#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, From)]
16pub enum OrderState<AssetKey = AssetIndex, InstrumentKey = InstrumentIndex> {
17 Active(ActiveOrderState),
18 Inactive(InactiveOrderState<AssetKey, InstrumentKey>),
19}
20
21impl<AssetKey, InstrumentKey> OrderState<AssetKey, InstrumentKey> {
22 pub fn active<S>(state: S) -> Self
23 where
24 S: Into<ActiveOrderState>,
25 {
26 OrderState::Active(state.into())
27 }
28
29 pub fn inactive<S>(state: S) -> Self
30 where
31 S: Into<InactiveOrderState<AssetKey, InstrumentKey>>,
32 {
33 OrderState::Inactive(state.into())
34 }
35
36 pub fn fully_filled() -> Self {
37 Self::Inactive(InactiveOrderState::FullyFilled)
38 }
39
40 pub fn expired() -> Self {
41 Self::Inactive(InactiveOrderState::Expired)
42 }
43
44 pub fn time_exchange(&self) -> Option<DateTime<Utc>> {
45 match self {
46 Self::Active(active) => match active {
47 ActiveOrderState::OpenInFlight(_) => None,
48 ActiveOrderState::Open(state) => Some(state.time_exchange),
49 ActiveOrderState::CancelInFlight(state) => {
50 state.order.as_ref().map(|order| order.time_exchange)
51 }
52 },
53 Self::Inactive(inactive) => match inactive {
54 InactiveOrderState::Cancelled(state) => Some(state.time_exchange),
55 _ => None,
56 },
57 }
58 }
59}
60
61#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, From)]
62pub enum ActiveOrderState {
63 OpenInFlight(OpenInFlight),
64 Open(Open),
65 CancelInFlight(CancelInFlight),
66}
67
68impl ActiveOrderState {
69 pub fn open_meta(&self) -> Option<&Open> {
70 match self {
71 Self::OpenInFlight(_) => None,
72 Self::Open(open) => Some(open),
73 Self::CancelInFlight(cancel) => cancel.order.as_ref(),
74 }
75 }
76}
77
78#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
79pub struct OpenInFlight;
80
81#[derive(
82 Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Constructor,
83)]
84pub struct Open {
85 pub id: OrderId,
86 pub time_exchange: DateTime<Utc>,
87 pub filled_quantity: Decimal,
88}
89
90impl Open {
91 pub fn quantity_remaining(&self, initial_quantity: Decimal) -> Decimal {
92 initial_quantity - self.filled_quantity
93 }
94}
95
96#[derive(
97 Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default, Deserialize, Serialize, Constructor,
98)]
99pub struct CancelInFlight {
100 pub order: Option<Open>,
101}
102
103#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, From)]
104pub enum InactiveOrderState<AssetKey, InstrumentKey> {
105 Cancelled(Cancelled),
106 FullyFilled,
107 OpenFailed(OrderError<AssetKey, InstrumentKey>),
108 Expired,
109}
110
111#[derive(
112 Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Constructor,
113)]
114pub struct Cancelled {
115 pub id: OrderId,
116 pub time_exchange: DateTime<Utc>,
117}