barter_execution/order/
state.rs

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
11/// Convenient type alias for an [`OrderState`] keyed with [`AssetNameExchange`]
12/// and [`InstrumentNameExchange`].
13pub 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}