barter_execution/order/
mod.rs

1use crate::order::{
2    id::StrategyId,
3    request::{OrderRequestCancel, OrderRequestOpen, RequestCancel, RequestOpen},
4    state::UnindexedOrderState,
5};
6use barter_instrument::{
7    Side,
8    asset::{AssetIndex, name::AssetNameExchange},
9    exchange::{ExchangeId, ExchangeIndex},
10    instrument::{InstrumentIndex, name::InstrumentNameExchange},
11};
12use derive_more::{Constructor, Display};
13use id::ClientOrderId;
14use rust_decimal::Decimal;
15use serde::{Deserialize, Serialize};
16use state::{ActiveOrderState, Cancelled, InactiveOrderState, Open, OpenInFlight, OrderState};
17
18/// `Order` related identifiers.
19pub mod id;
20
21/// `Order` states.
22///
23/// eg/ `OpenInFlight`, `Open`, `Rejected`, `Expired`, etc.
24pub mod state;
25
26/// Order open and cancel request types.
27///
28/// ie/ `OrderRequestOpen` & `OrderRequestCancel`.
29pub mod request;
30
31/// Convenient type alias for an [`Order`] keyed with [`ExchangeId`] and [`InstrumentNameExchange`].
32pub type UnindexedOrder = Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>;
33
34/// Convenient type alias for an [`OrderKey`] keyed with [`ExchangeId`]
35/// and [`InstrumentNameExchange`].
36pub type UnindexedOrderKey = OrderKey<ExchangeId, InstrumentNameExchange>;
37
38/// Convenient type alias for an [`OrderSnapshot`] keyed with [`ExchangeId`], [`AssetNameExchange`],
39/// and [`InstrumentNameExchange`].
40pub type UnindexedOrderSnapshot = Order<
41    ExchangeId,
42    InstrumentNameExchange,
43    OrderState<AssetNameExchange, InstrumentNameExchange>,
44>;
45
46/// Convenient type alias for an [`Order`] [`OrderState`] snapshot.
47pub type OrderSnapshot<
48    ExchangeKey = ExchangeIndex,
49    AssetKey = AssetIndex,
50    InstrumentKey = InstrumentIndex,
51> = Order<ExchangeKey, InstrumentKey, OrderState<AssetKey, InstrumentKey>>;
52
53#[derive(
54    Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Constructor,
55)]
56
57pub struct OrderEvent<State, ExchangeKey = ExchangeIndex, InstrumentKey = InstrumentIndex> {
58    pub key: OrderKey<ExchangeKey, InstrumentKey>,
59    pub state: State,
60}
61
62#[derive(
63    Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Constructor,
64)]
65pub struct OrderKey<ExchangeKey = ExchangeIndex, InstrumentKey = InstrumentIndex> {
66    pub exchange: ExchangeKey,
67    pub instrument: InstrumentKey,
68    pub strategy: StrategyId,
69    pub cid: ClientOrderId,
70}
71
72#[derive(
73    Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Constructor,
74)]
75pub struct Order<ExchangeKey = ExchangeIndex, InstrumentKey = InstrumentIndex, State = OrderState> {
76    pub key: OrderKey<ExchangeKey, InstrumentKey>,
77    pub side: Side,
78    pub price: Decimal,
79    pub quantity: Decimal,
80    pub kind: OrderKind,
81    pub time_in_force: TimeInForce,
82    pub state: State,
83}
84
85impl<ExchangeKey, AssetKey, InstrumentKey>
86    Order<ExchangeKey, InstrumentKey, OrderState<AssetKey, InstrumentKey>>
87{
88    pub fn to_active(&self) -> Option<Order<ExchangeKey, InstrumentKey, ActiveOrderState>>
89    where
90        ExchangeKey: Clone,
91        InstrumentKey: Clone,
92    {
93        let OrderState::Active(state) = &self.state else {
94            return None;
95        };
96
97        Some(Order {
98            key: self.key.clone(),
99            side: self.side,
100            price: self.price,
101            quantity: self.quantity,
102            kind: self.kind,
103            time_in_force: self.time_in_force,
104            state: state.clone(),
105        })
106    }
107
108    pub fn to_inactive(
109        &self,
110    ) -> Option<Order<ExchangeKey, InstrumentKey, InactiveOrderState<AssetKey, InstrumentKey>>>
111    where
112        ExchangeKey: Clone,
113        AssetKey: Clone,
114        InstrumentKey: Clone,
115    {
116        let OrderState::Inactive(state) = &self.state else {
117            return None;
118        };
119
120        Some(Order {
121            key: self.key.clone(),
122            side: self.side,
123            price: self.price,
124            quantity: self.quantity,
125            kind: self.kind,
126            time_in_force: self.time_in_force,
127            state: state.clone(),
128        })
129    }
130}
131
132impl<ExchangeKey, InstrumentKey> Order<ExchangeKey, InstrumentKey, ActiveOrderState>
133where
134    ExchangeKey: Clone,
135    InstrumentKey: Clone,
136{
137    pub fn to_request_cancel(&self) -> Option<OrderRequestCancel<ExchangeKey, InstrumentKey>> {
138        let Order { key, state, .. } = self;
139
140        let request_cancel = match state {
141            ActiveOrderState::OpenInFlight(_) => RequestCancel { id: None },
142            ActiveOrderState::Open(open) => RequestCancel {
143                id: Some(open.id.clone()),
144            },
145            _ => return None,
146        };
147
148        Some(OrderRequestCancel {
149            key: key.clone(),
150            state: request_cancel,
151        })
152    }
153}
154
155#[derive(
156    Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Display,
157)]
158pub enum OrderKind {
159    Market,
160    Limit,
161}
162
163#[derive(
164    Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Display,
165)]
166pub enum TimeInForce {
167    GoodUntilCancelled { post_only: bool },
168    GoodUntilEndOfDay,
169    FillOrKill,
170    ImmediateOrCancel,
171}
172
173impl<ExchangeKey, InstrumentKey> From<&OrderRequestOpen<ExchangeKey, InstrumentKey>>
174    for Order<ExchangeKey, InstrumentKey, ActiveOrderState>
175where
176    ExchangeKey: Clone,
177    InstrumentKey: Clone,
178{
179    fn from(value: &OrderRequestOpen<ExchangeKey, InstrumentKey>) -> Self {
180        let OrderRequestOpen {
181            key,
182            state:
183                RequestOpen {
184                    side,
185                    price,
186                    quantity,
187                    kind,
188                    time_in_force,
189                },
190        } = value;
191
192        Self {
193            key: key.clone(),
194            side: *side,
195            price: *price,
196            quantity: *quantity,
197            kind: *kind,
198            time_in_force: *time_in_force,
199            state: ActiveOrderState::OpenInFlight(OpenInFlight),
200        }
201    }
202}
203
204impl<ExchangeKey, InstrumentKey> From<Order<ExchangeKey, InstrumentKey, Open>>
205    for Order<ExchangeKey, InstrumentKey, ActiveOrderState>
206{
207    fn from(value: Order<ExchangeKey, InstrumentKey, Open>) -> Self {
208        let Order {
209            key,
210            side,
211            price,
212            quantity,
213            kind,
214            time_in_force,
215            state,
216        } = value;
217
218        Self {
219            key,
220            side,
221            price,
222            quantity,
223            kind,
224            time_in_force,
225            state: ActiveOrderState::Open(state),
226        }
227    }
228}
229
230impl<ExchangeKey, AssetKey, InstrumentKey> From<Order<ExchangeKey, InstrumentKey, Open>>
231    for Order<ExchangeKey, InstrumentKey, OrderState<AssetKey, InstrumentKey>>
232{
233    fn from(value: Order<ExchangeKey, InstrumentKey, Open>) -> Self {
234        let Order {
235            key,
236            side,
237            price,
238            quantity,
239            kind,
240            time_in_force,
241            state,
242        } = value;
243
244        Self {
245            key,
246            side,
247            price,
248            quantity,
249            kind,
250            time_in_force,
251            state: OrderState::Active(ActiveOrderState::Open(state)),
252        }
253    }
254}
255
256impl<ExchangeKey, AssetKey, InstrumentKey> From<Order<ExchangeKey, InstrumentKey, Cancelled>>
257    for Order<ExchangeKey, InstrumentKey, OrderState<AssetKey, InstrumentKey>>
258{
259    fn from(value: Order<ExchangeKey, InstrumentKey, Cancelled>) -> Self {
260        let Order {
261            key,
262            side,
263            price,
264            quantity,
265            kind,
266            time_in_force,
267            state,
268        } = value;
269
270        Self {
271            key,
272            side,
273            price,
274            quantity,
275            kind,
276            time_in_force,
277            state: OrderState::Inactive(InactiveOrderState::Cancelled(state)),
278        }
279    }
280}