apple-quant-algorithmic 0.3.0

Apple Quant's algorithmic library.
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)
	}
}