use smallvec::SmallVec;
use tracing::instrument;
#[allow(unused_imports)]
use tracing::trace;
use crate::{
backend::{OrderIdGenerator, OrdersBackend},
order::{
dependency::remote::{RemoteOrderAction, SubmitRemoteOrder},
ClientOrder, ClientOrderTracker, ClientTimingCondition, OrderAction,
OrderDependency, RemoteOrder, RemoteOrderTracker, RemoteTimingCondition,
StateGoal, TimingCondition, TriggerError,
},
order_manager::{OrderManager, OrdersCapacitySpec},
instrument::InstrumentSpec, price::BidAskPriceSpread, timestamp::TickTimestamp,
volume::DirectionalExposure,
};
use super::{ClientDeployedRemoteDependency, ClientOrderAction};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SubmitClientOrder<IS: InstrumentSpec> {
pub client_order_tracker: ClientOrderTracker,
pub client_order: ClientOrder<IS>,
pub client_deployed_remote_dependency: ClientDeployedRemoteDependency<IS>,
pub dependencies: Vec<(
ClientTimingCondition,
OrderAction<IS>,
)>,
}
impl<IS: InstrumentSpec> SubmitClientOrder<IS> {
pub fn new(
client_order_tracker: ClientOrderTracker,
client_order: ClientOrder<IS>,
remote_order_tracker: RemoteOrderTracker,
remote_order: RemoteOrder<IS>,
dependencies: impl IntoIterator<Item = (
TimingCondition,
OrderAction<IS>,
)>,
) -> Self {
let mut client_order_dependencies = Vec::with_capacity(4);
let dependencies = dependencies
.into_iter()
.filter_map(|dependency| {
match dependency.0 {
TimingCondition::Remote(
remote_timing_condition,
) => Some((remote_timing_condition, dependency.1)),
TimingCondition::Client(
client_timing_condition,
) => {
client_order_dependencies.push((
client_timing_condition,
dependency.1,
));
None
},
}
});
let submit_remote_order = SubmitRemoteOrder::new(
remote_order_tracker,
remote_order,
dependencies,
);
let client_deployed_remote_dependency = ClientDeployedRemoteDependency::new(
submit_remote_order,
);
Self {
client_order_tracker,
client_order,
client_deployed_remote_dependency,
dependencies: client_order_dependencies,
}
}
pub(crate) fn parent_processed(
&mut self,
bid_ask_price_spread: &BidAskPriceSpread<IS>,
) {
#[cfg(feature = "log-trace-order-actions")]
trace!(
"`parent_processed` called for order action: `{self:#?}` with `{bid_ask_price_spread:?}`."
);
self.client_order.parent_processed(bid_ask_price_spread);
}
pub fn into_order_action(
self,
) -> OrderAction<IS> {
self.into()
}
}
impl<IS: InstrumentSpec> OrderDependency<IS> for SubmitClientOrder<IS> {
#[instrument(skip_all)]
async fn trigger<
OB: OrdersBackend<IS>,
CS: OrdersCapacitySpec,
>(
&self,
tick_timestamp: &TickTimestamp,
order_manager: &mut OrderManager<IS, CS>,
orders_backend: &mut OB,
order_id_generator: &mut OrderIdGenerator,
directional_exposure: &mut DirectionalExposure<IS>,
state_goal: &mut StateGoal,
) -> Result<bool, TriggerError>
where
IS: Send,
{
#[cfg(feature = "log-trace-order-actions")]
trace!("Triggered order action: `{self:#?}`.");
let Self {
client_order_tracker,
client_order,
client_deployed_remote_dependency,
dependencies,
} = self;
order_manager.pending_client_orders.submit::<OB>(
tick_timestamp,
directional_exposure,
client_order_tracker,
client_order.clone(),
client_deployed_remote_dependency.clone(),
dependencies.clone(),
)?;
Ok(true)
}
}