use bevy::prelude::Deref;
use smallvec::SmallVec;
use thiserror::Error;
use crate::{backend::LocalOrderId, instrument::InstrumentSpec, volume::DirectionalIntentVolume};
use super::OrderExecutionExpectation;
#[derive(Debug, Error)]
pub(crate) enum AddOrderGoalError {
#[error("{0:?} already exists.")]
AlreadyExists(OrderGoalT),
}
#[derive(Debug, Error)]
pub(crate) enum RemoveOrderGoalError {
#[error("{0:?} already exists.")]
AlreadyExists(OrderGoalT),
}
#[derive(Debug, Error)]
pub enum OrderGoalAsExecutionExpectationError {
#[error("Can not convert {0:?} to an OrderExecutionExpectation.")]
InvalidConversion(OrderGoalT),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OrderGoalT {
CancelOrder,
CancelRevertOrder,
SubmitImmediatelyExecutableRemoteOrder,
SubmitRestingRemoteOrder,
}
impl<IS: InstrumentSpec> From<OrderGoal<IS>> for OrderGoalT {
fn from(value: OrderGoal<IS>) -> Self {
(&value).into()
}
}
impl<IS: InstrumentSpec> From<&OrderGoal<IS>> for OrderGoalT {
fn from(value: &OrderGoal<IS>) -> Self {
match value {
OrderGoal::CancelOrder(_) => Self::CancelOrder,
OrderGoal::CancelRevertOrder(_) => Self::CancelRevertOrder,
OrderGoal::SubmitImmediatelyExecutableRemoteOrder {
local_order_id: _,
directional_intent_volume: _,
} => Self::SubmitImmediatelyExecutableRemoteOrder,
OrderGoal::SubmitRestingRemoteOrder {
local_order_id: _,
directional_intent_volume: _,
} => Self::SubmitRestingRemoteOrder,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OrderGoal<IS: InstrumentSpec> {
CancelOrder(LocalOrderId),
CancelRevertOrder(LocalOrderId),
SubmitImmediatelyExecutableRemoteOrder {
local_order_id: LocalOrderId,
directional_intent_volume: DirectionalIntentVolume<IS>,
},
SubmitRestingRemoteOrder {
local_order_id: LocalOrderId,
directional_intent_volume: DirectionalIntentVolume<IS>,
},
}
impl<IS: InstrumentSpec> OrderGoal<IS> {
pub fn new_submit_remote_with_execution_expectation(
local_order_id: LocalOrderId,
directional_intent_volume: DirectionalIntentVolume<IS>,
order_execution_expectation: OrderExecutionExpectation,
) -> Self {
match order_execution_expectation {
OrderExecutionExpectation::Immediate => Self::SubmitImmediatelyExecutableRemoteOrder {
local_order_id,
directional_intent_volume,
},
OrderExecutionExpectation::Resting => Self::SubmitRestingRemoteOrder {
local_order_id,
directional_intent_volume,
},
}
}
pub fn as_order_execution_expectation(
&self
) -> Result<OrderExecutionExpectation, OrderGoalAsExecutionExpectationError> {
match self {
Self::CancelOrder(_) => {
Err(OrderGoalAsExecutionExpectationError::InvalidConversion(self.as_t()))
}
Self::CancelRevertOrder(_) => {
Err(OrderGoalAsExecutionExpectationError::InvalidConversion(self.as_t()))
}
Self::SubmitImmediatelyExecutableRemoteOrder {
local_order_id: _,
directional_intent_volume: _,
} => Ok(OrderExecutionExpectation::Immediate),
Self::SubmitRestingRemoteOrder {
local_order_id: _,
directional_intent_volume: _,
} => Ok(OrderExecutionExpectation::Resting),
}
}
pub fn as_local_order_id(&self) -> Result<&LocalOrderId, ()> {
match self {
Self::CancelOrder(local_order_id) => Ok(local_order_id),
Self::CancelRevertOrder(local_order_id) => Ok(local_order_id),
Self::SubmitImmediatelyExecutableRemoteOrder {
local_order_id,
directional_intent_volume,
} => Ok(local_order_id),
Self::SubmitRestingRemoteOrder {
local_order_id,
directional_intent_volume,
} => Ok(local_order_id),
}
}
pub fn as_directional_intent_volume(&self) -> Result<&DirectionalIntentVolume<IS>, ()> {
match self {
Self::CancelOrder(_) => Err(()),
Self::CancelRevertOrder(_) => Err(()),
Self::SubmitImmediatelyExecutableRemoteOrder {
local_order_id: _,
directional_intent_volume,
} => Ok(directional_intent_volume),
Self::SubmitRestingRemoteOrder {
local_order_id: _,
directional_intent_volume,
} => Ok(directional_intent_volume),
}
}
pub fn as_t(&self) -> OrderGoalT {
self.into()
}
}
#[derive(Debug)]
pub struct ActiveOrderGoals<IS: InstrumentSpec>(SmallVec<[OrderGoal<IS>; 4]>);
impl<IS: InstrumentSpec> ActiveOrderGoals<IS> {
pub(crate) fn reset(&mut self) {
self.0.clear()
}
pub(crate) fn add_order_goal(
&mut self,
order_goal: OrderGoal<IS>,
) -> Result<(), AddOrderGoalError> {
if self
.0
.iter()
.find(|&iter_order_goal| iter_order_goal == &order_goal)
.is_some()
{
return Err(AddOrderGoalError::AlreadyExists(order_goal.as_t()));
}
self.0.push(order_goal);
Ok(())
}
pub(crate) fn remove_order_goal(
&mut self,
order_goal: &OrderGoal<IS>,
) -> Result<(), RemoveOrderGoalError> {
let Some(active_order_goals_idx) = self
.0
.iter()
.position(|iter_order_goal| iter_order_goal == order_goal)
else {
return Err(RemoveOrderGoalError::AlreadyExists(order_goal.as_t()));
};
self.0
.swap_remove(active_order_goals_idx);
Ok(())
}
pub fn contains(
&self,
order_goal: &OrderGoal<IS>,
) -> bool {
self.0.contains(order_goal)
}
}
impl<IS: InstrumentSpec> Default for ActiveOrderGoals<IS> {
fn default() -> Self {
Self(SmallVec::default())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StateGoal {
CancelAll,
CancelFlattenAll,
CancelFlattenAllShutdown,
CancelFlattenAllRestart,
}
impl StateGoal {
pub fn completed_result(&self) -> UpdateStateGoalResult {
match self {
Self::CancelAll => UpdateStateGoalResult::Inactive,
Self::CancelFlattenAll => UpdateStateGoalResult::Inactive,
Self::CancelFlattenAllShutdown => UpdateStateGoalResult::Shutdown,
Self::CancelFlattenAllRestart => UpdateStateGoalResult::Restart,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum UpdateStateGoalResult {
Active,
Inactive,
Shutdown,
Restart,
}
#[derive(Debug, Default, Deref)]
pub struct ActiveStateGoal(Option<StateGoal>);