1use crate::order::{
2 id::StrategyId,
3 request::{OrderRequestCancel, OrderRequestOpen, RequestCancel, RequestOpen},
4 state::UnindexedOrderState,
5};
6use derive_more::{Constructor, Display};
7use id::ClientOrderId;
8use rust_decimal::Decimal;
9use rustrade_instrument::{
10 Side,
11 asset::{AssetIndex, name::AssetNameExchange},
12 exchange::{ExchangeId, ExchangeIndex},
13 instrument::{InstrumentIndex, name::InstrumentNameExchange},
14};
15use serde::{Deserialize, Serialize};
16use state::{ActiveOrderState, Cancelled, InactiveOrderState, Open, OpenInFlight, OrderState};
17
18pub mod id;
20
21pub mod state;
25
26pub mod request;
30
31pub type UnindexedOrder = Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>;
33
34pub type UnindexedOrderKey = OrderKey<ExchangeId, InstrumentNameExchange>;
37
38pub type UnindexedOrderSnapshot = Order<
41 ExchangeId,
42 InstrumentNameExchange,
43 OrderState<AssetNameExchange, InstrumentNameExchange>,
44>;
45
46pub 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 position_id: _,
190 reduce_only: _, },
192 } = value;
193
194 Self {
195 key: key.clone(),
196 side: *side,
197 price: *price,
198 quantity: *quantity,
199 kind: *kind,
200 time_in_force: *time_in_force,
201 state: ActiveOrderState::OpenInFlight(OpenInFlight),
202 }
203 }
204}
205
206impl<ExchangeKey, InstrumentKey> From<Order<ExchangeKey, InstrumentKey, Open>>
207 for Order<ExchangeKey, InstrumentKey, ActiveOrderState>
208{
209 fn from(value: Order<ExchangeKey, InstrumentKey, Open>) -> Self {
210 let Order {
211 key,
212 side,
213 price,
214 quantity,
215 kind,
216 time_in_force,
217 state,
218 } = value;
219
220 Self {
221 key,
222 side,
223 price,
224 quantity,
225 kind,
226 time_in_force,
227 state: ActiveOrderState::Open(state),
228 }
229 }
230}
231
232impl<ExchangeKey, AssetKey, InstrumentKey> From<Order<ExchangeKey, InstrumentKey, Open>>
233 for Order<ExchangeKey, InstrumentKey, OrderState<AssetKey, InstrumentKey>>
234{
235 fn from(value: Order<ExchangeKey, InstrumentKey, Open>) -> Self {
236 let Order {
237 key,
238 side,
239 price,
240 quantity,
241 kind,
242 time_in_force,
243 state,
244 } = value;
245
246 Self {
247 key,
248 side,
249 price,
250 quantity,
251 kind,
252 time_in_force,
253 state: OrderState::Active(ActiveOrderState::Open(state)),
254 }
255 }
256}
257
258impl<ExchangeKey, AssetKey, InstrumentKey> From<Order<ExchangeKey, InstrumentKey, Cancelled>>
259 for Order<ExchangeKey, InstrumentKey, OrderState<AssetKey, InstrumentKey>>
260{
261 fn from(value: Order<ExchangeKey, InstrumentKey, Cancelled>) -> Self {
262 let Order {
263 key,
264 side,
265 price,
266 quantity,
267 kind,
268 time_in_force,
269 state,
270 } = value;
271
272 Self {
273 key,
274 side,
275 price,
276 quantity,
277 kind,
278 time_in_force,
279 state: OrderState::Inactive(InactiveOrderState::Cancelled(state)),
280 }
281 }
282}