apple-quant-algorithmic 0.1.0

Apple Quant's algorithmic trading api
Documentation
use thiserror::Error;

use crate::{
	backend::{LocalOrderId, OrderIdError, OrdersBackendSubmitRemoteOrderError, RemoteOrderId},
	instrument::InstrumentSpec,
	order::{
		DesiredVolumeOrderError, OrderGoalAsExecutionExpectationError, OrderGoalT,
		RemoveOrderGoalError, StateGoal,
	},
};

mod capacity_spec;
mod client_pending;
mod completed;
mod remote_pending;
mod working;

pub use capacity_spec::*;
pub use client_pending::*;
pub use completed::*;
pub use remote_pending::*;
pub use working::*;

#[derive(Debug, Error)]
pub enum SubmitRemoteOrderError {
	#[error("{0:?}")]
	OrdersBackendSubmitRemoteOrderError(#[from] OrdersBackendSubmitRemoteOrderError),

	#[error("{0:?}")]
	DesiredVolumeOrderError(#[from] DesiredVolumeOrderError),
}

#[derive(Debug, Error)]
pub enum TryCancelRemoteOrderError {
	#[error("Unable to cancel order that is in a remote pending state.")]
	Pending(RemoteOrderId),

	#[error("Unable to cancel order that is partially filled at remote.")]
	ParitallyFilled(RemoteOrderId),

	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),
}

#[derive(Debug, Error)]
pub(crate) enum RemotePartialFillError {
	#[error("{0:?}")]
	TrasitionRemoteWorkingOrderError(#[from] TrasitionRemoteWorkingOrderError),

	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),
}

#[derive(Debug, Error)]
pub(crate) enum TrasitionLocalOrderError {
	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),

	#[error("{0:?}")]
	OrdersBackendSubmitRemoteOrderError(#[from] OrdersBackendSubmitRemoteOrderError),

	#[error(
		"{local_order_id:?} already is paired with {existing_remote_order_id:?} when attemping to transition to  {attemped_remote_order_id:?}"
	)]
	AlreadyTransitioned {
		local_order_id: LocalOrderId,
		attemped_remote_order_id: RemoteOrderId,
		existing_remote_order_id: RemoteOrderId,
	},
}

#[derive(Debug, Error)]
pub(crate) enum TransitionRemotePendingOrderError {
	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),

	#[error("{0:?}")]
	OrderGoalAsExecutionExpectation(#[from] OrderGoalAsExecutionExpectationError),

	#[error("{0:?}")]
	RemoveOrderGoalError(#[from] RemoveOrderGoalError),

	#[error("{local_order_id:?} is already in a working state under {remote_order_id:?}.")]
	AlreadyWorking {
		local_order_id: LocalOrderId,
		remote_order_id: RemoteOrderId,
	},

	#[error("Unexpected {0:?}.")]
	UnexpectedOrderGoal(OrderGoalT),
}

#[derive(Debug, Error)]
pub(crate) enum TrasitionRemoteWorkingOrderError {
	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),

	#[error("{0:?}")]
	RemoveOrderGoalError(#[from] RemoveOrderGoalError),

	#[error("{0:?} already exists in a completed state.")]
	AlreadyCompleted(RemoteOrderId),

	#[error("Unexpected {0:?}.")]
	UnexpectedOrderGoal(OrderGoalT),
}

#[derive(Debug, Error)]
pub enum CancelOrderError {
	#[error("No matching remote order id for: {0:?}")]
	NoMatchingRemoteOrderId(LocalOrderId),

	#[error("{0:?}")]
	CancelLocalOrderError(#[from] CancelClientOrderError),

	#[error("{0:?}")]
	CancelRemoteOrderError(#[from] CancelRemoteOrderError),
}

#[derive(Debug, Error)]
pub enum CancelClientOrderError {
	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),
}

#[derive(Debug, Error)]
pub enum CancelRemoteOrderError {
	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),

	#[error("{0:?}")]
	DesiredVolumeOrderError(#[from] DesiredVolumeOrderError),

	#[error("{0:?} has no RemoteOrderId assigned yet.")]
	NoRemoteOrderId(LocalOrderId),
}

#[derive(Debug, Error)]
pub enum CancelFlattenAllError {
	#[error("Can not cancel flatten while there is an existing: {0:?}")]
	ExistingStateGoal(StateGoal),
}

#[derive(Debug, Error)]
pub enum RemoteCanceledRemoteOrderError {
	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),

	#[error("{0:?}")]
	OrderGoalAsExecutionExpectationError(#[from] OrderGoalAsExecutionExpectationError),

	#[error("Order was already fully filled.")]
	FullyFilled,
}

#[derive(Debug, Error)]
pub enum AssignRemoteOrderIdError {
	#[error("{0:?}")]
	OrderIdError(#[from] OrderIdError),

	#[error(
		"Failed to assign {remote_order_id:?} to order with {local_order_id:?}. Already assigned {existing_remote_order_id:?}"
	)]
	AlreadyAssigned {
		local_order_id: LocalOrderId,
		remote_order_id: RemoteOrderId,
		existing_remote_order_id: RemoteOrderId,
	},
}

#[derive(Debug)]
pub enum OrderGroupMut<'a, IS: InstrumentSpec, CS: OrdersCapacitySpec> {
	PendingClient(&'a mut PendingClientOrders<IS, CS>),
	PendingRemote(&'a mut PendingRemoteOrders<IS, CS>),
	WorkingRemote(&'a mut WorkingRemoteOrders<IS, CS>),
	CompletedRemote(&'a mut CompletedRemoteOrders<IS, CS>),
}

#[derive(Debug)]
pub enum OrderRef<'a, IS: InstrumentSpec, CS: OrdersCapacitySpec> {
	PendingClient {
		pending_client_order: &'a PendingClientOrder<IS>,
		pending_client_orders: &'a PendingClientOrders<IS, CS>,
	},
	PendingRemote {
		pending_remote_order: &'a PendingRemoteOrder<IS, CS>,
		pending_remote_orders: &'a PendingRemoteOrders<IS, CS>,
	},
	WorkingRemote {
		working_remote_order: &'a WorkingRemoteOrder<IS, CS>,
		working_remote_orders: &'a WorkingRemoteOrders<IS, CS>,
	},
	CompletedRemote {
		completed_remote_order: &'a CompletedRemoteOrder<IS, CS>,
		completed_remote_orders: &'a CompletedRemoteOrders<IS, CS>,
	},
}

#[derive(Debug)]
pub enum OrderMut<'a, IS: InstrumentSpec, CS: OrdersCapacitySpec> {
	PendingClient(&'a mut PendingClientOrder<IS>),
	PendingRemote(&'a mut PendingRemoteOrder<IS, CS>),
	WorkingRemote(&'a mut WorkingRemoteOrder<IS, CS>),
	CompletedRemote(&'a mut CompletedRemoteOrder<IS, CS>),
}

#[derive(Debug)]
pub struct OrderManager<IS: InstrumentSpec, CS: OrdersCapacitySpec> {
	pub(crate) pending_client_orders: PendingClientOrders<IS, CS>,
	pub(crate) pending_remote_orders: PendingRemoteOrders<IS, CS>,
	pub(crate) working_remote_orders: WorkingRemoteOrders<IS, CS>,
	pub(crate) completed_remote_orders: CompletedRemoteOrders<IS, CS>,
}

impl<IS: InstrumentSpec, CS: OrdersCapacitySpec> OrderManager<IS, CS> {
	pub fn pending_client_orders(&self) -> &PendingClientOrders<IS, CS> {
		&self.pending_client_orders
	}

	pub fn pending_remote_orders(&self) -> &PendingRemoteOrders<IS, CS> {
		&self.pending_remote_orders
	}

	pub fn working_remote_orders(&self) -> &WorkingRemoteOrders<IS, CS> {
		&self.working_remote_orders
	}

	pub fn completed_remote_orders(&self) -> &CompletedRemoteOrders<IS, CS> {
		&self.completed_remote_orders
	}

	pub fn find_order(
		&self,
		local_order_id: &LocalOrderId,
	) -> Result<OrderRef<'_, IS, CS>, OrderIdError> {
		if let Ok(pending_client_order) = self
			.pending_client_orders
			.get(local_order_id)
		{
			return Ok(OrderRef::PendingClient {
				pending_client_order,
				pending_client_orders: &self.pending_client_orders,
			});
		}

		if let Ok(pending_remote_order) = self
			.pending_remote_orders
			.get(local_order_id)
		{
			return Ok(OrderRef::PendingRemote {
				pending_remote_order,
				pending_remote_orders: &self.pending_remote_orders,
			});
		}

		if let Ok(working_remote_order) = self
			.working_remote_orders
			.get(local_order_id)
		{
			return Ok(OrderRef::WorkingRemote {
				working_remote_order,
				working_remote_orders: &self.working_remote_orders,
			});
		}

		if let Ok(completed_remote_order) = self
			.completed_remote_orders
			.get(local_order_id)
		{
			return Ok(OrderRef::CompletedRemote {
				completed_remote_order,
				completed_remote_orders: &self.completed_remote_orders,
			});
		}

		local_order_id.err_invalid()
	}

	pub(crate) fn find_order_mut(
		&mut self,
		local_order_id: &LocalOrderId,
	) -> Result<OrderMut<'_, IS, CS>, OrderIdError> {
		if let Ok(pending_client_order) = self
			.pending_client_orders
			.get_mut(local_order_id)
		{
			return Ok(OrderMut::PendingClient(
				pending_client_order,
			));
		}

		if let Ok(pending_remote_order) = self
			.pending_remote_orders
			.get_mut(local_order_id)
		{
			return Ok(OrderMut::PendingRemote(
				pending_remote_order,
			));
		}

		if let Ok(working_remote_order) = self
			.working_remote_orders
			.get_mut(local_order_id)
		{
			return Ok(OrderMut::WorkingRemote(
				working_remote_order,
			));
		}

		if let Ok(completed_remote_order) = self
			.completed_remote_orders
			.get_mut(local_order_id)
		{
			return Ok(OrderMut::CompletedRemote(
				completed_remote_order,
			));
		}

		local_order_id.err_invalid()
	}

	pub(crate) fn find_order_group_mut(
		&mut self,
		local_order_id: &LocalOrderId,
	) -> Result<OrderGroupMut<'_, IS, CS>, OrderIdError> {
		if self
			.pending_client_orders
			.get(local_order_id)
			.is_ok()
		{
			return Ok(OrderGroupMut::PendingClient(
				&mut self.pending_client_orders,
			));
		}

		if self
			.pending_remote_orders
			.get(local_order_id)
			.is_ok()
		{
			return Ok(OrderGroupMut::PendingRemote(
				&mut self.pending_remote_orders,
			));
		}

		if self
			.working_remote_orders
			.get(local_order_id)
			.is_ok()
		{
			return Ok(OrderGroupMut::WorkingRemote(
				&mut self.working_remote_orders,
			));
		}

		if self
			.completed_remote_orders
			.get(local_order_id)
			.is_ok()
		{
			return Ok(OrderGroupMut::CompletedRemote(&mut self.completed_remote_orders));
		}

		local_order_id.err_invalid()
	}
}

impl<IS: InstrumentSpec, CS: OrdersCapacitySpec> Default for OrderManager<IS, CS> {
	fn default() -> Self {
		Self {
			pending_client_orders: PendingClientOrders::default(),
			pending_remote_orders: PendingRemoteOrders::default(),
			working_remote_orders: WorkingRemoteOrders::default(),
			completed_remote_orders: CompletedRemoteOrders::default(),
		}
	}
}