//! Machine Learning Models for Foxhunt //! //! This crate provides comprehensive machine learning models and algorithms //! for the Foxhunt high-frequency trading system. All ML operations use //! enterprise-grade safety controls to prevent system failures. //! //! ## Safety Features //! //! - **Comprehensive mathematical safety**: All operations handle NaN/Infinity gracefully //! - **Tensor bounds checking**: Prevents buffer overflows and memory issues //! - **Model drift detection**: Automatic monitoring of model performance degradation //! - **Financial validation**: Ensures all predictions use unified financial types //! - **Memory management**: Prevents OOM conditions and memory leaks //! - **Timeout handling**: Prevents hanging operations //! //! ## Usage //! //! ```rust //! use ml_models::safety::{get_global_safety_manager, MLSafetyConfig}; //! //! // Initialize safety with custom configuration //! let config = MLSafetyConfig::default(); //! let safety_manager = get_global_safety_manager(); //! //! // All ML operations should go through the safety manager //! let result = safety_manager.safe_math_operation("prediction", || { //! // Your ML computation here //! Ok(42.0) //! }).await?; //! ``` #![warn(missing_docs)] #![warn(missing_debug_implementations)] #![warn(rust_2018_idioms)] #![warn(missing_docs)] #![warn(missing_debug_implementations)] #![warn(rust_2018_idioms)] #![deny( clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::unreachable, clippy::indexing_slicing )] // Import the trading_engine types with an alias to avoid std::core conflicts pub use trading_engine as types; use serde::{Deserialize, Serialize}; // Missing type definitions for ML crate compatibility #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Trade { pub symbol: String, pub price: common::Price, pub quantity: common::Decimal, pub timestamp: u64, pub side: String, } // Health status for ensemble models #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum HealthStatus { Healthy, Degraded, Unhealthy, } // Re-export from trading_engine for easier access pub use trading_engine::prelude::*; // Placeholder types for compilation - should be imported from appropriate crates in production #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MarketDataSnapshot { pub timestamp: chrono::DateTime, pub symbol: String, pub price: common::Price, pub volume: common::Decimal, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FeatureVector(pub Vec); #[derive(Debug, Clone, Serialize, Deserialize)] pub struct IntegerTensor(pub Vec); #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateSummary { pub updated_models: usize, pub total_models: usize, } /// Common imports for ML module consumers pub mod prelude { pub use crate::error::*; pub use crate::traits::*; pub use crate::types::prelude::*; // Export canonical ML types pub use crate::{InferenceResult, ModelMetadata, ModelType}; // Export unified ML interface pub use crate::{ get_global_registry, Features, Feedback, MLModel, ModelPrediction, ModelRegistry, }; // Export performance optimizations pub use crate::{HFTPerformanceProfile, LatencyOptimizer, ParallelExecutor}; // Export model_loader for ML model loading and caching pub use model_loader::{ CacheConfig, ModelCacheTrait, ModelLoaderConfig, ModelLoaderFactory, ModelLoaderResult, ModelLoaderTrait, }; pub use model_loader::{ModelMetadata as LoaderModelMetadata, ModelType as LoaderModelType}; } use thiserror::Error; /// Machine Learning specific errors #[derive(Debug, Clone, Error, Serialize, Deserialize)] pub enum MLError { /// Configuration error #[error("Configuration error: {reason}")] ConfigError { reason: String }, /// Configuration error (alternative naming) #[error("Configuration error: {0}")] ConfigurationError(String), /// Dimension mismatch error #[error("Dimension mismatch: expected {expected}, got {actual}")] DimensionMismatch { expected: usize, actual: usize }, /// Graph-related error #[error("Graph error: {message}")] GraphError { message: String }, /// Resource limit exceeded #[error("Resource limit exceeded: {resource} limit {limit}")] ResourceLimit { resource: String, limit: usize }, /// Serialization error #[error("Serialization error: {reason}")] SerializationError { reason: String }, /// Validation error #[error("Validation error: {message}")] ValidationError { message: String }, /// Concurrency error #[error("Concurrency error in operation: {operation}")] ConcurrencyError { operation: String }, /// Invalid input error #[error("Invalid input: {0}")] InvalidInput(String), /// Training error #[error("Training error: {0}")] TrainingError(String), /// Inference error #[error("Inference error: {0}")] InferenceError(String), /// Model error #[error("Model error: {0}")] ModelError(String), /// Model not trained error #[error("Model not trained: {0}")] NotTrained(String), /// Anyhow error wrapping #[error("General error: {0}")] AnyhowError(String), /// Tensor creation error #[error("Tensor creation error in {operation}: {reason}")] TensorCreationError { operation: String, reason: String }, /// Lock error #[error("Lock error: {0}")] LockError(String), /// Model not found error #[error("Model not found: {0}")] ModelNotFound(String), /// Insufficient data error #[error("Insufficient data: {0}")] InsufficientData(String), } // Implement From trait for candle_core::Error impl From for MLError { fn from(err: candle_core::Error) -> Self { MLError::ModelError(format!("Candle error: {}", err)) } } // NOTE: Commented out workspace dependency - will be re-enabled when workspace is available // impl From for MLError { // fn from(err: error_handling::TradingError) -> Self { // match err { // error_handling::TradingError::InvalidPrice { value, reason } => { // MLError::ValidationError { // message: format!("Invalid price {}: {}", value, reason), // } // } // error_handling::TradingError::InvalidQuantity { value, reason } => { // MLError::ValidationError { // message: format!("Invalid quantity {}: {}", value, reason), // } // } // error_handling::TradingError::FinancialSafety { message, .. } => { // MLError::ValidationError { // message: format!("Financial safety error: {}", message), // } // } // error_handling::TradingError::DivisionByZero { operation } => { // MLError::ValidationError { // message: format!("Division by zero in {}", operation), // } // } // error_handling::TradingError::ModelInference { reason, model } => { // MLError::InferenceError(format!("Model inference error for {}: {}", model, reason)) // } // error_handling::TradingError::GpuComputation { reason, operation } => { // let msg = match operation { // Some(op) => format!("GPU computation error ({}): {}", op, reason), // None => format!("GPU computation error: {}", reason), // }; // MLError::ModelError(msg) // } // other => MLError::ModelError(format!("Trading error: {}", other)), // } // } // } // Implement From trait for anyhow::Error impl From for MLError { fn from(err: anyhow::Error) -> Self { MLError::AnyhowError(err.to_string()) } } // UNIFIED ERROR HANDLING: Convert all ML errors to CommonError for workspace consistency impl From for common::error::CommonError { fn from(err: MLError) -> Self { use common::error::{CommonError, ErrorCategory}; match err { MLError::ConfigError { reason } => CommonError::config( format!("ML configuration error: {}", reason) ), MLError::DimensionMismatch { expected, actual } => CommonError::validation( format!("ML dimension mismatch: expected {}, got {}", expected, actual) ), MLError::ValidationError { message } => CommonError::validation( format!("ML validation error: {}", message) ), MLError::InferenceError(msg) => CommonError::service( ErrorCategory::System, format!("ML inference error: {}", msg) ), MLError::TrainingError(msg) => CommonError::service( ErrorCategory::System, format!("ML training error: {}", msg) ), MLError::ModelError(msg) => CommonError::service( ErrorCategory::System, format!("ML model error: {}", msg) ), MLError::TensorCreationError { operation, reason } => CommonError::service( ErrorCategory::System, format!("ML tensor creation error in {}: {}", operation, reason) ), _ => CommonError::service( ErrorCategory::System, format!("ML error: {}", err) ), } } } // Convert common type errors to MLError (for backward compatibility) impl From for MLError { fn from(err: common::types::CommonTypeError) -> Self { MLError::ModelError(format!("Common type error: {}", err)) } } impl From for MLError { fn from(err: serde_json::Error) -> Self { MLError::SerializationError { reason: err.to_string(), } } } impl From for MLError { fn from(err: inference::RealInferenceError) -> Self { match err { inference::RealInferenceError::GpuRequired { reason } => { MLError::ModelError(format!("GPU required: {}", reason)) } inference::RealInferenceError::ComputationFailed { reason } => { MLError::InferenceError(reason) } inference::RealInferenceError::FeatureMismatch { expected, actual } => { MLError::DimensionMismatch { expected, actual } } inference::RealInferenceError::PredictionValidation { reason } => { MLError::ValidationError { message: reason } } inference::RealInferenceError::HardwareError { reason } => { MLError::ModelError(format!("Hardware error: {}", reason)) } other => MLError::InferenceError(other.to_string()), } } } // Implement From for MLError impl From for MLError { fn from(err: training_pipeline::ProductionTrainingError) -> Self { match err { training_pipeline::ProductionTrainingError::ConfigError { reason } => { MLError::ConfigError { reason } } training_pipeline::ProductionTrainingError::ArchitectureError { reason } => { MLError::ModelError(format!("Architecture error: {}", reason)) } training_pipeline::ProductionTrainingError::DataError { reason } => { MLError::ValidationError { message: format!("Data error: {}", reason), } } training_pipeline::ProductionTrainingError::OptimizationError { reason } => { MLError::TrainingError(format!("Optimization error: {}", reason)) } training_pipeline::ProductionTrainingError::FinancialError { reason } => { MLError::ValidationError { message: format!("Financial error: {}", reason), } } training_pipeline::ProductionTrainingError::SafetyViolation { reason } => { MLError::ValidationError { message: format!("Safety violation: {}", reason), } } training_pipeline::ProductionTrainingError::ConvergenceError { reason } => { MLError::TrainingError(format!("Convergence error: {}", reason)) } training_pipeline::ProductionTrainingError::ResourceError { reason } => { MLError::ModelError(format!("Resource error: {}", reason)) } training_pipeline::ProductionTrainingError::GpuRequired { reason } => { MLError::ModelError(format!("GPU required: {}", reason)) } } } } // Note: From trait for liquid::LiquidError is implemented in the liquid module to avoid conflicts /// Result type for ML operations pub type MLResult = Result; /// New unified result type using CommonError for better integration pub type UnifiedMLResult = Result; /// Precision factor for fixed-point arithmetic pub const PRECISION_FACTOR: i64 = 100_000_000; /// Maximum inference latency target in microseconds pub const MAX_INFERENCE_LATENCY_US: u64 = 100; // ========== CORE ML MODULES ========== // Core ML modules pub mod checkpoint; pub mod dqn; pub mod ensemble; pub mod flash_attention; pub mod integration; pub mod labeling; pub mod liquid; pub mod mamba; pub mod microstructure; pub mod ppo; pub mod risk; pub mod safety; pub mod tft; pub mod tgnn; pub mod tlob; pub mod transformers; pub mod universe; // ========== INFRASTRUCTURE MODULES ========== // Infrastructure pub mod benchmarks; pub mod common; pub mod training; // ========== CORE EXPORTS ========== // Core exports pub mod error; pub mod features; pub mod inference; pub mod model; pub mod operations; pub mod performance; pub mod production; pub mod validation; // ========== ADDITIONAL MODULES ========== // Additional ML processing modules pub mod batch_processing; // Batch processing for ML operations pub mod bridge; // Type system bridge for ML-Financial integration pub mod operations_safe; // Safe operations module pub mod ops_production; // Production ML operations pub mod portfolio_transformer; // Portfolio-specific transformer pub mod regime_detection; // Market regime detection pub mod tensor_ops; // TLOB transformer implementation moved to tlob module pub mod examples; // Removed examples_stubs module - contained only placeholder implementations pub mod integration_test; pub mod model_loader_integration; pub mod models_demo; pub mod observability; pub mod stress_testing; // Stress testing framework pub mod training_pipeline; // Complete training pipeline system pub mod traits; // Common traits for ML models // Production observability and monitoring // Integration with model_loader crate // Direct type exports pub use operations as safe_operations; // Re-export essential types for training pub use training::{ActivationType, NetworkConfig, TrainingConfig, TrainingPipeline}; // Re-export safety framework for convenience pub use safety::{ get_global_safety_manager, initialize_ml_safety, GradientSafetyConfig, GradientSafetyManager, GradientStatistics, MLSafetyConfig, MLSafetyError, MLSafetyManager, SafetyResult, SafetyStatus, }; // Re-export core ML types from tgnn module pub use tgnn::types::{TrainingMetrics, ValidationMetrics}; // ========== MISSING TYPES STUBS ========== /// Application result wrapper for ML operations #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MLAppResult { pub data: T, pub success: bool, pub message: Option, pub execution_time_ms: u64, pub metadata: HashMap, } impl MLAppResult { /// Create a successful result pub fn success(data: T) -> Self { Self { data, success: true, message: None, execution_time_ms: 0, metadata: HashMap::new(), } } /// Create a failed result with message pub fn error(data: T, message: String) -> Self { Self { data, success: false, message: Some(message), execution_time_ms: 0, metadata: HashMap::new(), } } /// Set execution time pub fn with_timing(mut self, execution_time_ms: u64) -> Self { self.execution_time_ms = execution_time_ms; self } /// Add metadata pub fn with_metadata(mut self, key: String, value: String) -> Self { self.metadata.insert(key, value); self } } /// Performance profile configuration for HFT models #[derive(Debug, Clone, Serialize, Deserialize)] pub struct HFTPerformanceProfile { pub max_latency_us: u64, pub target_throughput: u32, pub memory_limit_mb: u64, pub cpu_affinity: Option>, pub gpu_enabled: bool, pub batch_size: u32, pub optimization_level: OptimizationLevel, } /// Optimization levels for HFT performance #[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub enum OptimizationLevel { /// Maximum speed, minimal safety checks UltraLow, /// Balanced speed and safety Low, /// Standard optimization Medium, /// Conservative with full validation High, } impl Default for HFTPerformanceProfile { fn default() -> Self { Self { max_latency_us: 100, // 100 microseconds target target_throughput: 10000, // 10k operations per second memory_limit_mb: 1024, // 1GB memory limit cpu_affinity: None, gpu_enabled: false, batch_size: 1, optimization_level: OptimizationLevel::Medium, } } } /// Create HFT performance profile with default settings pub fn create_hft_performance_profile() -> HFTPerformanceProfile { HFTPerformanceProfile::default() } /// Create HFT performance profile with custom latency target pub fn create_hft_performance_profile_with_latency(max_latency_us: u64) -> HFTPerformanceProfile { HFTPerformanceProfile { max_latency_us, ..Default::default() } } /// Create HFT performance profile optimized for ultra-low latency pub fn create_ultra_low_latency_profile() -> HFTPerformanceProfile { HFTPerformanceProfile { max_latency_us: 10, // 10 microseconds target target_throughput: 50000, // 50k operations per second memory_limit_mb: 512, // Reduced memory for cache efficiency gpu_enabled: true, // Enable GPU acceleration batch_size: 1, // No batching for minimal latency optimization_level: OptimizationLevel::UltraLow, ..Default::default() } } // ========== UNIFIED ML MODEL INTERFACE ========== use async_trait::async_trait; use futures::future::join_all; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; /// Features vector for ML model input #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Features { /// Raw feature values pub values: Vec, /// Feature names for debugging pub names: Vec, /// Timestamp of features pub timestamp: u64, /// Symbol these features are for pub symbol: Option, } impl Features { pub fn new(values: Vec, names: Vec) -> Self { Self { values, names, timestamp: std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap_or_default() .as_micros() as u64, symbol: None, } } pub fn with_symbol(mut self, symbol: String) -> Self { self.symbol = Some(symbol); self } } /// Model prediction result #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ModelPrediction { /// Predicted value (price direction, probability, etc.) pub value: f64, /// Model confidence (0.0 to 1.0) pub confidence: f64, /// Additional model-specific metadata pub metadata: HashMap, /// Prediction timestamp pub timestamp: u64, /// Model identifier pub model_id: String, } impl ModelPrediction { pub fn new(model_id: String, value: f64, confidence: f64) -> Self { Self { value, confidence, metadata: HashMap::new(), timestamp: std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap_or_default() .as_micros() as u64, model_id, } } pub fn with_metadata(mut self, key: String, value: serde_json::Value) -> Self { self.metadata.insert(key, value); self } } /// Feedback for model weight updates #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Feedback { /// Actual outcome (for supervised learning) pub actual_value: Option, /// Reward signal (for reinforcement learning) pub reward: Option, /// Trading performance metrics pub performance_metrics: HashMap, /// Timestamp of feedback pub timestamp: u64, } impl Feedback { pub fn new() -> Self { Self { actual_value: None, reward: None, performance_metrics: HashMap::new(), timestamp: std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap_or_default() .as_micros() as u64, } } pub fn with_actual(mut self, actual: f64) -> Self { self.actual_value = Some(actual); self } pub fn with_reward(mut self, reward: f64) -> Self { self.reward = Some(reward); self } } /// Unified interface for all ML models in the system #[async_trait] pub trait MLModel: Send + Sync { /// Get unique model identifier fn name(&self) -> &str; /// Get model type fn model_type(&self) -> ModelType; /// Make prediction based on features async fn predict(&self, features: &Features) -> MLResult; /// Get current model confidence score (0.0 to 1.0) fn get_confidence(&self) -> f64; /// Update model weights based on feedback (optional - not all models support online learning) async fn update_weights(&mut self, _feedback: &Feedback) -> MLResult<()> { // Default implementation does nothing (for immutable models) Ok(()) } /// Check if model is ready for predictions fn is_ready(&self) -> bool { true // Default to ready } /// Get model metadata fn get_metadata(&self) -> ModelMetadata; /// Validate input features fn validate_features(&self, features: &Features) -> MLResult<()> { // Default validation - check for empty features if features.values.is_empty() { return Err(MLError::ValidationError { message: "Empty feature vector".to_string(), }); } Ok(()) } } /// Thread-safe model registry using DashMap for high-performance concurrent access pub struct ModelRegistry { /// Models stored by name models: dashmap::DashMap>, /// Registry metadata metadata: Arc>, } #[derive(Debug, Clone)] struct RegistryMetadata { created_at: std::time::SystemTime, total_registrations: u64, last_access: std::time::SystemTime, } impl ModelRegistry { /// Create new model registry pub fn new() -> Self { Self { models: dashmap::DashMap::new(), metadata: Arc::new(RwLock::new(RegistryMetadata { created_at: std::time::SystemTime::now(), total_registrations: 0, last_access: std::time::SystemTime::now(), })), } } /// Register a model in the registry pub async fn register(&self, model: Arc) -> MLResult<()> { let name = model.name().to_string(); // Check if model is ready if !model.is_ready() { return Err(MLError::ModelError(format!("Model {} is not ready", name))); } self.models.insert(name.clone(), model); // Update metadata { let mut meta = self.metadata.write().await; meta.total_registrations += 1; meta.last_access = std::time::SystemTime::now(); } tracing::info!("Registered ML model: {}", name); Ok(()) } /// Get model by name pub async fn get(&self, name: &str) -> Option> { // Update last access time { let mut meta = self.metadata.write().await; meta.last_access = std::time::SystemTime::now(); } self.models.get(name).map(|entry| entry.value().clone()) } /// Get all registered models pub fn get_all(&self) -> Vec> { self.models .iter() .map(|entry| entry.value().clone()) .collect() } /// Get model names pub fn get_model_names(&self) -> Vec { self.models .iter() .map(|entry| entry.key().clone()) .collect() } /// Remove model from registry pub async fn remove(&self, name: &str) -> Option> { let result = self.models.remove(name).map(|(_, model)| model); if result.is_some() { tracing::info!("Removed ML model: {}", name); } result } /// Get registry statistics pub async fn get_stats(&self) -> RegistryStats { let meta = self.metadata.read().await; RegistryStats { total_models: self.models.len(), total_registrations: meta.total_registrations, created_at: meta.created_at, last_access: meta.last_access, } } /// Parallel prediction across all models pub async fn predict_all(&self, features: &Features) -> Vec> { let models = self.get_all(); let futures = models.iter().map(|model| { let features = features.clone(); async move { model.predict(&features).await } }); join_all(futures).await } /// Parallel prediction across specific models pub async fn predict_selected( &self, model_names: &[String], features: &Features, ) -> Vec> { let futures = model_names.iter().map(|name| { let name = name.clone(); let features = features.clone(); async move { if let Some(model) = self.get(&name).await { model.predict(&features).await } else { Err(MLError::ModelNotFound(name)) } } }); join_all(futures).await } } impl Default for ModelRegistry { fn default() -> Self { Self::new() } } /// Registry statistics #[derive(Debug, Clone)] pub struct RegistryStats { pub total_models: usize, pub total_registrations: u64, pub created_at: std::time::SystemTime, pub last_access: std::time::SystemTime, } /// Global model registry instance (singleton pattern) static GLOBAL_REGISTRY: once_cell::sync::Lazy> = once_cell::sync::Lazy::new(|| Arc::new(ModelRegistry::new())); /// Get global model registry pub fn get_global_registry() -> Arc { GLOBAL_REGISTRY.clone() } // ========== PARALLEL EXECUTION OPTIMIZATIONS ========== /// High-performance parallel executor for ML models optimized for sub-50μs latency pub struct ParallelExecutor { /// Performance profile profile: HFTPerformanceProfile, /// CPU affinity settings cpu_affinity: Option>, /// Thread pool for CPU-bound operations cpu_pool: Arc, /// Async runtime handle runtime_handle: tokio::runtime::Handle, } impl ParallelExecutor { /// Create new parallel executor with HFT performance profile pub fn new(profile: HFTPerformanceProfile) -> Result { // Create dedicated thread pool based on profile let cpu_pool = rayon::ThreadPoolBuilder::new() .num_threads( profile .cpu_affinity .as_ref() .map(|v| v.len()) .unwrap_or(num_cpus::get()), ) .thread_name(|i| format!("ml-cpu-{}", i)) .build() .map_err(|e| MLError::ModelError(format!("Failed to create thread pool: {}", e)))?; let runtime_handle = tokio::runtime::Handle::try_current() .map_err(|e| MLError::ModelError(format!("No tokio runtime available: {}", e)))?; let cpu_affinity = profile.cpu_affinity.clone(); Ok(Self { profile, cpu_affinity, cpu_pool: Arc::new(cpu_pool), runtime_handle, }) } /// Execute parallel predictions with latency optimization pub async fn execute_parallel_predictions( &self, models: Vec>, features: Features, ) -> Vec> { let start_time = std::time::Instant::now(); // Determine execution strategy based on performance profile let results = match self.profile.optimization_level { OptimizationLevel::UltraLow => { // Ultra-low latency: parallel execution with minimal overhead self.execute_ultra_low_latency(models, features).await } OptimizationLevel::Low => { // Low latency: parallel with basic batching self.execute_low_latency(models, features).await } OptimizationLevel::Medium => { // Medium: balanced parallel execution self.execute_balanced(models, features).await } OptimizationLevel::High => { // High: conservative with full validation self.execute_conservative(models, features).await } }; let execution_time = start_time.elapsed(); // Log performance if exceeding target latency if execution_time.as_micros() > self.profile.max_latency_us as u128 { tracing::warn!( "Parallel execution exceeded target latency: {}μs > {}μs", execution_time.as_micros(), self.profile.max_latency_us ); } results } /// Ultra-low latency execution (<10μs target) async fn execute_ultra_low_latency( &self, models: Vec>, features: Features, ) -> Vec> { // Use futures::future::join_all for minimal overhead let futures = models.into_iter().map(|model| { let features = features.clone(); async move { model.predict(&features).await } }); join_all(futures).await } /// Low latency execution with basic optimizations async fn execute_low_latency( &self, models: Vec>, features: Features, ) -> Vec> { // Group models by type for potential batching let mut model_groups: HashMap>> = HashMap::new(); for model in models { let model_type = model.model_type(); model_groups.entry(model_type).or_default().push(model); } let mut all_futures = Vec::new(); for (_, group_models) in model_groups { for model in group_models { let features = features.clone(); all_futures.push(async move { model.predict(&features).await }); } } join_all(all_futures).await } /// Balanced execution with moderate optimizations async fn execute_balanced( &self, models: Vec>, features: Features, ) -> Vec> { // Validate features once for all models for model in &models { if let Err(e) = model.validate_features(&features) { tracing::debug!( "Feature validation failed for model {}: {}", model.name(), e ); } } let futures = models.into_iter().map(|model| { let features = features.clone(); async move { if model.is_ready() { model.predict(&features).await } else { Err(MLError::ModelError(format!( "Model {} not ready", model.name() ))) } } }); join_all(futures).await } /// Conservative execution with full validation async fn execute_conservative( &self, models: Vec>, features: Features, ) -> Vec> { let mut results = Vec::new(); for model in models { // Comprehensive validation if !model.is_ready() { results.push(Err(MLError::ModelError(format!( "Model {} not ready", model.name() )))); continue; } if let Err(e) = model.validate_features(&features) { results.push(Err(e)); continue; } // Execute with timeout let prediction_future = model.predict(&features); let timeout_duration = std::time::Duration::from_micros(self.profile.max_latency_us); match tokio::time::timeout(timeout_duration, prediction_future).await { Ok(result) => results.push(result), Err(_) => results.push(Err(MLError::ModelError(format!( "Model {} prediction timed out after {}μs", model.name(), self.profile.max_latency_us )))), } } results } /// Get execution statistics pub fn get_stats(&self) -> ExecutorStats { ExecutorStats { optimization_level: self.profile.optimization_level, target_latency_us: self.profile.max_latency_us, cpu_threads: self.cpu_pool.current_num_threads(), cpu_affinity: self.cpu_affinity.clone(), } } } /// Executor performance statistics #[derive(Debug, Clone)] pub struct ExecutorStats { pub optimization_level: OptimizationLevel, pub target_latency_us: u64, pub cpu_threads: usize, pub cpu_affinity: Option>, } /// Latency optimizer for ML inference pipelines pub struct LatencyOptimizer { /// Target latency in microseconds target_latency_us: u64, /// Performance history performance_history: Arc>>, /// Optimization parameters optimization_params: OptimizationParams, } #[derive(Debug, Clone)] struct PerformancePoint { timestamp: std::time::Instant, latency_us: u64, model_count: usize, batch_size: u32, success: bool, } #[derive(Debug, Clone)] struct OptimizationParams { max_batch_size: u32, adaptive_batching: bool, prefetch_enabled: bool, cache_predictions: bool, } impl Default for OptimizationParams { fn default() -> Self { Self { max_batch_size: 8, adaptive_batching: true, prefetch_enabled: true, cache_predictions: false, // Disabled for real-time trading } } } impl LatencyOptimizer { /// Create new latency optimizer pub fn new(target_latency_us: u64) -> Self { Self { target_latency_us, performance_history: Arc::new(RwLock::new(Vec::new())), optimization_params: OptimizationParams::default(), } } /// Record performance measurement pub async fn record_performance( &self, latency_us: u64, model_count: usize, batch_size: u32, success: bool, ) { let point = PerformancePoint { timestamp: std::time::Instant::now(), latency_us, model_count, batch_size, success, }; { let mut history = self.performance_history.write().await; history.push(point); // Keep only recent history (last 1000 measurements) if history.len() > 1000 { let excess = history.len() - 1000; history.drain(0..excess); } } } /// Get optimization recommendations pub async fn get_recommendations(&self) -> OptimizationRecommendations { let history = self.performance_history.read().await; if history.is_empty() { return OptimizationRecommendations::default(); } let recent_points: Vec<&PerformancePoint> = history.iter().rev().take(100).collect(); let avg_latency = recent_points.iter().map(|p| p.latency_us).sum::() / recent_points.len() as u64; let success_rate = recent_points.iter().filter(|p| p.success).count() as f64 / recent_points.len() as f64; OptimizationRecommendations { current_avg_latency_us: avg_latency, target_latency_us: self.target_latency_us, success_rate, meets_target: avg_latency <= self.target_latency_us, recommended_batch_size: self.calculate_optimal_batch_size(&recent_points), recommended_model_limit: self.calculate_optimal_model_limit(&recent_points), } } fn calculate_optimal_batch_size(&self, points: &[&PerformancePoint]) -> u32 { // Simple heuristic: find batch size with best latency/success ratio let mut batch_performance: HashMap = HashMap::new(); for point in points { let entry = batch_performance .entry(point.batch_size) .or_insert((0, 0.0)); entry.0 += point.latency_us; entry.1 += if point.success { 1.0 } else { 0.0 }; } batch_performance .into_iter() .filter(|(_, (_, success_count))| *success_count > 0.0) .min_by_key(|(_, (latency, success_count))| { // Optimize for latency with success rate weighting ((*latency as f64) / success_count) as u64 }) .map(|(batch_size, _)| batch_size) .unwrap_or(1) } fn calculate_optimal_model_limit(&self, points: &[&PerformancePoint]) -> usize { // Find the sweet spot where adding more models doesn't improve latency let mut model_performance: HashMap = HashMap::new(); for point in points { if point.success { let entry = model_performance.entry(point.model_count).or_insert(0); *entry += point.latency_us; } } model_performance .into_iter() .filter(|(_, avg_latency)| *avg_latency <= self.target_latency_us) .max_by_key(|(model_count, _)| *model_count) .map(|(model_count, _)| model_count) .unwrap_or(1) } } /// Optimization recommendations from latency analysis #[derive(Debug, Clone)] pub struct OptimizationRecommendations { pub current_avg_latency_us: u64, pub target_latency_us: u64, pub success_rate: f64, pub meets_target: bool, pub recommended_batch_size: u32, pub recommended_model_limit: usize, } impl Default for OptimizationRecommendations { fn default() -> Self { Self { current_avg_latency_us: 0, target_latency_us: 50, success_rate: 0.0, meets_target: false, recommended_batch_size: 1, recommended_model_limit: 1, } } } /// Create optimized parallel executor for HFT scenarios pub fn create_hft_parallel_executor() -> Result { let profile = create_ultra_low_latency_profile(); ParallelExecutor::new(profile) } /// Create latency optimizer with HFT targets pub fn create_hft_latency_optimizer() -> LatencyOptimizer { LatencyOptimizer::new(50) // 50 microsecond target } // ========== CANONICAL ML TYPES ========== // These are the unified types that all ML modules must use to prevent type conflicts /// Canonical inference result used throughout ML module #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InferenceResult { /// Model identifier pub model_id: String, /// Prediction value (primary prediction) pub prediction_value: f64, /// Confidence score (0.0 to 1.0) pub confidence: f64, /// Latency in microseconds pub latency_us: u64, /// Timestamp in microseconds since UNIX epoch pub timestamp: u64, /// Model metadata pub metadata: ModelMetadata, } impl InferenceResult { /// Create new inference result pub fn new( model_id: String, prediction_value: f64, confidence: f64, latency_us: u64, timestamp: u64, metadata: ModelMetadata, ) -> Self { Self { model_id, prediction_value, confidence, latency_us, timestamp, metadata, } } /// Extract prediction as float value pub fn prediction_as_float(&self) -> f64 { self.prediction_value } /// Get the model identifier pub fn model_id(&self) -> &str { &self.model_id } } /// Canonical model metadata used throughout ML module #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ModelMetadata { /// Type of the model pub model_type: ModelType, /// Model version pub version: String, /// Number of features used for inference pub features_used: usize, /// Memory usage in megabytes pub memory_usage_mb: f64, /// Additional metadata key-value pairs pub additional_metadata: HashMap, } impl ModelMetadata { /// Create new model metadata pub fn new( model_type: ModelType, version: String, features_used: usize, memory_usage_mb: f64, ) -> Self { Self { model_type, version, features_used, memory_usage_mb, additional_metadata: HashMap::new(), } } /// Add additional metadata pub fn add_metadata(&mut self, key: &str, value: String) { self.additional_metadata.insert(key.to_string(), value); } /// Mark the model as trained (for training pipeline compatibility) pub fn mark_trained(&mut self) { self.add_metadata("training_status", "trained".to_string()); self.add_metadata( "training_timestamp", std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap_or_default() .as_secs() .to_string(), ); } } /// Canonical model type enum used throughout ML module #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] pub enum ModelType { /// Compact Deep Q-Network CompactDQN, /// Distilled micro network for ultra-low latency DistilledMicroNet, /// Standard Deep Q-Network DQN, /// Rainbow DQN with all enhancements RainbowDQN, /// MAMBA model (SSM) MAMBA, /// Temporal Fusion Transformer TFT, /// Temporal Graph Neural Network TGGN, /// Liquid Neural Network LNN, /// Temporal Limit Order Book transformer TLOB, /// Proximal Policy Optimization PPO, /// Transformer for sequence modeling Transformer, /// Mamba state space model (alias for MAMBA) Mamba, /// Liquid time constant networks (alias for LNN) LiquidNet, /// Temporal Graph Neural Network (alias for TGGN) TGNN, /// Ensemble methods Ensemble, } impl ModelType { /// Get file extension for model type pub fn file_extension(&self) -> &'static str { match self { ModelType::DQN => "dqn", ModelType::MAMBA | ModelType::Mamba => "mamba", ModelType::TFT => "tft", ModelType::TGGN | ModelType::TGNN => "tggn", ModelType::LNN | ModelType::LiquidNet => "lnn", ModelType::CompactDQN => "compact_dqn", ModelType::DistilledMicroNet => "distilled", ModelType::RainbowDQN => "rainbow_dqn", ModelType::TLOB => "tlob", ModelType::PPO => "ppo", ModelType::Transformer => "transformer", ModelType::Ensemble => "ensemble", } } /// Get model type from string pub fn from_str(s: &str) -> Option { match s.to_lowercase().as_str() { "dqn" => Some(ModelType::DQN), "mamba" => Some(ModelType::MAMBA), "tft" => Some(ModelType::TFT), "tggn" | "tgnn" => Some(ModelType::TGGN), "lnn" | "liquidnet" => Some(ModelType::LNN), "compact_dqn" | "compactdqn" => Some(ModelType::CompactDQN), "distilled" | "distilledmicronet" => Some(ModelType::DistilledMicroNet), "rainbow_dqn" | "rainbowdqn" => Some(ModelType::RainbowDQN), "tlob" => Some(ModelType::TLOB), "ppo" => Some(ModelType::PPO), "transformer" => Some(ModelType::Transformer), "ensemble" => Some(ModelType::Ensemble), _ => None, } } } // TEMPORARILY COMMENTED OUT - These modules need to be checked for availability // Re-export training pipeline system (from existing training_pipeline module) // pub use training_pipeline::{ // ProductionMLTrainingSystem, ProductionTrainingConfig, ProductionTrainingMetrics, // FinancialFeatures, MicrostructureFeatures, RiskFeatures, TrainingResult, // }; // Re-export feature system (from existing features module) pub use features::{ FeatureExtractionConfig, FeatureQualityMetrics, PriceFeatures, TechnicalFeatures, UnifiedFeatureExtractor, UnifiedFinancialFeatures, VolumeFeatures, }; // Re-export examples and demonstrations pub use examples::{ run_example, // list_examples, // TEMPORARILY DISABLED: Import issue DataSource, ExampleConfig, ExampleMetrics, ExampleResult, ExampleType, }; pub use models_demo::{ create_benchmark_config, get_available_models, run_model_demonstrations, DemoSummary, ModelDemoConfig, ModelDemoResults, ModelPerformanceMetrics, }; // Re-export inference system (from existing inference module) pub use inference::{ ModelConfig, RealInferenceConfig, RealMLInferenceEngine, RealNeuralNetwork, RealPredictionResult, }; #[cfg(test)] mod tests { use super::*; #[test] fn test_ml_error_creation() -> Result<(), Box> { let error = MLError::ConfigError { reason: "test".to_string(), }; assert!(error.to_string().contains("Configuration error")); Ok(()) } }