apple_quant_algorithmic/order_manager/
remote_pending.rs1use smallvec::SmallVec;
2use thiserror::Error;
3use tracing::instrument;
4
5#[allow(unused_imports)]
6use tracing::trace;
7
8use crate::{
9 backend::{
10 LocalOrderId, OrderIdError, OrdersBackend, OrdersBackendSubmitRemoteOrderError,
11 RemoteOrderId,
12 },
13 order::{
14 DeferredOrderActions, DesiredVolumeOrder, DesiredVolumeOrderError, OrderAction,
15 RemoteOrder, RemoteOrderTracker, RemoteTimingCondition, TriggerError,
16 },
17 timestamp::{TickTimestamp, Timestamp, Timestamped},
18 volume::{DirectionalExposure, DirectionalIntentVolume, ZeroableVolume},
19 instrument::InstrumentSpec, price::AbsolutePrice,
20};
21
22use super::{
23 OrdersCapacitySpec, PendingClientCancelError, WorkingRemoteOrderSubmitError,
24 WorkingRemoteOrders,
25};
26
27#[derive(Debug, Error)]
28pub enum PendingRemoteSubmitError {
29 #[error("{0:?}")]
30 DesiredVolumeOrder(#[from] DesiredVolumeOrderError),
31
32 #[error("{0:?}")]
33 OrdersBackendSubmitRemoteOrder(#[from] OrdersBackendSubmitRemoteOrderError),
34}
35
36#[derive(Debug, Error)]
37pub enum PendingRemoteProcessedError {
38 #[error("{0:?}")]
39 OrderId(#[from] OrderIdError),
40
41 #[error("{0:?}")]
42 PendingClientCancel(#[from] PendingClientCancelError),
43
44 #[error("{0:?}")]
45 WorkingRemoteOrderSubmit(#[from] WorkingRemoteOrderSubmitError),
46
47 #[error("{0:?}")]
48 Trigger(#[from] TriggerError),
49}
50
51pub struct PendingRemoteOrder<
52 IS: InstrumentSpec,
53 CS: OrdersCapacitySpec,
54> {
55 pub(crate) submission_timestamp: Timestamp,
56 pub(crate) local_order_id: LocalOrderId,
57
58 pub(crate) dependencies: SmallVec<[(
59 RemoteTimingCondition,
60 OrderAction<IS>,
61 ); core::direct_const_arg!(CS::DEPENDENCY)]>,
62
63 pub(crate) desired_directional_intent_volume: DirectionalIntentVolume<IS>,
64 pub(crate) rest_at: Option<AbsolutePrice<IS>>,
65 pub(crate) cancel_on_process: bool,
66}
67
68impl<
69 IS: InstrumentSpec,
70 CS: OrdersCapacitySpec,
71> PendingRemoteOrder<IS, CS> {
72 pub(crate) fn new(
73 submission_timestamp: Timestamp,
74 local_order_id: LocalOrderId,
75 dependencies: impl IntoIterator<Item = (
76 RemoteTimingCondition,
77 OrderAction<IS>,
78 )>,
79 desired_directional_intent_volume: DirectionalIntentVolume<IS>,
80 rest_at: Option<AbsolutePrice<IS>>,
81 ) -> Self {
82 Self {
83 submission_timestamp,
84 local_order_id,
85 dependencies: dependencies.into_iter().collect(),
86 desired_directional_intent_volume,
87 rest_at,
88 cancel_on_process: false,
89 }
90 }
91}
92
93pub struct PendingRemoteOrders<
95 IS: InstrumentSpec,
96 CS: OrdersCapacitySpec,
97>(SmallVec<[PendingRemoteOrder<IS, CS>; core::direct_const_arg!(CS::PENDING_REMOTE)]>);
98
99impl<
100 IS: InstrumentSpec,
101 CS: OrdersCapacitySpec,
102> PendingRemoteOrders<IS, CS> {
103 #[instrument(skip_all)]
104 pub async fn submit<OB: OrdersBackend<IS>>(
105 &mut self,
106 directional_exposure: &mut DirectionalExposure<IS>,
107 orders_backend: &mut OB,
108 tick_timestamp: &TickTimestamp,
109 remote_order_tracker: RemoteOrderTracker,
110 remote_order: RemoteOrder<IS>,
111 dependencies: impl IntoIterator<Item = (
112 RemoteTimingCondition,
113 OrderAction<IS>,
114 )>,
115 ) -> Result<(), PendingRemoteSubmitError>
116 where
117 IS: Send,
118 {
119 let submission_timestamp = tick_timestamp.timestamp();
120 let local_order_id = *remote_order_tracker.as_local_order_id();
121
122 #[cfg(feature = "log-trace-order-manager")]
123 trace!(
124 "Adding id: `{:?}` order: `{:?}`.",
125 local_order_id,
126 remote_order,
127 );
128
129 let desired_directional_intent_volume = remote_order.desired_directional_intent_volume()?;
130
131 let rest_at = if let RemoteOrder::Limit(
132 limit_order,
133 ) = &remote_order {
134 Some(limit_order.price.into_absolute().unwrap())
135 } else {
136 None
137 };
138
139 orders_backend.submit_order(
140 &local_order_id,
141 &submission_timestamp,
142 remote_order,
143 ).await?;
144
145 let pending_remote_order = PendingRemoteOrder::new(
146 submission_timestamp,
147 local_order_id,
148 dependencies,
149 desired_directional_intent_volume,
150 rest_at,
151 );
152
153 self.0.push(pending_remote_order);
154
155 directional_exposure.change_armed_directional_exposure(
156 &desired_directional_intent_volume.as_zeroable(),
157 );
158
159 Ok(())
160 }
161
162 #[instrument(skip_all)]
163 pub fn get(
164 &self,
165 local_order_id: &LocalOrderId,
166 ) -> Result<&PendingRemoteOrder<IS, CS>, OrderIdError> {
167 let Some(
168 pending_remote_order,
169 ) = self.0.iter().find(|
170 pending_remote_order,
171 | &pending_remote_order.local_order_id == local_order_id) else {
172 return local_order_id.err_invalid();
173 };
174
175 Ok(pending_remote_order)
176 }
177
178 #[instrument(skip_all)]
179 pub(crate) fn get_mut(
180 &mut self,
181 local_order_id: &LocalOrderId,
182 ) -> Result<&mut PendingRemoteOrder<IS, CS>, OrderIdError> {
183 let Some(
184 pending_remote_order,
185 ) = self.0.iter_mut().find(|
186 pending_remote_order,
187 | &pending_remote_order.local_order_id == local_order_id) else {
188 return local_order_id.err_invalid();
189 };
190
191 Ok(pending_remote_order)
192 }
193
194 #[instrument(skip_all)]
195 pub(crate) fn remove(
196 &mut self,
197 directional_exposure: &mut DirectionalExposure<IS>,
198 local_order_id: &LocalOrderId,
199 ) -> Result<PendingRemoteOrder<IS, CS>, PendingClientCancelError> {
200 #[cfg(feature = "log-trace-order-manager")]
201 trace!("Removing id: `{:?}`.", local_order_id);
202
203 let Some(
204 idx,
205 ) = self.0.iter().position(|
206 pending_remote_order,
207 | &pending_remote_order.local_order_id == local_order_id) else {
208 return local_order_id.err_invalid();
209 };
210
211 let pending_remote_order = self.0.swap_remove(idx);
212
213 let desired_directional_intent_volume = &pending_remote_order.desired_directional_intent_volume;
214
215 directional_exposure.change_armed_directional_exposure(
216 &desired_directional_intent_volume.as_flipped().as_zeroable(),
217 );
218
219 Ok(pending_remote_order)
220 }
221
222 #[instrument(skip_all)]
223 pub(crate) async fn acknowledged<OB: OrdersBackend<IS>>(
224 &mut self,
225 tick_timestamp: &TickTimestamp,
226 working_remote_orders: &mut WorkingRemoteOrders<IS, CS>,
227 directional_exposure: &mut DirectionalExposure<IS>,
228 deferred_order_actions: &mut DeferredOrderActions<IS>,
229 local_order_id: &LocalOrderId,
230 remote_order_id: RemoteOrderId,
231 ) -> Result<(), PendingRemoteProcessedError>
232 where
233 IS: Send,
234 {
235 #[cfg(feature = "log-trace-order-manager")]
236 trace!(
237 "Acknowledging `{:?}` with `{:?}`.",
238 local_order_id,
239 remote_order_id,
240 );
241
242 let mut pending_remote_order = self.remove(
243 directional_exposure,
244 local_order_id,
245 )?;
246
247 for (
248 remote_timing_condition,
249 remote_order_action,
250 ) in pending_remote_order.dependencies.iter_mut() {
251 if remote_timing_condition != &RemoteTimingCondition::Acknowledged {
252 continue;
253 }
254
255 deferred_order_actions.push(remote_order_action.clone());
256 }
257
258 working_remote_orders.submit::<OB>(
259 directional_exposure,
260 deferred_order_actions,
261 tick_timestamp,
262 pending_remote_order,
263 remote_order_id,
264 )?;
265
266 Ok(())
267 }
268}
269
270impl<
271 IS: InstrumentSpec,
272 CS: OrdersCapacitySpec,
273> Default for PendingRemoteOrders<IS, CS> {
274 fn default() -> Self {
275 Self(SmallVec::default())
276 }
277}