diff --git a/nautilus_core/execution/src/engine.rs b/nautilus_core/execution/src/engine.rs index 257485dc779d..e89eca4fab46 100644 --- a/nautilus_core/execution/src/engine.rs +++ b/nautilus_core/execution/src/engine.rs @@ -19,6 +19,7 @@ use std::collections::{HashMap, HashSet}; +use log::debug; use nautilus_common::{cache::Cache, generators::position_id::PositionIdGenerator}; use nautilus_model::{ enums::{OmsType, OrderSide}, @@ -32,7 +33,14 @@ use nautilus_model::{ types::quantity::Quantity, }; -use crate::client::ExecutionClient; +use crate::{ + client::ExecutionClient, + messages::{ + cancel::CancelOrder, cancel_all::CancelAllOrders, cancel_batch::BatchCancelOrders, + modify::ModifyOrder, query::QueryOrder, submit::SubmitOrder, submit_list::SubmitOrderList, + TradingCommand, + }, +}; pub struct ExecutionEngineConfig { pub debug: bool, @@ -115,10 +123,9 @@ impl ExecutionEngine { todo!(); } - // TODO: Implement `TradingCommand` enum - // pub fn execute(&self, command: TradingCommand) { - // todo!(); - // } + pub fn execute(&mut self, command: TradingCommand) { + self.execute_command(command); + } pub fn process(&self, event: &OrderEvent) { todo!(); @@ -126,45 +133,61 @@ impl ExecutionEngine { // -- COMMAND HANDLERS ---------------------------------------------------- - // fn execute_command(&self, command: TradingCommand) { - // todo!(); - // } + fn execute_command(&mut self, command: TradingCommand) { + debug!("<--[CMD] {:?}", command); // TODO: Log constants + self.command_count += 1; + + // TODO: Refine getting the client (no need for two expects) + let client = if let Some(client) = self.clients.get(&command.client_id()) { + client + } else if let Some(client_id) = self.routing_map.get(&command.instrument_id().venue) { + if let Some(client) = self.clients.get(client_id) { + client + } else { + self.default_client.as_ref().expect("No client found") + } + } else { + self.default_client.as_ref().expect("No client found") + }; + + match command { + TradingCommand::SubmitOrder(cmd) => self.handle_submit_order(client, cmd), + TradingCommand::SubmitOrderList(cmd) => self.handle_submit_order_list(client, cmd), + TradingCommand::ModifyOrder(cmd) => self.handle_modify_order(client, cmd), + TradingCommand::CancelOrder(cmd) => self.handle_cancel_order(client, cmd), + TradingCommand::CancelAllOrders(cmd) => self.handle_cancel_all_orders(client, cmd), + TradingCommand::BatchCancelOrders(cmd) => self.handle_batch_cancel_orders(client, cmd), + TradingCommand::QueryOrder(cmd) => self.handle_query_order(client, cmd), + } + } - // TODO: Implement `SubmitOrder` - // fn handle_submit_order(&self, client: &ExecutionClient, command: SubmitOrder) { - // todo!(); - // } + fn handle_submit_order(&self, client: &ExecutionClient, command: SubmitOrder) { + todo!(); + } - // TODO: Implement `SubmitOrderList` - // fn handle_submit_order_list(&self, client: &ExecutionClient, command: SubmitOrderList) { - // todo!(); - // } + fn handle_submit_order_list(&self, client: &ExecutionClient, command: SubmitOrderList) { + todo!(); + } - // TODO: Implement `ModifyOrder` - // fn handle_modify_order(&self, client: &ExecutionClient, command: ModifyOrder) { - // todo!(); - // } + fn handle_modify_order(&self, client: &ExecutionClient, command: ModifyOrder) { + todo!(); + } - // TODO: Implement `CancelOrder` - // fn handle_cancel_order(&self, client: &ExecutionClient, command: CancelOrder) { - // todo!(); - // } + fn handle_cancel_order(&self, client: &ExecutionClient, command: CancelOrder) { + todo!(); + } - // TODO: Implement `CancelAllOrder` - // fn handle_cancel_all_orders(&self, client: &ExecutionClient, command: CancelAllOrders) { - // todo!(); - // } + fn handle_cancel_all_orders(&self, client: &ExecutionClient, command: CancelAllOrders) { + todo!(); + } - // TODO: Implement `BatchCancelOrders` - // fn handle_batch_cancel_orders(&self, client: &ExecutionClient, command: - // BatchCancelOrders) { - // todo!(); - // } + fn handle_batch_cancel_orders(&self, client: &ExecutionClient, command: BatchCancelOrders) { + todo!(); + } - // TODO: Implement `QueryOrder` - // fn handle_query_order(&self, client: &ExecutionClient, command: QueryOrder) { - // todo!(); - // } + fn handle_query_order(&self, client: &ExecutionClient, command: QueryOrder) { + todo!(); + } // -- EVENT HANDLERS ---------------------------------------------------- diff --git a/nautilus_core/execution/src/messages/cancel_batch.rs b/nautilus_core/execution/src/messages/cancel_batch.rs new file mode 100644 index 000000000000..7d3092e37f37 --- /dev/null +++ b/nautilus_core/execution/src/messages/cancel_batch.rs @@ -0,0 +1,77 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (C) 2015-2024 Nautech Systems Pty Ltd. All rights reserved. +// https://nautechsystems.io +// +// Licensed under the GNU Lesser General Public License Version 3.0 (the "License"); +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ------------------------------------------------------------------------------------------------- + +use std::fmt::Display; + +use derive_builder::Builder; +use nautilus_core::{time::UnixNanos, uuid::UUID4}; +use nautilus_model::identifiers::{ + client_id::ClientId, instrument_id::InstrumentId, strategy_id::StrategyId, trader_id::TraderId, +}; +use serde::{Deserialize, Serialize}; + +use super::cancel::CancelOrder; + +#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, Builder)] +#[builder(default)] +#[serde(tag = "type")] +pub struct BatchCancelOrders { + pub trader_id: TraderId, + pub client_id: ClientId, + pub strategy_id: StrategyId, + pub instrument_id: InstrumentId, + pub cancels: Vec, + pub command_id: UUID4, + pub ts_init: UnixNanos, +} + +impl BatchCancelOrders { + #[allow(clippy::too_many_arguments)] + pub fn new( + trader_id: TraderId, + client_id: ClientId, + strategy_id: StrategyId, + instrument_id: InstrumentId, + cancels: Vec, + command_id: UUID4, + ts_init: UnixNanos, + ) -> anyhow::Result { + Ok(Self { + trader_id, + client_id, + strategy_id, + instrument_id, + cancels, + command_id, + ts_init, + }) + } +} + +impl Display for BatchCancelOrders { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "BatchCancelOrders(instrument_id={}, cancels=TBD)", + self.instrument_id, + ) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////////////// +#[cfg(test)] +mod tests {} diff --git a/nautilus_core/execution/src/messages/mod.rs b/nautilus_core/execution/src/messages/mod.rs index 47f35f6f4f3c..42310f7d5e59 100644 --- a/nautilus_core/execution/src/messages/mod.rs +++ b/nautilus_core/execution/src/messages/mod.rs @@ -13,9 +13,55 @@ // limitations under the License. // ------------------------------------------------------------------------------------------------- +use nautilus_model::identifiers::{client_id::ClientId, instrument_id::InstrumentId}; +use strum::Display; + +use self::{ + cancel::CancelOrder, cancel_all::CancelAllOrders, cancel_batch::BatchCancelOrders, + modify::ModifyOrder, query::QueryOrder, submit::SubmitOrder, submit_list::SubmitOrderList, +}; + pub mod cancel; pub mod cancel_all; +pub mod cancel_batch; pub mod modify; pub mod query; pub mod submit; pub mod submit_list; + +#[derive(Clone, Debug, Display)] +pub enum TradingCommand { + SubmitOrder(SubmitOrder), + SubmitOrderList(SubmitOrderList), + ModifyOrder(ModifyOrder), + CancelOrder(CancelOrder), + CancelAllOrders(CancelAllOrders), + BatchCancelOrders(BatchCancelOrders), + QueryOrder(QueryOrder), +} + +impl TradingCommand { + pub fn client_id(&self) -> ClientId { + match self { + Self::SubmitOrder(command) => command.client_id, + Self::SubmitOrderList(command) => command.client_id, + Self::ModifyOrder(command) => command.client_id, + Self::CancelOrder(command) => command.client_id, + Self::CancelAllOrders(command) => command.client_id, + Self::BatchCancelOrders(command) => command.client_id, + Self::QueryOrder(command) => command.client_id, + } + } + + pub fn instrument_id(&self) -> InstrumentId { + match self { + Self::SubmitOrder(command) => command.instrument_id, + Self::SubmitOrderList(command) => command.instrument_id, + Self::ModifyOrder(command) => command.instrument_id, + Self::CancelOrder(command) => command.instrument_id, + Self::CancelAllOrders(command) => command.instrument_id, + Self::BatchCancelOrders(command) => command.instrument_id, + Self::QueryOrder(command) => command.instrument_id, + } + } +}