Skip to main content

apple_quant_algorithmic/order/
goal.rs

1use bevy::prelude::Deref;
2use smallvec::SmallVec;
3use thiserror::Error;
4
5use crate::{backend::LocalOrderId, instrument::InstrumentSpec, volume::DirectionalIntentVolume};
6
7use super::OrderExecutionExpectation;
8
9#[derive(Debug, Error)]
10pub(crate) enum AddOrderGoalError {
11	#[error("{0:?} already exists.")]
12	AlreadyExists(OrderGoalT),
13}
14
15#[derive(Debug, Error)]
16pub(crate) enum RemoveOrderGoalError {
17	#[error("{0:?} already exists.")]
18	AlreadyExists(OrderGoalT),
19}
20
21#[derive(Debug, Error)]
22pub enum OrderGoalAsExecutionExpectationError {
23	#[error("Can not convert {0:?} to an OrderExecutionExpectation.")]
24	InvalidConversion(OrderGoalT),
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28pub enum OrderGoalT {
29	CancelOrder,
30	CancelRevertOrder,
31	SubmitImmediatelyExecutableRemoteOrder,
32	SubmitRestingRemoteOrder,
33}
34
35impl<IS: InstrumentSpec> From<OrderGoal<IS>> for OrderGoalT {
36	fn from(value: OrderGoal<IS>) -> Self {
37		(&value).into()
38	}
39}
40
41impl<IS: InstrumentSpec> From<&OrderGoal<IS>> for OrderGoalT {
42	fn from(value: &OrderGoal<IS>) -> Self {
43		match value {
44			OrderGoal::CancelOrder(_) => Self::CancelOrder,
45			OrderGoal::CancelRevertOrder(_) => Self::CancelRevertOrder,
46			OrderGoal::SubmitImmediatelyExecutableRemoteOrder {
47				local_order_id: _,
48				directional_intent_volume: _,
49			} => Self::SubmitImmediatelyExecutableRemoteOrder,
50			OrderGoal::SubmitRestingRemoteOrder {
51				local_order_id: _,
52				directional_intent_volume: _,
53			} => Self::SubmitRestingRemoteOrder,
54		}
55	}
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
59pub enum OrderGoal<IS: InstrumentSpec> {
60	/// Cancels any remaining potential exposure for an order that has not been matched yet. Does not revert partially filled or fully filled orders. After the goal is completed, there should be no potential exposure, however, there may be effective exposure due to a partial or a full fill that could not be canceled passively.
61	CancelOrder(LocalOrderId),
62
63	/// Cancels any remaining potential exposure for an order that has not been matched yet. Aggressively reverts any partial fills fragments that are then received by the client. After the goal is completed, there should be no potential or effective exposure related to this order anymore.
64	CancelRevertOrder(LocalOrderId),
65
66	/// Completes when the order is fully matched (fully filled only, not partially fill).
67	SubmitImmediatelyExecutableRemoteOrder {
68		local_order_id: LocalOrderId,
69		directional_intent_volume: DirectionalIntentVolume<IS>,
70	},
71
72	/// Completes when the order is booked (resting, partially filled, or fully filled).
73	SubmitRestingRemoteOrder {
74		local_order_id: LocalOrderId,
75		directional_intent_volume: DirectionalIntentVolume<IS>,
76	},
77}
78
79impl<IS: InstrumentSpec> OrderGoal<IS> {
80	pub fn new_submit_remote_with_execution_expectation(
81		local_order_id: LocalOrderId,
82		directional_intent_volume: DirectionalIntentVolume<IS>,
83		order_execution_expectation: OrderExecutionExpectation,
84	) -> Self {
85		match order_execution_expectation {
86			OrderExecutionExpectation::Immediate => Self::SubmitImmediatelyExecutableRemoteOrder {
87				local_order_id,
88				directional_intent_volume,
89			},
90			OrderExecutionExpectation::Resting => Self::SubmitRestingRemoteOrder {
91				local_order_id,
92				directional_intent_volume,
93			},
94		}
95	}
96
97	pub fn as_order_execution_expectation(
98		&self
99	) -> Result<OrderExecutionExpectation, OrderGoalAsExecutionExpectationError> {
100		match self {
101			Self::CancelOrder(_) => {
102				Err(OrderGoalAsExecutionExpectationError::InvalidConversion(self.as_t()))
103			}
104			Self::CancelRevertOrder(_) => {
105				Err(OrderGoalAsExecutionExpectationError::InvalidConversion(self.as_t()))
106			}
107			Self::SubmitImmediatelyExecutableRemoteOrder {
108				local_order_id: _,
109				directional_intent_volume: _,
110			} => Ok(OrderExecutionExpectation::Immediate),
111			Self::SubmitRestingRemoteOrder {
112				local_order_id: _,
113				directional_intent_volume: _,
114			} => Ok(OrderExecutionExpectation::Resting),
115		}
116	}
117
118	pub fn as_local_order_id(&self) -> Result<&LocalOrderId, ()> {
119		match self {
120			Self::CancelOrder(local_order_id) => Ok(local_order_id),
121			Self::CancelRevertOrder(local_order_id) => Ok(local_order_id),
122			Self::SubmitImmediatelyExecutableRemoteOrder {
123				local_order_id,
124				directional_intent_volume,
125			} => Ok(local_order_id),
126			Self::SubmitRestingRemoteOrder {
127				local_order_id,
128				directional_intent_volume,
129			} => Ok(local_order_id),
130		}
131	}
132
133	pub fn as_directional_intent_volume(&self) -> Result<&DirectionalIntentVolume<IS>, ()> {
134		match self {
135			Self::CancelOrder(_) => Err(()),
136			Self::CancelRevertOrder(_) => Err(()),
137			Self::SubmitImmediatelyExecutableRemoteOrder {
138				local_order_id: _,
139				directional_intent_volume,
140			} => Ok(directional_intent_volume),
141			Self::SubmitRestingRemoteOrder {
142				local_order_id: _,
143				directional_intent_volume,
144			} => Ok(directional_intent_volume),
145		}
146	}
147
148	pub fn as_t(&self) -> OrderGoalT {
149		self.into()
150	}
151}
152
153#[derive(Debug)]
154pub struct ActiveOrderGoals<IS: InstrumentSpec>(SmallVec<[OrderGoal<IS>; 4]>);
155
156impl<IS: InstrumentSpec> ActiveOrderGoals<IS> {
157	pub(crate) fn reset(&mut self) {
158		self.0.clear()
159	}
160
161	pub(crate) fn add_order_goal(
162		&mut self,
163		order_goal: OrderGoal<IS>,
164	) -> Result<(), AddOrderGoalError> {
165		if self
166			.0
167			.iter()
168			.find(|&iter_order_goal| iter_order_goal == &order_goal)
169			.is_some()
170		{
171			return Err(AddOrderGoalError::AlreadyExists(order_goal.as_t()));
172		}
173
174		self.0.push(order_goal);
175		Ok(())
176	}
177
178	pub(crate) fn remove_order_goal(
179		&mut self,
180		order_goal: &OrderGoal<IS>,
181	) -> Result<(), RemoveOrderGoalError> {
182		let Some(active_order_goals_idx) = self
183			.0
184			.iter()
185			.position(|iter_order_goal| iter_order_goal == order_goal)
186		else {
187			return Err(RemoveOrderGoalError::AlreadyExists(order_goal.as_t()));
188		};
189
190		self.0
191			.swap_remove(active_order_goals_idx);
192		Ok(())
193	}
194
195	pub fn contains(
196		&self,
197		order_goal: &OrderGoal<IS>,
198	) -> bool {
199		self.0.contains(order_goal)
200	}
201}
202
203impl<IS: InstrumentSpec> Default for ActiveOrderGoals<IS> {
204	fn default() -> Self {
205		Self(SmallVec::default())
206	}
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
210pub enum StateGoal {
211	CancelAll,
212	CancelFlattenAll,
213	CancelFlattenAllShutdown,
214	CancelFlattenAllRestart,
215}
216
217impl StateGoal {
218	pub fn completed_result(&self) -> UpdateStateGoalResult {
219		match self {
220			Self::CancelAll => UpdateStateGoalResult::Inactive,
221			Self::CancelFlattenAll => UpdateStateGoalResult::Inactive,
222			Self::CancelFlattenAllShutdown => UpdateStateGoalResult::Shutdown,
223			Self::CancelFlattenAllRestart => UpdateStateGoalResult::Restart,
224		}
225	}
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
229pub enum UpdateStateGoalResult {
230	Active,
231	Inactive,
232	Shutdown,
233	Restart,
234}
235
236#[derive(Debug, Default, Deref)]
237pub struct ActiveStateGoal(Option<StateGoal>);