#[cfg(feature = "log-trace-order-manager")]
use apple_quant_core::log::trace;
use crate::{
price::{AbsolutePrice, BidAskPriceSpread, ProtoabsolutePrice},
volume::{
AggressiveVolume, AggressorSide, DirectionalIntentVolume, DirectionlessVolume,
RestingSide, RestingVolume,
},
backend::OrderIdGenerator, instrument::InstrumentSpec, liquidity::LiquidityEstimation,
};
use super::{
DesiredVolumeOrder, DesiredVolumeOrderError, MatchableOrder,
OrderExecutionExpectation, RemoteOrderTracker,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RemoteOrder<IS: InstrumentSpec> {
Market(MarketOrder<IS>),
Limit(LimitOrder<IS>),
}
impl<IS: InstrumentSpec> RemoteOrder<IS> {
pub(crate) fn parent_processed(
&mut self,
bid_ask_price_spread: &BidAskPriceSpread<IS>,
) {
let Self::Limit(
limit_order,
) = self else {
return;
};
limit_order.parent_processed(bid_ask_price_spread);
}
pub fn as_order_execution_expectation(
&self,
) -> OrderExecutionExpectation {
match self {
Self::Market(_) => OrderExecutionExpectation::Immediate,
Self::Limit(
limit_order,
) => limit_order.order_execution_expectation,
}
}
pub fn register(
&self,
order_id_generator: &mut OrderIdGenerator,
) -> Result<RemoteOrderTracker, DesiredVolumeOrderError>
where
IS: Send,
{
let local_order_id = order_id_generator.next_local_order_id();
#[cfg(feature = "log-trace-order-manager")]
trace!("Registering order `{self:?}` with `{local_order_id:?}`");
let directional_intent_volume = self.desired_directional_intent_volume()?;
let order_execution_expectation = self.as_order_execution_expectation();
Ok(RemoteOrderTracker::new(local_order_id))
}
}
impl<IS: InstrumentSpec> DesiredVolumeOrder<IS> for RemoteOrder<IS> {
fn desired_directional_intent_volume(
&self,
) -> Result<DirectionalIntentVolume<IS>, DesiredVolumeOrderError> {
match self {
Self::Market(
market_order,
) => market_order.desired_directional_intent_volume(),
Self::Limit(
limit_order,
) => limit_order.desired_directional_intent_volume(),
}
}
fn desired_directionless_volume(
&self,
) -> Result<&DirectionlessVolume<IS>, DesiredVolumeOrderError> {
match self {
Self::Market(
market_order,
) => market_order.desired_directionless_volume(),
Self::Limit(
limit_order,
) => limit_order.desired_directionless_volume(),
}
}
}
impl<IS: InstrumentSpec> MatchableOrder<IS> for RemoteOrder<IS> {
fn is_liquidable(
&self,
liquidity_estimation: &LiquidityEstimation<IS>,
) -> Option<AbsolutePrice<IS>> {
match self {
Self::Market(
market_order,
) => market_order.is_liquidable(liquidity_estimation),
Self::Limit(
limit_order,
) => limit_order.is_liquidable(liquidity_estimation),
}
}
}
impl<IS: InstrumentSpec> From<MarketOrder<IS>> for RemoteOrder<IS> {
fn from(
value: MarketOrder<IS>,
) -> Self {
Self::Market(value)
}
}
impl<IS: InstrumentSpec> From<LimitOrder<IS>> for RemoteOrder<IS> {
fn from(
value: LimitOrder<IS>,
) -> Self {
Self::Limit(value)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MarketOrder<IS: InstrumentSpec> {
pub aggressive_volume: AggressiveVolume<IS>,
}
impl<IS: InstrumentSpec> MarketOrder<IS> {
pub fn new(
aggressive_volume: AggressiveVolume<IS>,
) -> Self {
Self { aggressive_volume }
}
pub fn new_from_parts(
directionless_volume: DirectionlessVolume<IS>,
aggressor_side: AggressorSide,
) -> Self {
Self {
aggressive_volume: AggressiveVolume {
directionless_volume,
aggressor_side,
},
}
}
pub fn into_remote(
self,
) -> RemoteOrder<IS> {
self.into()
}
}
impl<IS: InstrumentSpec> DesiredVolumeOrder<IS> for MarketOrder<IS> {
fn desired_directional_intent_volume(
&self,
) -> Result<DirectionalIntentVolume<IS>, DesiredVolumeOrderError> {
Ok(self.aggressive_volume.as_directional_intent_volume())
}
fn desired_directionless_volume(
&self,
) -> Result<&DirectionlessVolume<IS>, DesiredVolumeOrderError> {
Ok(self.aggressive_volume.as_directionless_volume())
}
}
impl<IS: InstrumentSpec> MatchableOrder<IS> for MarketOrder<IS> {
fn is_liquidable(
&self,
liquidity_estimation: &LiquidityEstimation<IS>,
) -> Option<AbsolutePrice<IS>> {
let Some((
bid_level,
ask_level,
)) = liquidity_estimation.furthest_bid_ask() else {
return None;
};
match self.aggressive_volume.into_aggressor_side() {
AggressorSide::Bid => Some(bid_level.price),
AggressorSide::Ask => Some(ask_level.price),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LimitOrder<IS: InstrumentSpec> {
pub price: ProtoabsolutePrice<IS>,
pub resting_volume: RestingVolume<IS>,
pub order_execution_expectation: OrderExecutionExpectation,
}
impl<IS: InstrumentSpec> LimitOrder<IS> {
pub fn new(
price: ProtoabsolutePrice<IS>,
resting_volume: RestingVolume<IS>,
order_execution_expectation: OrderExecutionExpectation,
) -> Self {
Self {
price,
resting_volume,
order_execution_expectation,
}
}
pub(crate) fn parent_processed(
&mut self,
bid_ask_price_spread: &BidAskPriceSpread<IS>,
) {
let ProtoabsolutePrice::Relative(
relative_price,
) = &self.price else {
return;
};
let absolute_price = if relative_price.is_positive() {
bid_ask_price_spread.ask_price + relative_price
} else {
bid_ask_price_spread.bid_price + relative_price
};
self.price = absolute_price.into_protoabsolute_price();
}
pub fn into_remote(
self,
) -> RemoteOrder<IS> {
self.into()
}
}
impl<IS: InstrumentSpec> DesiredVolumeOrder<IS> for LimitOrder<IS> {
fn desired_directional_intent_volume(
&self,
) -> Result<DirectionalIntentVolume<IS>, DesiredVolumeOrderError> {
Ok(self.resting_volume.as_directional_intent_volume())
}
fn desired_directionless_volume(
&self,
) -> Result<&DirectionlessVolume<IS>, DesiredVolumeOrderError> {
Ok(self.resting_volume.as_directionless_volume())
}
}
impl<IS: InstrumentSpec> MatchableOrder<IS> for LimitOrder<IS> {
fn is_liquidable(
&self,
liquidity_estimation: &LiquidityEstimation<IS>,
) -> Option<AbsolutePrice<IS>> {
let Some((
bid_level,
ask_level,
)) = liquidity_estimation.furthest_bid_ask() else {
return None;
};
match self.resting_volume.resting_side {
RestingSide::Bid => {
let ProtoabsolutePrice::Absolute(
absolute_price,
) = self.price else {
return None;
};
if bid_level.price <= absolute_price {
Some(bid_level.price)
} else {
None
}
},
RestingSide::Ask => {
let ProtoabsolutePrice::Absolute(
absolute_price,
) = self.price else {
return None;
};
if ask_level.price >= absolute_price {
Some(ask_level.price)
} else {
None
}
},
}
}
}