//! Trade execution algorithms module //! //! This module provides sophisticated trade execution algorithms designed to //! minimize market impact, reduce slippage, and optimize execution quality. //! Includes TWAP, VWAP, Implementation Shortfall, and custom execution strategies. use anyhow::Result; use chrono::NaiveDate; use common::HftTimestamp; use common::Order; use common::OrderSide; use common::OrderStatus; use common::OrderType; use common::Price; use common::Quantity; use common::TimeInForce; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, VecDeque}; use tokio::time::{Duration, Instant}; use tracing::{debug, info, warn}; use super::config::{ExecutionAlgorithm, ExecutionConfig}; use super::microstructure::{MicrostructureAnalyzer, OrderLevel, Trade}; /// Trade execution engine /// /// Coordinates all trade execution activities including algorithm selection, /// order management, execution monitoring, and performance analysis. #[derive(Debug)] pub struct ExecutionEngine { /// Execution configuration config: ExecutionConfig, /// Available execution algorithms algorithms: HashMap>, /// Order management system order_manager: OrderManager, /// Execution performance tracker performance_tracker: ExecutionPerformanceTracker, /// Smart order router smart_router: SmartOrderRouter, } /// Order management system #[derive(Debug)] pub struct OrderManager { /// Active orders active_orders: HashMap, /// Order history order_history: VecDeque, /// Fill tracker fill_tracker: FillTracker, /// Order ID generator next_order_id: u64, } // Order struct removed - using canonical definition from common::prelude::Order // OrderSide, OrderType and OrderStatus imported from canonical source in common::prelude // REMOVED: TimeInForce duplicate - use common::TimeInForce // Note: GTD variant not supported in canonical definition /// Fill information #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Fill { /// Fill ID pub id: String, /// Order ID pub order_id: String, /// Fill price pub price: f64, /// Fill quantity pub quantity: f64, /// Fill timestamp pub timestamp: chrono::DateTime, /// Counterparty information pub counterparty: Option, /// Exchange/venue pub venue: String, /// Commission paid pub commission: f64, } /// Fill tracking system #[derive(Debug)] pub struct FillTracker { /// Recent fills fills: VecDeque, /// Fill statistics by symbol fill_stats: HashMap, } /// Fill statistics #[derive(Debug, Clone)] pub struct FillStatistics { /// Total fills pub total_fills: u64, /// Total volume pub total_volume: f64, /// Volume-weighted average price pub vwap: f64, /// Average fill size pub average_fill_size: f64, /// Fill rate (fills per hour) pub fill_rate: f64, } /// Execution performance tracking #[derive(Debug)] pub struct ExecutionPerformanceTracker { /// Performance metrics by algorithm algorithm_performance: HashMap, /// Slippage measurements #[allow(dead_code)] slippage_tracker: SlippageTracker, /// Implementation shortfall tracker #[allow(dead_code)] shortfall_tracker: ShortfallTracker, } /// Algorithm performance metrics #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AlgorithmPerformance { /// Algorithm name pub algorithm: String, /// Total executions pub total_executions: u64, /// Average slippage (basis points) pub average_slippage_bps: f64, /// Average execution time pub average_execution_time_ms: f64, /// Fill rate pub fill_rate: f64, /// Market impact pub average_market_impact_bps: f64, /// Success rate pub success_rate: f64, /// Last updated pub last_updated: chrono::DateTime, } /// Slippage tracking #[derive(Debug)] pub struct SlippageTracker { /// Slippage measurements #[allow(dead_code)] measurements: VecDeque, /// Slippage statistics by symbol #[allow(dead_code)] stats_by_symbol: HashMap, } /// Slippage measurement #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SlippageMeasurement { /// Order ID pub order_id: String, /// Symbol pub symbol: String, /// Expected price (at order submission) pub expected_price: f64, /// Actual execution price pub execution_price: f64, /// Slippage in basis points pub slippage_bps: f64, /// Order quantity pub quantity: f64, /// Execution timestamp pub timestamp: chrono::DateTime, } /// Slippage statistics #[derive(Debug, Clone)] pub struct SlippageStatistics { /// Average slippage pub average_slippage_bps: f64, /// Slippage standard deviation pub slippage_std_bps: f64, /// 95th percentile slippage pub slippage_95th_percentile_bps: f64, /// Number of measurements pub measurement_count: u64, } /// Implementation shortfall tracking #[derive(Debug)] pub struct ShortfallTracker {} /// Implementation shortfall measurement #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ShortfallMeasurement { /// Order ID pub order_id: String, /// Symbol pub symbol: String, /// Decision price (at strategy decision) pub decision_price: f64, /// Average execution price pub execution_price: f64, /// Implementation shortfall (basis points) pub shortfall_bps: f64, /// Delay cost pub delay_cost_bps: f64, /// Market impact cost pub market_impact_bps: f64, /// Timing cost pub timing_cost_bps: f64, /// Execution timestamp pub timestamp: chrono::DateTime, } /// Smart order routing system #[derive(Debug)] pub struct SmartOrderRouter { /// Available venues venues: Vec, /// Routing rules #[allow(dead_code)] routing_rules: HashMap, /// Venue performance tracker #[allow(dead_code)] venue_performance: HashMap, } /// Trading venue information #[derive(Debug, Clone)] pub struct TradingVenue { /// Venue name pub name: String, /// Venue type pub venue_type: VenueType, /// Supported symbols pub supported_symbols: Vec, /// Minimum order size pub min_order_size: f64, /// Maximum order size pub max_order_size: f64, /// Commission structure pub commission_rate: f64, /// Dark pool preference pub is_dark_pool: bool, /// Latency (microseconds) pub latency_us: u64, } /// Venue type #[derive(Debug, Clone)] pub enum VenueType { /// Primary exchange Exchange, /// Electronic Communication Network ECN, /// Dark pool DarkPool, /// Alternative Trading System ATS, /// Market maker MarketMaker, } /// Routing rule #[derive(Debug, Clone)] pub struct RoutingRule { /// Rule name pub name: String, /// Symbol pattern pub symbol_pattern: String, /// Order size range pub size_range: (f64, f64), /// Preferred venues pub preferred_venues: Vec, /// Dark pool percentage pub dark_pool_percentage: f64, /// Time-based routing pub time_based: bool, } /// Venue performance metrics #[derive(Debug, Clone)] pub struct VenuePerformance { /// Venue name pub venue: String, /// Fill rate pub fill_rate: f64, /// Average execution time pub average_execution_time_ms: f64, /// Average slippage pub average_slippage_bps: f64, /// Reject rate pub reject_rate: f64, /// Last updated pub last_updated: chrono::DateTime, } /// Execution request #[derive(Debug, Clone)] pub struct ExecutionRequest { /// Request ID pub id: String, /// Symbol to trade pub symbol: String, /// Order side pub side: OrderSide, /// Quantity to execute pub quantity: f64, /// Execution algorithm preference pub algorithm: ExecutionAlgorithm, /// Execution parameters pub parameters: HashMap, /// Maximum slippage tolerance pub max_slippage_bps: f64, /// Execution deadline pub deadline: Option>, /// Dark pool preference pub dark_pool_preference: f64, } /// Execution result #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExecutionResult { /// Request ID pub request_id: String, /// Execution status pub status: ExecutionStatus, /// Child orders created pub child_orders: Vec, /// Fills received pub fills: Vec, /// Execution metrics pub metrics: ExecutionMetrics, /// Completion timestamp pub completed_at: Option>, } /// Execution status #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ExecutionStatus { /// Execution in progress InProgress, /// Execution completed successfully Completed, /// Execution partially completed PartiallyCompleted, /// Execution failed Failed, /// Execution cancelled Cancelled, } /// Execution metrics #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExecutionMetrics { /// Volume-weighted average price pub vwap: f64, /// Total slippage (basis points) pub slippage_bps: f64, /// Implementation shortfall (basis points) pub implementation_shortfall_bps: f64, /// Market impact (basis points) pub market_impact_bps: f64, /// Execution time (milliseconds) pub execution_time_ms: f64, /// Fill rate pub fill_rate: f64, /// Number of child orders pub child_order_count: u32, /// Number of venues used pub venue_count: u32, } /// Base trait for execution algorithms pub trait ExecutionAlgorithmTrait: std::fmt::Debug { /// Algorithm name fn name(&self) -> &str; /// Execute a trade request fn execute( &mut self, request: &ExecutionRequest, order_manager: &mut OrderManager, microstructure: &MicrostructureAnalyzer, ) -> Result>; /// Update algorithm with market data fn update_market_data( &mut self, symbol: &str, trades: &[Trade], book: &[OrderLevel], ) -> Result<()>; /// Get algorithm parameters fn get_parameters(&self) -> HashMap; /// Set algorithm parameters fn set_parameters(&mut self, parameters: HashMap) -> Result<()>; } /// Time-Weighted Average Price (TWAP) algorithm #[derive(Debug)] pub struct TWAPAlgorithm { /// Algorithm name name: String, /// Execution window duration window_duration: Duration, /// Number of slices slice_count: u32, /// Current slice #[allow(dead_code)] current_slice: u32, /// Slice orders #[allow(dead_code)] slice_orders: Vec, } /// Volume-Weighted Average Price (VWAP) algorithm #[derive(Debug)] pub struct VWAPAlgorithm { /// Algorithm name name: String, /// Historical volume profile #[allow(dead_code)] volume_profile: HashMap, /// Participation rate participation_rate: f64, /// Current volume tracking #[allow(dead_code)] volume_tracker: VolumeTracker, } /// Volume profile for VWAP calculation #[derive(Debug, Clone)] pub struct VolumeProfile { /// Time buckets #[allow(dead_code)] buckets: Vec, /// Profile date #[allow(dead_code)] date: NaiveDate, } /// Volume bucket #[derive(Debug, Clone)] pub struct VolumeBucket { /// Time period pub time_period: (chrono::NaiveTime, chrono::NaiveTime), /// Volume percentage pub volume_percentage: f64, /// Historical average volume pub average_volume: f64, } /// Volume tracking for VWAP #[derive(Debug)] pub struct VolumeTracker { /// Current period volumes #[allow(dead_code)] period_volumes: HashMap, /// Target volumes #[allow(dead_code)] target_volumes: HashMap, } /// Implementation Shortfall algorithm #[derive(Debug)] pub struct ImplementationShortfallAlgorithm { /// Algorithm name name: String, /// Risk aversion parameter risk_aversion: f64, /// Market impact model #[allow(dead_code)] impact_model: MarketImpactModel, /// Optimal schedule #[allow(dead_code)] execution_schedule: Vec, } /// Market impact model #[derive(Debug)] pub struct MarketImpactModel { /// Temporary impact coefficient #[allow(dead_code)] temp_impact_coeff: f64, /// Permanent impact coefficient #[allow(dead_code)] perm_impact_coeff: f64, /// Volatility estimate #[allow(dead_code)] volatility: f64, } /// Execution schedule slice #[derive(Debug, Clone)] pub struct ScheduleSlice { /// Slice start time pub start_time: chrono::DateTime, /// Slice end time pub end_time: chrono::DateTime, /// Target quantity for this slice pub target_quantity: f64, /// Execution urgency pub urgency: f64, } impl ExecutionEngine { /// Create a new execution engine /// /// # Arguments /// /// * `config` - Execution configuration /// /// # Returns /// /// A new `ExecutionEngine` instance pub fn new(config: ExecutionConfig) -> Result { info!( "Initializing execution engine with algorithm: {:?}", config.algorithm ); let mut algorithms: HashMap> = HashMap::new(); // Initialize available algorithms algorithms.insert("TWAP".to_owned(), Box::new(TWAPAlgorithm::new()?)); algorithms.insert("VWAP".to_owned(), Box::new(VWAPAlgorithm::new()?)); algorithms.insert( "ImplementationShortfall".to_owned(), Box::new(ImplementationShortfallAlgorithm::new()?), ); let order_manager = OrderManager::new(); let performance_tracker = ExecutionPerformanceTracker::new(); let smart_router = SmartOrderRouter::new()?; Ok(Self { config, algorithms, order_manager, performance_tracker, smart_router, }) } /// Execute a trade request /// /// # Arguments /// /// * `request` - Execution request /// * `microstructure` - Market microstructure analyzer /// /// # Returns /// /// Execution result pub async fn execute_trade( &mut self, request: ExecutionRequest, microstructure: &MicrostructureAnalyzer, ) -> Result { info!( "Executing trade: {} {} {} with {:?}", request.side as u8, request.quantity, request.symbol, request.algorithm ); let start_time = Instant::now(); // Select execution algorithm let algorithm_name = match request.algorithm { ExecutionAlgorithm::TWAP => "TWAP", ExecutionAlgorithm::VWAP => "VWAP", ExecutionAlgorithm::IS => "ImplementationShortfall", ExecutionAlgorithm::ImplementationShortfall => "ImplementationShortfall", ExecutionAlgorithm::ArrivalPrice => "TWAP", // Use TWAP as fallback ExecutionAlgorithm::POV => "VWAP", // Use VWAP for POV (Percentage of Volume) }; // Execute using selected algorithm let request_clone = request.clone(); let child_orders = if let Some(algorithm) = self.algorithms.get_mut(algorithm_name) { algorithm.execute(&request_clone, &mut self.order_manager, microstructure)? } else { return Err(anyhow::anyhow!( "Algorithm {} not available", algorithm_name )); }; // Track child order IDs let child_order_ids: Vec = child_orders.iter().map(|o| o.id.to_string()).collect(); // Submit orders through smart router for order in child_orders { self.submit_order_with_routing(order).await?; } // Wait for execution completion or timeout let fills = self.monitor_execution(&request, &child_order_ids).await?; let execution_time = start_time.elapsed().as_millis() as f64; // Calculate execution metrics let metrics = self.calculate_execution_metrics(&request, &fills, execution_time)?; // Update performance tracking self.performance_tracker .update_algorithm_performance(algorithm_name, &metrics); let status = if fills.is_empty() { ExecutionStatus::Failed } else if fills.iter().map(|f| f.quantity).sum::() >= request.quantity { ExecutionStatus::Completed } else { ExecutionStatus::PartiallyCompleted }; Ok(ExecutionResult { request_id: request.id, status, child_orders: child_order_ids, fills, metrics, completed_at: Some(chrono::Utc::now()), }) } /// Submit order with smart routing async fn submit_order_with_routing(&mut self, order: Order) -> Result<()> { let venue = self.smart_router.select_venue(&order)?; // Submit order to selected venue (production) info!("Submitting order {} to venue {}", order.id, venue); // Update order status self.order_manager .update_order_status(&order.id.to_string(), OrderStatus::Submitted)?; Ok(()) } /// Monitor execution progress async fn monitor_execution( &mut self, request: &ExecutionRequest, child_order_ids: &[String], ) -> Result> { let mut fills = Vec::new(); let timeout = Duration::from_millis(self.config.order_timeout.as_millis() as u64); let start_time = Instant::now(); // Monitor orders until completion or timeout while start_time.elapsed() < timeout { // Check for new fills (production implementation) for order_id in child_order_ids { if let Some(new_fills) = self.check_for_fills(order_id).await? { fills.extend(new_fills); } } // Check if execution is complete let total_filled: f64 = fills.iter().map(|f| f.quantity).sum(); if total_filled >= request.quantity { break; } // Sleep before next check tokio::time::sleep(Duration::from_millis(100_u64)).await; } Ok(fills) } /// Check for new fills (production) async fn check_for_fills(&self, _order_id: &str) -> Result>> { // Production implementation - would integrate with actual execution venues Ok(None) } /// Calculate execution metrics fn calculate_execution_metrics( &self, request: &ExecutionRequest, fills: &[Fill], execution_time_ms: f64, ) -> Result { if fills.is_empty() { return Ok(ExecutionMetrics { vwap: 0.0, slippage_bps: 0.0_f64, implementation_shortfall_bps: 0.0_f64, market_impact_bps: 0.0_f64, execution_time_ms, fill_rate: 0.0_f64, child_order_count: 0_u32, venue_count: 0_u32, }); } // Calculate VWAP let total_value: f64 = fills.iter().map(|f| f.price * f.quantity).sum(); let total_quantity: f64 = fills.iter().map(|f| f.quantity).sum(); let vwap = total_value / total_quantity; // Calculate fill rate let fill_rate = total_quantity / request.quantity; // Calculate unique venues let venues: std::collections::HashSet<_> = fills.iter().map(|f| &f.venue).collect(); let venue_count = venues.len() as u32; Ok(ExecutionMetrics { vwap, slippage_bps: 0.0_f64, // Would calculate based on benchmark implementation_shortfall_bps: 0.0_f64, // Would calculate based on decision price market_impact_bps: 0.0_f64, // Would calculate based on price movement execution_time_ms, fill_rate, child_order_count: 0_u32, // Would track actual child orders venue_count, }) } /// Get execution performance metrics pub fn get_performance_metrics(&self) -> &HashMap { &self.performance_tracker.algorithm_performance } /// Update algorithm parameters pub fn update_algorithm_parameters( &mut self, algorithm: &str, parameters: HashMap, ) -> Result<()> { if let Some(algo) = self.algorithms.get_mut(algorithm) { algo.set_parameters(parameters)?; info!("Updated parameters for algorithm: {}", algorithm); } else { warn!("Algorithm {} not found", algorithm); } Ok(()) } } impl Default for OrderManager { fn default() -> Self { Self::new() } } impl OrderManager { /// Create a new order manager pub fn new() -> Self { Self { active_orders: Default::default(), order_history: VecDeque::new(), fill_tracker: FillTracker::new(), next_order_id: 1_u64, } } /// Create a new order pub fn create_order( &mut self, symbol: String, side: OrderSide, quantity: f64, order_type: OrderType, price: Option, execution_algorithm: String, ) -> Order { let id = format!("ORD{:08}", self.next_order_id); self.next_order_id += 1; let order = Order { // Core Identity id: id.clone().into(), client_order_id: None, broker_order_id: None, account_id: None, // Trading Details symbol: symbol.into(), side, order_type, status: OrderStatus::New, time_in_force: TimeInForce::GoodTillCancel, // Quantities & Pricing quantity: Quantity::from_f64(quantity).unwrap_or_default(), price: price.map(|p| Price::from_f64(p).unwrap_or_default()), stop_price: None, filled_quantity: Quantity::default(), remaining_quantity: Quantity::from_f64(quantity).unwrap_or_default(), average_price: None, avg_fill_price: None, average_fill_price: None, // Strategy Fields parent_id: None, execution_algorithm: Some(execution_algorithm), execution_params: serde_json::Value::Object(serde_json::Map::new()), // Risk Management stop_loss: None, take_profit: None, // Timestamps created_at: HftTimestamp::now_or_zero(), updated_at: Some(HftTimestamp::now_or_zero()), expires_at: None, exchange_order_id: None, // Extensibility metadata: serde_json::Value::Object(serde_json::Map::new()), }; self.active_orders.insert(id, order.clone()); order } /// Update order status pub fn update_order_status(&mut self, order_id: &str, status: OrderStatus) -> Result<()> { if let Some(order) = self.active_orders.get_mut(order_id) { order.status = status; order.updated_at = Some(HftTimestamp::now_or_zero()); // Move to history if terminal status match status { OrderStatus::Filled | OrderStatus::Cancelled | OrderStatus::Rejected | OrderStatus::Expired => { if let Some(order) = self.active_orders.remove(order_id) { self.order_history.push_back(order); // Maintain history size if self.order_history.len() > 10000_usize { self.order_history.pop_front(); } } }, _ => {}, } } Ok(()) } /// Add fill pub fn add_fill(&mut self, fill: Fill) -> Result<()> { // Update order if let Some(order) = self.active_orders.get_mut(&fill.order_id) { let current_remaining = order.remaining_quantity.to_f64(); let new_remaining = current_remaining - fill.quantity; order.remaining_quantity = Quantity::from_f64(new_remaining.max(0.0)).unwrap_or_default(); if order.remaining_quantity.to_f64() <= 0.0_f64 { order.status = OrderStatus::Filled; } else { order.status = OrderStatus::PartiallyFilled; } order.updated_at = Some(HftTimestamp::now_or_zero()); } // Track fill self.fill_tracker.add_fill(fill)?; Ok(()) } /// Get active orders pub fn get_active_orders(&self) -> &HashMap { &self.active_orders } /// Get order history pub fn get_order_history(&self) -> &VecDeque { &self.order_history } } impl Default for FillTracker { fn default() -> Self { Self::new() } } impl FillTracker { /// Create a new fill tracker pub fn new() -> Self { Self { fills: VecDeque::new(), fill_stats: Default::default(), } } /// Add a fill pub fn add_fill(&mut self, fill: Fill) -> Result<()> { // Update statistics let stats = self .fill_stats .entry(fill.order_id.clone()) .or_insert(FillStatistics { total_fills: 0_u64, total_volume: 0.0_f64, vwap: 0.0_f64, average_fill_size: 0.0_f64, fill_rate: 0.0_f64, }); stats.total_fills += 1_u64; stats.total_volume += fill.quantity; stats.vwap = ((stats.vwap * (stats.total_fills - 1_u64) as f64) + fill.price) / stats.total_fills as f64; stats.average_fill_size = stats.total_volume / stats.total_fills as f64; // Add to history self.fills.push_back(fill); // Maintain history size if self.fills.len() > 10000_usize { self.fills.pop_front(); } Ok(()) } /// Get fill statistics pub fn get_fill_statistics(&self, symbol: &str) -> Option<&FillStatistics> { self.fill_stats.get(symbol) } } impl Default for ExecutionPerformanceTracker { fn default() -> Self { Self::new() } } impl ExecutionPerformanceTracker { /// Create a new performance tracker pub fn new() -> Self { Self { algorithm_performance: HashMap::new(), slippage_tracker: SlippageTracker::new(), shortfall_tracker: ShortfallTracker::new(), } } /// Update algorithm performance pub fn update_algorithm_performance(&mut self, algorithm: &str, metrics: &ExecutionMetrics) { let perf = self .algorithm_performance .entry(algorithm.to_string()) .or_insert(AlgorithmPerformance { algorithm: algorithm.to_string(), total_executions: 0_u64, average_slippage_bps: 0.0_f64, average_execution_time_ms: 0.0_f64, fill_rate: 0.0_f64, average_market_impact_bps: 0.0_f64, success_rate: 0.0_f64, last_updated: chrono::Utc::now(), }); // Update running averages let weight = 1.0_f64 / (perf.total_executions + 1_u64) as f64; perf.average_slippage_bps = (1.0_f64 - weight) * perf.average_slippage_bps + weight * metrics.slippage_bps; perf.average_execution_time_ms = (1.0_f64 - weight) * perf.average_execution_time_ms + weight * metrics.execution_time_ms; perf.fill_rate = (1.0_f64 - weight) * perf.fill_rate + weight * metrics.fill_rate; perf.average_market_impact_bps = (1.0_f64 - weight) * perf.average_market_impact_bps + weight * metrics.market_impact_bps; perf.total_executions += 1_u64; perf.last_updated = chrono::Utc::now(); } } impl Default for SlippageTracker { fn default() -> Self { Self::new() } } impl SlippageTracker { /// Create a new slippage tracker pub fn new() -> Self { Self { measurements: VecDeque::new(), stats_by_symbol: HashMap::new(), } } } impl Default for ShortfallTracker { fn default() -> Self { Self::new() } } impl ShortfallTracker { /// Create a new shortfall tracker pub fn new() -> Self { Self {} } } impl SmartOrderRouter { /// Create a new smart order router pub fn new() -> Result { // Initialize with default venues let venues = vec![ TradingVenue { name: "PRIMARY".to_owned(), venue_type: VenueType::Exchange, supported_symbols: vec!["*".to_owned()], // All symbols min_order_size: 1.0_f64, max_order_size: 1000000.0_f64, commission_rate: 0.0005_f64, is_dark_pool: false, latency_us: 100_u64, }, TradingVenue { name: "DARK1".to_owned(), venue_type: VenueType::DarkPool, supported_symbols: vec!["*".to_owned()], min_order_size: 100.0_f64, max_order_size: 100000.0_f64, commission_rate: 0.0003_f64, is_dark_pool: true, latency_us: 200_u64, }, ]; Ok(Self { venues, routing_rules: HashMap::new(), venue_performance: HashMap::new(), }) } /// Select optimal venue for order pub fn select_venue(&self, order: &Order) -> Result { // Simple venue selection logic for venue in &self.venues { if venue.min_order_size <= order.quantity && order.quantity <= venue.max_order_size { return Ok(venue.name.clone()); } } // Default to first venue Ok(self .venues .first() .map(|v| v.name.clone()) .unwrap_or_else(|| "DEFAULT".to_owned())) } } // Algorithm implementations impl TWAPAlgorithm { /// Create a new TWAP algorithm pub fn new() -> Result { Ok(Self { name: "TWAP".to_owned(), window_duration: Duration::from_secs(300_u64), // 5 minutes slice_count: 10_u32, current_slice: 0_u32, slice_orders: Vec::new(), }) } } impl ExecutionAlgorithmTrait for TWAPAlgorithm { fn name(&self) -> &str { &self.name } fn execute( &mut self, request: &ExecutionRequest, order_manager: &mut OrderManager, _microstructure: &MicrostructureAnalyzer, ) -> Result> { let slice_size = request.quantity / self.slice_count as f64; let mut orders = Vec::new(); // Create orders for each time slice for _i in 0..self.slice_count { let order = order_manager.create_order( request.symbol.clone(), request.side, slice_size, OrderType::Market, None, "TWAP".to_owned(), ); orders.push(order); } info!("TWAP algorithm created {} slice orders", orders.len()); Ok(orders) } fn update_market_data( &mut self, _symbol: &str, _trades: &[Trade], _book: &[OrderLevel], ) -> Result<()> { // TWAP doesn't need market data updates Ok(()) } fn get_parameters(&self) -> HashMap { let mut params = HashMap::new(); params.insert( "window_duration_seconds".to_owned(), self.window_duration.as_secs() as f64, ); params.insert("slice_count".to_owned(), self.slice_count as f64); params } fn set_parameters(&mut self, parameters: HashMap) -> Result<()> { if let Some(&duration) = parameters.get("window_duration_seconds") { self.window_duration = Duration::from_secs(duration as u64); } if let Some(&count) = parameters.get("slice_count") { self.slice_count = count as u32; } Ok(()) } } impl VWAPAlgorithm { /// Create a new VWAP algorithm pub fn new() -> Result { Ok(Self { name: "VWAP".to_owned(), volume_profile: HashMap::new(), participation_rate: 0.1_f64, // 10% participation volume_tracker: VolumeTracker::new(), }) } } impl ExecutionAlgorithmTrait for VWAPAlgorithm { fn name(&self) -> &str { &self.name } fn execute( &mut self, request: &ExecutionRequest, order_manager: &mut OrderManager, _microstructure: &MicrostructureAnalyzer, ) -> Result> { // Simplified VWAP implementation let order = order_manager.create_order( request.symbol.clone(), request.side, request.quantity, OrderType::Market, None, "VWAP".to_owned(), ); info!("VWAP algorithm created market order"); Ok(vec![order]) } fn update_market_data( &mut self, symbol: &str, _trades: &[Trade], _book: &[OrderLevel], ) -> Result<()> { // Update volume tracking for VWAP calculation debug!("Updating VWAP market data for {}", symbol); Ok(()) } fn get_parameters(&self) -> HashMap { let mut params = HashMap::new(); params.insert("participation_rate".to_owned(), self.participation_rate); params } fn set_parameters(&mut self, parameters: HashMap) -> Result<()> { if let Some(&rate) = parameters.get("participation_rate") { self.participation_rate = rate; } Ok(()) } } impl Default for VolumeTracker { fn default() -> Self { Self::new() } } impl VolumeTracker { /// Create a new volume tracker pub fn new() -> Self { Self { period_volumes: HashMap::new(), target_volumes: HashMap::new(), } } } impl ImplementationShortfallAlgorithm { /// Create a new Implementation Shortfall algorithm pub fn new() -> Result { Ok(Self { name: "ImplementationShortfall".to_owned(), risk_aversion: 1e-6_f64, impact_model: MarketImpactModel::new(), execution_schedule: Vec::new(), }) } } impl ExecutionAlgorithmTrait for ImplementationShortfallAlgorithm { fn name(&self) -> &str { &self.name } fn execute( &mut self, request: &ExecutionRequest, order_manager: &mut OrderManager, _microstructure: &MicrostructureAnalyzer, ) -> Result> { // Simplified IS implementation let order = order_manager.create_order( request.symbol.clone(), request.side, request.quantity, OrderType::Limit, Some( request .parameters .get("limit_price") .copied() .unwrap_or(100.0_f64), ), "ImplementationShortfall".to_owned(), ); info!("Implementation Shortfall algorithm created limit order"); Ok(vec![order]) } fn update_market_data( &mut self, symbol: &str, _trades: &[Trade], _book: &[OrderLevel], ) -> Result<()> { debug!("Updating IS market data for {}", symbol); Ok(()) } fn get_parameters(&self) -> HashMap { let mut params = HashMap::new(); params.insert("risk_aversion".to_owned(), self.risk_aversion); params } fn set_parameters(&mut self, parameters: HashMap) -> Result<()> { if let Some(&aversion) = parameters.get("risk_aversion") { self.risk_aversion = aversion; } Ok(()) } } impl Default for MarketImpactModel { fn default() -> Self { Self::new() } } impl MarketImpactModel { /// Create a new market impact model pub fn new() -> Self { Self { temp_impact_coeff: 0.01_f64, perm_impact_coeff: 0.001_f64, volatility: 0.02_f64, } } } #[cfg(test)] mod tests { use super::*; use common::Symbol; #[test] fn test_execution_engine_creation() { let config = ExecutionConfig { algorithm: ExecutionAlgorithm::TWAP, max_order_size: 10000.0_f64, min_order_size: 100.0_f64, order_timeout: Duration::from_secs(30_u64), max_slippage_bps: 10.0_f64, smart_routing_enabled: true, dark_pool_preference: 0.3_f64, }; let engine = ExecutionEngine::new(config); assert!(engine.is_ok()); } #[test] fn test_order_manager() { let mut manager = OrderManager::new(); let order = manager.create_order( "BTC-USD".to_owned(), OrderSide::Buy, 100.0_f64, OrderType::Market, None, "TEST".to_owned(), ); assert_eq!(order.symbol.as_str(), "BTC-USD"); assert_eq!(order.quantity, 100.0_f64); assert!(matches!(order.status, OrderStatus::New)); } #[test] fn test_twap_algorithm() { let twap = TWAPAlgorithm::new().unwrap(); let _order_manager = OrderManager::new(); let _request = ExecutionRequest { id: "REQ001".to_owned(), symbol: "BTC-USD".to_owned(), side: OrderSide::Buy, quantity: 1000.0_f64, algorithm: ExecutionAlgorithm::TWAP, parameters: HashMap::new(), max_slippage_bps: 10.0_f64, deadline: None, dark_pool_preference: 0.0_f64, }; // Note: microstructure analyzer is needed but we can't easily create one in tests // This would need more sophisticated test setup let params = twap.get_parameters(); assert!(params.contains_key("slice_count")); } #[test] fn test_smart_order_router() { let router = SmartOrderRouter::new().unwrap(); assert!(!router.venues.is_empty()); let order = Order::new( Symbol::from("BTC-USD"), OrderSide::Buy, Quantity::new(500.0_f64).unwrap(), None, OrderType::Market, ); let venue = router.select_venue(&order); assert!(venue.is_ok()); } }