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