#[allow(unused_imports)]
use apple_quant_core::log::trace;
use apple_quant_core::log::{error, warn, CtxExt};
use tracing::instrument;
use crate::{
backend::{LocalOrderId, OrderIdGenerator, OrdersBackend},
order::{OrderDependency, RemoteOrderBuilder, StateGoal, TriggerError},
order_manager::{OrderManager, OrdersCapacitySpec, PendingClientCancelError},
volume::{AggressorSide, DirectionalExposure, DirectionalIntent, ZeroableExt},
instrument::InstrumentSpec, points::Subpoints, timestamp::TickTimestamp,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CancelClientOrder {
pub local_order_id: LocalOrderId,
pub attempt_exposure_reversion: bool,
}
impl CancelClientOrder {
pub fn new(
local_order_id: LocalOrderId,
attempt_exposure_reversion: bool,
) -> Self {
Self {
local_order_id,
attempt_exposure_reversion,
}
}
}
impl<IS: InstrumentSpec> OrderDependency<IS> for CancelClientOrder {
#[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:#?}`.");
match order_manager.pending_client_orders.remove(
directional_exposure,
&self.local_order_id,
) {
Ok(_) => return Ok(false),
Err(
error,
) => {
if !self.attempt_exposure_reversion {
return Err(error.into());
}
match error {
PendingClientCancelError::OrderId(_) => {},
_ => return Err(error.into()),
}
},
}
let Some(
effective_directional_intent_volume,
) = directional_exposure.combined().into_optional_nonzero() else {
warn!("Exposure reversion trigger failed with 0 combined directional exposure.");
return Ok(false);
};
let aggressor_side = match effective_directional_intent_volume.directional_intent {
DirectionalIntent::Positive => AggressorSide::Bid,
DirectionalIntent::Negative => AggressorSide::Ask,
};
let directionless_volume = effective_directional_intent_volume.directionless_volume;
warn!(
"Exposure reversion triggered. Submitting detached market `{:?}` with `{:?}`.",
aggressor_side,
directionless_volume
);
let order = match RemoteOrderBuilder::<IS>::new_market_parts(
order_id_generator,
aggressor_side,
directionless_volume,
) {
Ok(
remote_order_builder,
) => remote_order_builder,
error_result => {
error!(
"{:?}",
error_result.ctx("While constructing exposure reversion market order.")
);
return Ok(false);
},
};
let order_action = order.into_condensed().into_order_action::<4>().0;
Box::pin(order_action.trigger(
tick_timestamp,
order_manager,
orders_backend,
order_id_generator,
directional_exposure,
state_goal,
)).await
}
}