1use smallvec::SmallVec;
2use thiserror::Error;
3
4use crate::{
5 backend::{LocalOrderId, OrderId, OrderIdError, OrdersBackend, RemoteOrderId},
6 instrument::InstrumentSpec,
7 order::{
8 DeferredOrderActions, DesiredVolumeOrderError, OrderGoal, PartialOrderFill,
9 RemoteTimingCondition, dependency::remote::RemoteOrderAction,
10 },
11 price::{AbsolutePrice, BidAskPriceSpread},
12 timestamp::{TickTimestamp, Timestamp},
13 volume::{
14 DirectionalExposure, DirectionalIntentVolume, DirectionlessVolume,
15 ZeroableDirectionalIntentVolume,
16 },
17};
18
19use super::{CompletedRemoteOrders, OrdersCapacitySpec, PendingRemoteOrder};
20
21#[derive(Debug, Error)]
22pub enum WorkingRemoteOrderSubmitError {
23 #[error("{0:?}")]
24 DesiredVolumeOrder(#[from] DesiredVolumeOrderError),
25
26 #[error("{0:?}")]
27 OrderId(#[from] OrderIdError),
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, Hash)]
31pub struct WorkingRemoteOrder<IS: InstrumentSpec, CS: OrdersCapacitySpec> {
32 pub(crate) local_order_id: LocalOrderId,
33 pub(crate) remote_order_id: RemoteOrderId,
34 pub(crate) dependencies: SmallVec<
35 [(
36 RemoteTimingCondition,
37 RemoteOrderAction<IS>,
38 ); CS::DEPENDENCY],
39 >,
40 pub(crate) order_goal: OrderGoal<IS>,
41 pub(crate) desired_directional_intent_volume: DirectionalIntentVolume<IS>,
42 pub(crate) booking_timestamp: Timestamp,
43 pub(crate) partial_order_fills: SmallVec<[PartialOrderFill<IS>; CS::PARTIAL_FILL]>,
44
45 pub(crate) armed_directional_exposure: ZeroableDirectionalIntentVolume<IS>,
46 pub(crate) effective_directional_exposure: ZeroableDirectionalIntentVolume<IS>,
47 pub(crate) rest_at: Option<AbsolutePrice<IS>>,
48}
49
50impl<IS: InstrumentSpec, CS: OrdersCapacitySpec> WorkingRemoteOrder<IS, CS> {
51 pub(crate) fn get_fully_filled(&self) -> Option<BidAskPriceSpread<IS>> {
52 let mut filled_volume = ZeroableDirectionalIntentVolume::ZERO;
53
54 let mut iter_partial_order_fills = self
55 .partial_order_fills
56 .iter();
57
58 let Some(mut bid_ask_price_spread) = iter_partial_order_fills
59 .next()
60 .map(|partial_order_fill| {
61 filled_volume += partial_order_fill
62 .directional_intent_volume
63 .as_zeroable();
64
65 BidAskPriceSpread {
66 ask_price: partial_order_fill.price,
67 bid_price: partial_order_fill.price,
68 }
69 })
70 else {
71 return None;
72 };
73
74 for partial_order_fill in iter_partial_order_fills {
75 filled_volume += partial_order_fill
76 .directional_intent_volume
77 .as_zeroable();
78
79 if partial_order_fill.price > bid_ask_price_spread.ask_price {
80 bid_ask_price_spread.ask_price = partial_order_fill.price;
81 }
82
83 if partial_order_fill.price < bid_ask_price_spread.bid_price {
84 bid_ask_price_spread.bid_price = partial_order_fill.price;
85 }
86 }
87
88 if filled_volume
89 < self
90 .desired_directional_intent_volume
91 .as_zeroable()
92 {
93 return None;
94 }
95
96 Some(bid_ask_price_spread)
97 }
98
99 pub(crate) fn modify_volume(
100 &mut self,
101 directional_exposure: &mut DirectionalExposure<IS>,
102 volume: &DirectionlessVolume<IS>,
103 ) {
104 let Some(desired_volume_delta) = (self.desired_directional_intent_volume
105 - DirectionalIntentVolume {
106 directional_intent: self
107 .desired_directional_intent_volume
108 .directional_intent,
109 directionless_volume: *volume,
110 })
111 else {
112 return;
113 };
114
115 let desired_volume_delta = desired_volume_delta
116 .as_zeroable()
117 .as_flipped();
118
119 directional_exposure.change_armed_directional_exposure(&desired_volume_delta);
120
121 self.desired_directional_intent_volume
122 .directionless_volume = *volume;
123
124 self.armed_directional_exposure += desired_volume_delta;
125
126 if let Some(directional_intent_volume) = self
127 .armed_directional_exposure
128 .directional_intent_volume()
129 {
130 if directional_intent_volume.directional_intent
131 != self
132 .desired_directional_intent_volume
133 .directional_intent
134 {
135 unimplemented!()
136 }
137 } else {
138 unimplemented!()
139 }
140 }
141}
142
143impl<IS: InstrumentSpec, CS: OrdersCapacitySpec> WorkingRemoteOrder<IS, CS> {
144 pub(crate) fn new(
145 local_order_id: LocalOrderId,
146 remote_order_id: RemoteOrderId,
147 dependencies: impl IntoIterator<
148 Item = (
149 RemoteTimingCondition,
150 RemoteOrderAction<IS>,
151 ),
152 >,
153 order_goal: OrderGoal<IS>,
154 desired_directional_intent_volume: DirectionalIntentVolume<IS>,
155 booking_timestamp: Timestamp,
156 rest_at: Option<AbsolutePrice<IS>>,
157 ) -> Self {
158 Self {
159 local_order_id,
160 remote_order_id,
161 dependencies: dependencies
162 .into_iter()
163 .collect(),
164 order_goal,
165 desired_directional_intent_volume,
166 booking_timestamp,
167 partial_order_fills: SmallVec::default(),
168 armed_directional_exposure: desired_directional_intent_volume.as_zeroable(),
169 effective_directional_exposure: ZeroableDirectionalIntentVolume::ZERO,
170 rest_at,
171 }
172 }
173}
174
175#[derive(Debug)]
177pub struct WorkingRemoteOrders<IS: InstrumentSpec, CS: OrdersCapacitySpec>(
178 SmallVec<[WorkingRemoteOrder<IS, CS>; CS::WORKING_REMOTE]>,
179);
180
181impl<IS: InstrumentSpec, CS: OrdersCapacitySpec> WorkingRemoteOrders<IS, CS> {
182 pub(crate) fn submit<OB: OrdersBackend<IS>>(
183 &mut self,
184 directional_exposure: &mut DirectionalExposure<IS>,
185 tick_timestamp: &TickTimestamp,
186 pending_remote_order: PendingRemoteOrder<IS, CS>,
187 remote_order_id: RemoteOrderId,
188 ) -> Result<(), WorkingRemoteOrderSubmitError>
189 where
190 IS: Send,
191 {
192 let PendingRemoteOrder {
193 submission_timestamp: _,
194 local_order_id,
195 dependencies,
196 order_goal,
197 desired_directional_intent_volume,
198 rest_at,
199 } = pending_remote_order;
200
201 let booking_timestamp = tick_timestamp.timestamp();
202
203 let working_remote_order = WorkingRemoteOrder::new(
204 local_order_id,
205 remote_order_id,
206 dependencies,
207 order_goal,
208 desired_directional_intent_volume,
209 booking_timestamp,
210 rest_at,
211 );
212
213 directional_exposure
214 .change_armed_directional_exposure(&working_remote_order.armed_directional_exposure);
215
216 self.0
217 .push(working_remote_order);
218
219 Ok(())
220 }
221
222 pub fn get(
223 &self,
224 order_id: impl Into<OrderId>,
225 ) -> Result<&WorkingRemoteOrder<IS, CS>, OrderIdError> {
226 match &order_id.into() {
227 OrderId::Local(local_order_id) => self.get_with_local(local_order_id),
228 OrderId::Remote(remote_order_id) => self.get_with_remote(remote_order_id),
229 }
230 }
231
232 pub fn get_with_local(
233 &self,
234 local_order_id: &LocalOrderId,
235 ) -> Result<&WorkingRemoteOrder<IS, CS>, OrderIdError> {
236 let Some(working_remote_order) = self
237 .0
238 .iter()
239 .find(|working_remote_order| &working_remote_order.local_order_id == local_order_id)
240 else {
241 return local_order_id.err_invalid();
242 };
243
244 Ok(working_remote_order)
245 }
246
247 pub fn get_with_remote(
248 &self,
249 remote_order_id: &RemoteOrderId,
250 ) -> Result<&WorkingRemoteOrder<IS, CS>, OrderIdError> {
251 let Some(working_remote_order) = self
252 .0
253 .iter()
254 .find(|working_remote_order| &working_remote_order.remote_order_id == remote_order_id)
255 else {
256 return remote_order_id.err_invalid();
257 };
258
259 Ok(working_remote_order)
260 }
261
262 pub(crate) fn get_mut(
263 &mut self,
264 order_id: impl Into<OrderId>,
265 ) -> Result<&mut WorkingRemoteOrder<IS, CS>, OrderIdError> {
266 match &order_id.into() {
267 OrderId::Local(local_order_id) => self.get_mut_with_local(local_order_id),
268 OrderId::Remote(remote_order_id) => self.get_mut_with_remote(remote_order_id),
269 }
270 }
271
272 pub(crate) fn get_mut_with_local(
273 &mut self,
274 local_order_id: &LocalOrderId,
275 ) -> Result<&mut WorkingRemoteOrder<IS, CS>, OrderIdError> {
276 let Some(working_remote_order) = self
277 .0
278 .iter_mut()
279 .find(|working_remote_order| &working_remote_order.local_order_id == local_order_id)
280 else {
281 return local_order_id.err_invalid();
282 };
283
284 Ok(working_remote_order)
285 }
286
287 pub(crate) fn get_mut_with_remote(
288 &mut self,
289 remote_order_id: &RemoteOrderId,
290 ) -> Result<&mut WorkingRemoteOrder<IS, CS>, OrderIdError> {
291 let Some(working_remote_order) = self
292 .0
293 .iter_mut()
294 .find(|working_remote_order| &working_remote_order.remote_order_id == remote_order_id)
295 else {
296 return remote_order_id.err_invalid();
297 };
298
299 Ok(working_remote_order)
300 }
301
302 pub(crate) fn remove(
303 &mut self,
304 directional_exposure: &mut DirectionalExposure<IS>,
305 order_id: impl Into<OrderId>,
306 ) -> Result<WorkingRemoteOrder<IS, CS>, OrderIdError>
307 where
308 IS: Send,
309 {
310 let order_id = order_id.into();
311
312 let idx = match order_id {
313 OrderId::Local(local_order_id) => self
314 .0
315 .iter()
316 .position(|working_remote_order| {
317 working_remote_order.local_order_id == local_order_id
318 }),
319 OrderId::Remote(remote_order_id) => self
320 .0
321 .iter()
322 .position(|working_remote_order| {
323 working_remote_order.remote_order_id == remote_order_id
324 }),
325 };
326
327 let Some(idx) = idx else {
328 return order_id.err_invalid();
329 };
330
331 let mut working_remote_order = self.0.swap_remove(idx);
332
333 directional_exposure.change_armed_directional_exposure(
334 &working_remote_order
335 .armed_directional_exposure
336 .as_flipped(),
337 );
338
339 working_remote_order.armed_directional_exposure = ZeroableDirectionalIntentVolume::ZERO;
340
341 Ok(working_remote_order)
342 }
343
344 pub(crate) fn processed<OB: OrdersBackend<IS>>(
345 &mut self,
346 remote_order_id: &RemoteOrderId,
347 ) -> Result<(), OrderIdError>
348 where
349 IS: Send,
350 {
351 let working_remote_order = self.get_mut_with_remote(remote_order_id)?;
352
353 let Some(rest_at) = &working_remote_order.rest_at else {
354 return Ok(());
355 };
356
357 let bid_ask_price_spread = BidAskPriceSpread {
358 ask_price: *rest_at,
359 bid_price: *rest_at,
360 };
361
362 for (_, remote_order_action) in working_remote_order
363 .dependencies
364 .iter_mut()
365 {
366 remote_order_action.parent_processed(&bid_ask_price_spread);
367 }
368
369 Ok(())
370 }
371
372 pub(crate) fn partial_fill<OB: OrdersBackend<IS>>(
373 &mut self,
374 tick_timestamp: &TickTimestamp,
375 completed_remote_orders: &mut CompletedRemoteOrders<IS, CS>,
376 deferred_order_actions: &mut DeferredOrderActions<IS>,
377 directional_exposure: &mut DirectionalExposure<IS>,
378 partial_order_fill: PartialOrderFill<IS>,
379 remote_order_id: &RemoteOrderId,
380 ) -> Result<(), OrderIdError>
381 where
382 IS: Send,
383 {
384 let working_remote_order = self.get_mut_with_remote(remote_order_id)?;
385
386 working_remote_order.armed_directional_exposure -= partial_order_fill
387 .directional_intent_volume
388 .as_zeroable();
389
390 directional_exposure.change_armed_directional_exposure(
391 &partial_order_fill
392 .directional_intent_volume
393 .as_zeroable()
394 .as_flipped(),
395 );
396
397 working_remote_order.effective_directional_exposure += partial_order_fill
398 .directional_intent_volume
399 .as_zeroable();
400
401 directional_exposure.change_effective_directional_exposure(
402 &partial_order_fill
403 .directional_intent_volume
404 .as_zeroable(),
405 );
406
407 working_remote_order
408 .partial_order_fills
409 .push(partial_order_fill);
410
411 for (remote_timing_condition, remote_order_action) in working_remote_order
412 .dependencies
413 .iter()
414 {
415 if remote_timing_condition != &RemoteTimingCondition::PartialFill {
416 continue;
417 }
418
419 deferred_order_actions.push(
420 remote_order_action
421 .clone()
422 .into_order_action(),
423 );
424 }
425
426 let Some(bid_ask_price_spread) = working_remote_order.get_fully_filled() else {
427 return Ok(());
428 };
429
430 let mut working_remote_order = self.remove(
431 directional_exposure,
432 remote_order_id,
433 )?;
434
435 if working_remote_order
436 .rest_at
437 .is_none()
438 {
439 for (_, remote_order_action) in working_remote_order
440 .dependencies
441 .iter_mut()
442 {
443 remote_order_action.parent_processed(&bid_ask_price_spread);
444 }
445 }
446
447 for (remote_timing_condition, remote_order_action) in working_remote_order
448 .dependencies
449 .iter()
450 {
451 if remote_timing_condition != &RemoteTimingCondition::FullyFilled {
452 continue;
453 }
454
455 deferred_order_actions.push(
456 remote_order_action
457 .clone()
458 .into_order_action(),
459 );
460 }
461
462 completed_remote_orders.submit::<OB>(
463 tick_timestamp,
464 working_remote_order,
465 );
466
467 Ok(())
468 }
469
470 pub(crate) async fn modify_volume<OB: OrdersBackend<IS>>(
471 &mut self,
472 orders_backend: &mut OB,
473 directional_exposure: &mut DirectionalExposure<IS>,
474 local_order_id: &LocalOrderId,
475 volume: &DirectionlessVolume<IS>,
476 ) -> Result<(), OrderIdError>
477 where
478 IS: Send,
479 {
480 let working_remote_order = self.get_mut_with_local(local_order_id)?;
481
482 working_remote_order.modify_volume(directional_exposure, volume);
483
484 orders_backend
485 .modify_order_volume(
486 &working_remote_order.remote_order_id,
487 volume,
488 )
489 .await;
490
491 Ok(())
492 }
493}
494
495impl<IS: InstrumentSpec, CS: OrdersCapacitySpec> Default for WorkingRemoteOrders<IS, CS> {
496 fn default() -> Self {
497 Self(SmallVec::default())
498 }
499}