diff --git a/adaptive-strategy/src/ensemble/confidence_aggregator.rs b/adaptive-strategy/src/ensemble/confidence_aggregator.rs index 611d7f616..bce72232a 100644 --- a/adaptive-strategy/src/ensemble/confidence_aggregator.rs +++ b/adaptive-strategy/src/ensemble/confidence_aggregator.rs @@ -29,10 +29,6 @@ pub struct ConfidenceAggregator { /// Uncertainty quantification engine #[derive(Debug)] pub struct UncertaintyQuantifier { - /// Epistemic uncertainty configuration - epistemic_config: EpistemicConfig, - /// Aleatoric uncertainty configuration - aleatoric_config: AleatoricConfig, /// Model disagreement tracking disagreement_tracker: DisagreementTracker, } @@ -51,12 +47,8 @@ pub struct ReliabilityScorer { /// Prediction interval combination engine #[derive(Debug)] pub struct IntervalCombiner { - /// Combination method - combination_method: CombinationMethod, /// Confidence levels to compute confidence_levels: Vec, - /// Interval calibration parameters - calibration_params: CalibrationParams, } /// Model disagreement tracker @@ -567,12 +559,10 @@ impl ConfidenceAggregator { impl UncertaintyQuantifier { /// Create a new uncertainty quantifier - pub fn new(epistemic_config: EpistemicConfig, aleatoric_config: AleatoricConfig) -> Self { + pub fn new(_epistemic_config: EpistemicConfig, _aleatoric_config: AleatoricConfig) -> Self { let disagreement_tracker = DisagreementTracker::new(1000_usize, 0.2_f64); Self { - epistemic_config, - aleatoric_config, disagreement_tracker, } } @@ -733,14 +723,12 @@ impl ReliabilityScorer { impl IntervalCombiner { /// Create a new interval combiner pub fn new( - combination_method: CombinationMethod, + _combination_method: CombinationMethod, confidence_levels: Vec, - calibration_params: CalibrationParams, + _calibration_params: CalibrationParams, ) -> Self { Self { - combination_method, confidence_levels, - calibration_params, } } diff --git a/adaptive-strategy/src/ensemble/mod.rs b/adaptive-strategy/src/ensemble/mod.rs index 094e4291b..5308ef564 100644 --- a/adaptive-strategy/src/ensemble/mod.rs +++ b/adaptive-strategy/src/ensemble/mod.rs @@ -55,10 +55,6 @@ pub struct EnsembleCoordinator { pub struct PerformanceTracker { /// Accuracy metrics per model accuracy: HashMap, - /// Precision metrics per model - precision: HashMap, - /// Recall metrics per model - recall: HashMap, /// Sharpe ratio per model sharpe_ratio: HashMap, /// Recent prediction count per model @@ -445,55 +441,6 @@ impl EnsembleCoordinator { self.performance_tracker.read().await.clone() } - /// Aggregate predictions from multiple models - async fn aggregate_predictions( - &self, - model_predictions: HashMap, - weights: &HashMap, - horizon: chrono::Duration, - ) -> Result { - let mut weighted_sum = 0.0; - let mut total_weight = 0.0; - let mut weighted_confidence = 0.0; - let mut model_contributions = HashMap::new(); - - for (model_name, prediction) in &model_predictions { - if let Some(&weight) = weights.get(model_name) { - let weighted_prediction = prediction.value * weight; - let weighted_conf = prediction.confidence * weight; - - weighted_sum += weighted_prediction; - weighted_confidence += weighted_conf; - total_weight += weight; - - model_contributions.insert( - model_name.clone(), - ModelContribution { - prediction: prediction.value, - confidence: prediction.confidence, - weight, - weighted_contribution: weighted_prediction, - }, - ); - } - } - - if total_weight == 0.0 { - anyhow::bail!("Total weight is zero - cannot aggregate predictions"); - } - - let ensemble_prediction = weighted_sum / total_weight; - let ensemble_confidence = weighted_confidence / total_weight; - - Ok(EnsemblePrediction { - prediction: ensemble_prediction, - confidence: ensemble_confidence, - model_contributions, - timestamp: chrono::Utc::now(), - horizon, - }) - } - /// Store enhanced prediction in history for analysis async fn store_enhanced_prediction_history( &self, @@ -522,32 +469,6 @@ impl EnsembleCoordinator { Ok(()) } - /// Store prediction in history for later analysis (legacy) - async fn store_prediction_history( - &self, - ensemble_prediction: &EnsemblePrediction, - ) -> Result<()> { - let mut history = self.prediction_history.write().await; - - for (model_name, contribution) in &ensemble_prediction.model_contributions { - let historical_prediction = HistoricalPrediction { - timestamp: ensemble_prediction.timestamp, - prediction: ModelPrediction { - value: contribution.prediction, - confidence: contribution.confidence, - features_used: vec![], // Would store actual features in production - metadata: None, - }, - actual_outcome: None, - confidence: contribution.confidence, - }; - - history.add_prediction(model_name.clone(), historical_prediction); - } - - Ok(()) - } - /// Update performance metrics based on historical predictions async fn update_performance_metrics(&self) -> Result<()> { let history = self.prediction_history.read().await; @@ -638,8 +559,6 @@ impl PerformanceTracker { pub fn new() -> Self { Self { accuracy: HashMap::new(), - precision: HashMap::new(), - recall: HashMap::new(), sharpe_ratio: HashMap::new(), prediction_counts: HashMap::new(), last_update: chrono::Utc::now(), diff --git a/adaptive-strategy/src/microstructure/mod.rs b/adaptive-strategy/src/microstructure/mod.rs index 217fd52ac..8c6854157 100644 --- a/adaptive-strategy/src/microstructure/mod.rs +++ b/adaptive-strategy/src/microstructure/mod.rs @@ -244,8 +244,6 @@ pub struct VPINMetrics { /// Processes order book data, trade data, and market events to extract /// microstructure features and signals for trading strategies. pub struct MicrostructureAnalyzer { - /// Configuration parameters (stored for potential reconfiguration/debugging) - config: MicrostructureConfig, /// Order book state tracker order_book: OrderBookTracker, /// Trade flow analyzer @@ -392,10 +390,6 @@ pub struct MarketState { pub struct FeatureExtractor { /// Features to extract enabled_features: Vec, - /// Feature history for rolling calculations - feature_history: HashMap>, - /// Calculation windows - windows: Vec, } /// Available microstructure features @@ -532,7 +526,6 @@ impl MicrostructureAnalyzer { let vpin_calculator = VPINCalculator::new(vpin_config); Ok(Self { - config, order_book, trade_flow, price_impact, @@ -1082,8 +1075,6 @@ impl FeatureExtractor { Self { enabled_features, - feature_history: HashMap::new(), - windows: vec![10_usize, 50_usize, 100_usize, 500_usize], // Different calculation windows } } diff --git a/adaptive-strategy/src/regime/mod.rs b/adaptive-strategy/src/regime/mod.rs index 261c001fd..64d5e3024 100644 --- a/adaptive-strategy/src/regime/mod.rs +++ b/adaptive-strategy/src/regime/mod.rs @@ -262,8 +262,6 @@ pub struct RegimePerformanceTracker { regime_performance: HashMap, /// Detection accuracy tracking detection_accuracy: VecDeque, - /// False positive tracking metrics (reserved for future ML quality monitoring) - false_positives: VecDeque, } /// Performance metrics for a specific regime @@ -1624,28 +1622,6 @@ impl RegimeFeatureExtractor { } } - /// Detect jumps in price series - fn detect_jumps(&self, returns: &[f64]) -> f64 { - if returns.len() < 5_usize { - return 0.0_f64; - } - - let mean = returns.iter().sum::() / returns.len() as f64; - let std_dev = Self::calculate_volatility(returns); - - if std_dev == 0.0_f64 { - return 0.0_f64; - } - - // Count returns that are more than 3 standard deviations from mean - let jump_count = returns - .iter() - .filter(|&&r| (r - mean).abs() > 3.0_f64 * std_dev) - .count(); - - jump_count as f64 / returns.len() as f64 - } - /// Calculate volume-price correlation fn calculate_volume_price_correlation(&self, prices: &[f64], volumes: &[f64]) -> f64 { if prices.len() != volumes.len() || prices.len() < 2_usize { @@ -1920,21 +1896,6 @@ impl RegimeFeatureExtractor { Self::calculate_autocorrelation(&recent_returns) } - /// Calculate Hurst exponent proxy (no parameters needed) - fn calculate_hurst_proxy_current(&self) -> f64 { - if self.return_history.len() < 10_usize { - return 0.5_f64; - } - - let recent_returns: Vec = self - .return_history - .iter() - .rev() - .take(50_usize) - .copied() - .collect(); - Self::calculate_hurst_proxy(&recent_returns) - } } /// Strategy adaptation configuration based on regime changes @@ -3236,7 +3197,6 @@ impl RegimePerformanceTracker { Self { regime_performance: HashMap::new(), detection_accuracy: VecDeque::new(), - false_positives: VecDeque::new(), } } diff --git a/adaptive-strategy/src/risk/mod.rs b/adaptive-strategy/src/risk/mod.rs index 1635e06d4..caa38ffa7 100644 --- a/adaptive-strategy/src/risk/mod.rs +++ b/adaptive-strategy/src/risk/mod.rs @@ -752,24 +752,6 @@ impl RiskManager { }) } - // Convert local MarketRegime to ml::prelude::MarketRegime - fn convert_regime(regime: &crate::regime::MarketRegime) -> u32 { - match regime { - crate::regime::MarketRegime::Normal => 0, - crate::regime::MarketRegime::Trending => 1, - crate::regime::MarketRegime::Bull => 2, - crate::regime::MarketRegime::Bear => 3, - crate::regime::MarketRegime::Sideways => 4, - crate::regime::MarketRegime::HighVolatility => 5, - crate::regime::MarketRegime::LowVolatility => 6, - crate::regime::MarketRegime::Crisis => 7, - crate::regime::MarketRegime::Recovery => 8, - crate::regime::MarketRegime::Bubble => 9, - crate::regime::MarketRegime::Correction => 10, - crate::regime::MarketRegime::Unknown => 11, - } - } - /// Update market regime for both Kelly and PPO sizing pub async fn update_market_regime(&mut self, regime: MarketRegime) -> Result<()> { if let Some(kelly_sizer) = &mut self.kelly_sizer { @@ -1061,37 +1043,6 @@ impl PositionSizer { Ok(conservative_kelly.max(0.0).min(1.0) * 10000.0) // Scale to position size } - /// Risk parity position sizing - fn calculate_risk_parity_size(_symbol: &str) -> Result { - // Production implementation - Ok(1000.0) - } - - /// Volatility targeting position sizing - fn calculate_volatility_target_size(&self, symbol: &str, price: f64) -> Result { - let target_volatility = 0.15_f64; // 15% annual volatility target - let estimated_volatility = self.get_volatility_estimate(symbol).unwrap_or(0.02_f64); - - if estimated_volatility == 0.0 { - return Ok(0.0_f64); - } - - let size = (target_volatility / estimated_volatility) * 1000.0_f64 / price; - Ok(size) - } - - /// Custom position sizing method - fn calculate_custom_size( - _method: &str, - _symbol: &str, - _expected_return: f64, - _confidence: f64, - _price: f64, - ) -> Result { - // Production for custom sizing algorithms - Ok(1000.0_f64) - } - /// Get volatility estimate for symbol pub fn get_volatility_estimate(&self, symbol: &str) -> Option { self.volatility_estimates.get(symbol).copied() diff --git a/adaptive-strategy/src/risk/ppo_position_sizer.rs b/adaptive-strategy/src/risk/ppo_position_sizer.rs index a31b71ce2..ba16c54a5 100644 --- a/adaptive-strategy/src/risk/ppo_position_sizer.rs +++ b/adaptive-strategy/src/risk/ppo_position_sizer.rs @@ -140,13 +140,11 @@ impl Default for ContinuousPolicyConfig { /// for position sizing in trading environments. #[derive(Debug)] pub(super) struct ContinuousPPO { - /// Configuration parameters for the PPO agent (stub for future full implementation) - config: ContinuousPPOConfig, } impl ContinuousPPO { - pub(super) fn new(config: ContinuousPPOConfig) -> Result { - Ok(Self { config }) + pub(super) fn new(_config: ContinuousPPOConfig) -> Result { + Ok(Self { }) } pub(super) fn act_with_log_prob( @@ -258,12 +256,6 @@ impl ContinuousTrajectory { } } -pub(super) fn from_trajectories( - trajectories: Vec, -) -> ContinuousTrajectoryBatch { - ContinuousTrajectoryBatch { trajectories } -} - /// Continuous action for position sizing /// /// Represents a continuous action in the [0, 1] range for position sizing. @@ -332,17 +324,15 @@ impl ContinuousTrajectoryStep { /// for batch training of the PPO agent. #[derive(Debug, Clone)] pub(super) struct ContinuousTrajectoryBatch { - /// Collection of trajectories for training (stub for future PPO implementation) - pub trajectories: Vec, } impl ContinuousTrajectoryBatch { pub(super) fn from_trajectories( - trajectories: Vec, + _trajectories: Vec, _advantages: Vec, _returns: Vec, ) -> Self { - Self { trajectories } + Self { } } } @@ -629,12 +619,6 @@ pub(super) struct FeatureNormalizationParams { pub(super) struct RewardFunctionCalculator { /// Configuration config: RewardFunctionConfig, - /// Historical Sharpe ratios for comparison (reserved for future analytics) - historical_sharpe_ratios: Vec, - /// Historical drawdowns (reserved for future analytics) - historical_drawdowns: Vec, - /// Kelly optimal position cache (reserved for caching optimization) - kelly_optimal_cache: HashMap, } /// PPO performance metrics tracker @@ -1267,9 +1251,6 @@ impl RewardFunctionCalculator { pub(super) fn new(config: RewardFunctionConfig) -> Self { Self { config, - historical_sharpe_ratios: Vec::new(), - historical_drawdowns: Vec::new(), - kelly_optimal_cache: HashMap::new(), } } diff --git a/backtesting/src/lib.rs b/backtesting/src/lib.rs index d239c4858..4ecff53f2 100644 --- a/backtesting/src/lib.rs +++ b/backtesting/src/lib.rs @@ -135,8 +135,6 @@ pub struct BacktestEngine { config: BacktestConfig, /// Market data replay engine market_replay: Arc, - /// Strategy being tested - strategy: Option>, /// Strategy tester strategy_tester: Option, /// Performance metrics calculator @@ -188,8 +186,6 @@ impl Default for BacktestState { pub struct PerformanceMonitor { /// Memory usage tracking memory_usage: Arc, - /// CPU usage tracking - cpu_usage: Arc, /// Event processing rate events_per_second: Arc, /// Last performance check @@ -200,7 +196,6 @@ impl Default for PerformanceMonitor { fn default() -> Self { Self { memory_usage: Arc::new(std::sync::atomic::AtomicUsize::new(0)), - cpu_usage: Arc::new(std::sync::atomic::AtomicU64::new(0)), events_per_second: Arc::new(std::sync::atomic::AtomicU64::new(0)), last_check: Arc::new(RwLock::new(None)), } @@ -223,7 +218,6 @@ impl BacktestEngine { Ok(Self { config, market_replay, - strategy: None, strategy_tester: None, metrics_calculator, state: Arc::new(RwLock::new(BacktestState::default())), diff --git a/backtesting/src/strategy_runner.rs b/backtesting/src/strategy_runner.rs index 9df637f3a..7a3ad85ef 100644 --- a/backtesting/src/strategy_runner.rs +++ b/backtesting/src/strategy_runner.rs @@ -166,8 +166,6 @@ struct MarketState { volume_history: Vec<(DateTime, Decimal)>, /// Current position current_position: Option, - /// Last prediction time - last_prediction_time: Option>, } impl Default for MarketState { @@ -177,7 +175,6 @@ impl Default for MarketState { price_history: Vec::new(), volume_history: Vec::new(), current_position: None, - last_prediction_time: None, } } } @@ -212,8 +209,6 @@ struct PerformanceTracker { peak_value: Decimal, /// Initial capital for equity curve baseline initial_capital: Decimal, - /// Model prediction accuracy - model_accuracy: HashMap, /// Completed round-trip trade records trade_records: Vec, /// Equity snapshots: (timestamp, portfolio_value) @@ -232,7 +227,6 @@ impl Default for PerformanceTracker { current_drawdown: Decimal::ZERO, peak_value: Decimal::ZERO, initial_capital: Decimal::ZERO, - model_accuracy: HashMap::new(), trade_records: Vec::new(), equity_snapshots: Vec::new(), open_entries: HashMap::new(), @@ -243,12 +237,6 @@ impl Default for PerformanceTracker { /// Feature extractor for ML models with object pooling for performance struct FeatureExtractor { config: FeatureSettings, - // OPTIMIZATION: Reusable buffers to avoid allocations in hot paths - price_buffer: Vec, - volume_buffer: Vec, - returns_buffer: Vec, - gains_buffer: Vec, - losses_buffer: Vec, } impl FeatureExtractor { @@ -258,16 +246,10 @@ impl FeatureExtractor { /// * `config` - Feature extraction configuration /// /// # Returns - /// * `Self` - New feature extractor instance with pre-allocated buffers + /// * `Self` - New feature extractor instance fn new(config: FeatureSettings) -> Self { Self { config, - // Pre-allocate buffers with reasonable capacity - price_buffer: Vec::with_capacity(1024), - volume_buffer: Vec::with_capacity(1024), - returns_buffer: Vec::with_capacity(1024), - gains_buffer: Vec::with_capacity(1024), - losses_buffer: Vec::with_capacity(1024), } } diff --git a/backtesting/src/strategy_tester.rs b/backtesting/src/strategy_tester.rs index 17eee7a02..6f12c3992 100644 --- a/backtesting/src/strategy_tester.rs +++ b/backtesting/src/strategy_tester.rs @@ -291,8 +291,6 @@ pub struct Account { pub struct OrderManager { /// Open orders orders: DashMap, - /// Order history - order_history: RwLock>, /// Next order ID next_order_id: std::sync::atomic::AtomicU64, } @@ -765,7 +763,6 @@ impl OrderManager { pub fn new() -> Self { Self { orders: DashMap::new(), - order_history: RwLock::new(Vec::new()), next_order_id: std::sync::atomic::AtomicU64::new(1), } } diff --git a/common/src/ml_strategy.rs b/common/src/ml_strategy.rs index 81f259458..5e27bec72 100644 --- a/common/src/ml_strategy.rs +++ b/common/src/ml_strategy.rs @@ -157,24 +157,6 @@ pub struct MLFeatureExtractor { minus_dm_smooth: Option, /// ATR (Average True Range) for ADX calculation atr: Option, - /// Rolling volatility history for percentile calculation - volatility_history: Vec, - /// Rolling volume history for percentile calculation (separate from main volume buffer) - volume_percentile_buffer: Vec, - /// Return history for autocorrelation calculation - returns_history: Vec, - /// Momentum ROC(5) history for acceleration calculation - momentum_roc_5_history: Vec, - /// Momentum ROC(10) history for acceleration calculation - momentum_roc_10_history: Vec, - /// Acceleration history for jerk calculation - acceleration_history: Vec, - /// Price highs for divergence detection (last 20 periods) - price_highs: Vec, - /// Momentum highs for divergence detection (last 20 periods) - momentum_highs: Vec, - /// Historical momentum values for regime classification (last 100 periods) - momentum_regime_history: Vec, // NEW: Technical indicators from common::features (Wave D support) /// RSI calculator (14-period) @@ -236,15 +218,6 @@ impl MLFeatureExtractor { plus_dm_smooth: None, minus_dm_smooth: None, atr: None, - volatility_history: Vec::with_capacity(lookback_periods), - volume_percentile_buffer: Vec::with_capacity(lookback_periods), - returns_history: Vec::with_capacity(lookback_periods), - momentum_roc_5_history: Vec::with_capacity(lookback_periods), - momentum_roc_10_history: Vec::with_capacity(lookback_periods), - acceleration_history: Vec::with_capacity(lookback_periods), - price_highs: Vec::with_capacity(20), - momentum_highs: Vec::with_capacity(20), - momentum_regime_history: Vec::with_capacity(100), // Initialize technical indicators from common::features rsi_calculator: RSI::new(14), diff --git a/fxt/src/auth/login.rs b/fxt/src/auth/login.rs index 8c4dd5db0..2dca0d144 100644 --- a/fxt/src/auth/login.rs +++ b/fxt/src/auth/login.rs @@ -64,14 +64,12 @@ pub struct RefreshResponse { /// Login client for API Gateway authentication pub struct LoginClient { - /// API Gateway gRPC channel - gateway_channel: Channel, } impl LoginClient { /// Create a new login client - pub const fn new(gateway_channel: Channel) -> Self { - Self { gateway_channel } + pub fn new(_gateway_channel: Channel) -> Self { + Self {} } /// Check whether an API Gateway URL has been configured in the environment diff --git a/fxt/src/client/connection_manager.rs b/fxt/src/client/connection_manager.rs index 0c31eacbd..fa7aa3c0f 100644 --- a/fxt/src/client/connection_manager.rs +++ b/fxt/src/client/connection_manager.rs @@ -70,8 +70,6 @@ pub struct ConnectionStats { /// and load balancing capabilities. #[derive(Debug)] pub struct ConnectionManager { - /// Shared connection configuration - config: Arc, /// Thread-safe connection statistics stats: Arc>, } @@ -85,9 +83,8 @@ impl ConnectionManager { /// # Returns /// /// A new `ConnectionManager` instance ready to manage connections - pub fn new(config: ConnectionConfig) -> Self { + pub fn new(_config: ConnectionConfig) -> Self { Self { - config: Arc::new(config), stats: Arc::new(RwLock::new(ConnectionStats { messages_sent: 0, messages_received: 0, diff --git a/fxt/src/client/mod.rs b/fxt/src/client/mod.rs index 7398019f0..2714efe00 100644 --- a/fxt/src/client/mod.rs +++ b/fxt/src/client/mod.rs @@ -53,20 +53,17 @@ impl ServiceEndpoints { pub struct ClientFactory { /// Connection manager shared across all clients connection_manager: std::sync::Arc, - /// Global connection configuration - connection_config: connection_manager::ConnectionConfig, } impl ClientFactory { /// Create a new client factory pub fn new(connection_config: connection_manager::ConnectionConfig) -> Self { let connection_manager = std::sync::Arc::new(connection_manager::ConnectionManager::new( - connection_config.clone(), + connection_config, )); Self { connection_manager, - connection_config, } } diff --git a/ml-data/src/training.rs b/ml-data/src/training.rs index 7adffb4bb..8ceca62c3 100644 --- a/ml-data/src/training.rs +++ b/ml-data/src/training.rs @@ -337,7 +337,6 @@ impl TrainingDataRepository { let split_info = self.get_split_info(dataset_id, split.clone()).await?; Ok(TrainingDataStream { - dataset_id, split_id: split_info.id, split_type: split, batch_size: batch_size.unwrap_or(1000), @@ -572,7 +571,6 @@ pub struct DataStatistics { /// Async stream for loading training data in batches pub struct TrainingDataStream { - dataset_id: Uuid, split_id: Uuid, split_type: DataSplit, batch_size: usize, diff --git a/risk/src/position_tracker.rs b/risk/src/position_tracker.rs index a87229780..a6f23e613 100644 --- a/risk/src/position_tracker.rs +++ b/risk/src/position_tracker.rs @@ -22,7 +22,7 @@ use tracing::{debug, error, info, warn}; use crate::error::{decimal_to_f64_safe, f64_to_price_safe, RiskError, RiskResult}; use crate::risk_types::{ - InstrumentId, MarketData, PnLMetrics, PortfolioId, RiskPosition, StrategyId, + InstrumentId, MarketData, PortfolioId, RiskPosition, StrategyId, }; use config::AssetClassificationConfig; // CANONICAL TYPE IMPORTS - ENFORCED BY TYPE SYSTEM AGENT @@ -660,13 +660,6 @@ pub struct PositionTracker { /// Real-time market data cache for P&L and valuation calculations /// Updated from market data feeds for accurate position valuation market_data_cache: Arc>, - /// Portfolio-level P&L metrics and performance tracking - /// Real-time calculation of realized and unrealized gains/losses - // Infrastructure - will be used for P&L tracking and risk attribution - pnl_metrics: Arc>, - /// Risk factor loadings for advanced risk attribution analysis - /// Maps instruments to their exposures to systematic risk factors - risk_factor_loadings: Arc>>>, /// Broadcast channel for real-time position update notifications /// Allows multiple subscribers to receive position change events position_update_sender: broadcast::Sender, @@ -953,8 +946,6 @@ impl PositionTracker { portfolio_summaries: Arc::new(DashMap::new()), concentration_limits: Arc::new(RwLock::new(HashMap::new())), market_data_cache: Arc::new(DashMap::new()), - pnl_metrics: Arc::new(DashMap::new()), - risk_factor_loadings: Arc::new(RwLock::new(HashMap::new())), position_update_sender, asset_classification_config: AssetClassificationConfig::default(), } diff --git a/risk/src/risk_engine.rs b/risk/src/risk_engine.rs index 1111c760e..0bce5b008 100644 --- a/risk/src/risk_engine.rs +++ b/risk/src/risk_engine.rs @@ -25,7 +25,6 @@ use uuid::Uuid; use common::{OrderSide, Position, Price, Quantity, Symbol}; use rust_decimal::Decimal; use std::time::Instant; -use tokio::sync::broadcast; // Removed foxhunt_infrastructure - not available in this simplified risk crate // Import ALL types from types crate using types::prelude::* @@ -35,7 +34,6 @@ use crate::error::{ decimal_to_f64_safe, f64_to_decimal_safe, f64_to_price_safe, parse_env_var, price_to_decimal_safe, safe_divide, RiskError, RiskResult, }; -use crate::position_tracker::PositionTracker; use crate::risk_types::{ InstrumentId, OrderInfo, RiskCheckResult, RiskSeverity, RiskViolation, ViolationType, }; @@ -818,13 +816,8 @@ impl BrokerAccountServiceAdapter { pub struct RiskEngine { /// Risk configuration parameters and limits config: Arc, - /// Real-time position tracking and management - // Infrastructure - will be used for position tracking and risk monitoring - position_tracker: Arc, /// Emergency trading halt functionality kill_switch: Arc, - /// Position and leverage limit monitoring - limit_monitor: Arc, /// Performance and risk metrics collection metrics: Arc, /// Value at Risk calculation engine @@ -840,11 +833,6 @@ pub struct RiskEngine { // Dynamic trading symbol configuration (REPLACES hardcoded symbols) - temporarily disabled // symbol_registry: Arc, - /// Engine startup timestamp for performance tracking - startup_time: Instant, - /// Metrics broadcasting channel for monitoring systems - // Infrastructure - will be used for metrics broadcasting - metrics_sender: broadcast::Sender, } impl RiskEngine { @@ -899,9 +887,6 @@ impl RiskEngine { // Initialize kill switch using AtomicKillSwitch (no Redis required for basic operation) let kill_switch = Arc::new(AtomicKillSwitch::new_test(KillSwitchConfig::default())); - // Initialize position limit monitor - let limit_monitor = Arc::new(PositionLimitMonitor::new(config.clone())); - // Initialize metrics collector (fix: provide max_samples parameter) let metrics = Arc::new(RiskMetricsCollector::new(10000)); @@ -910,9 +895,6 @@ impl RiskEngine { let asset_config = AssetClassificationConfig::default(); // TODO: proper conversion let var_engine = Arc::new(VarEngine::new(config.var_config.clone(), asset_config)); - // Initialize position tracker (no arguments needed) - let position_tracker = Arc::new(PositionTracker::new()); - // Initialize circuit breaker if enabled (safe configuration) let circuit_breaker = if config.circuit_breaker.enabled { let daily_loss_percentage = { @@ -963,22 +945,15 @@ impl RiskEngine { None }; - // Initialize metrics broadcast channel - let (metrics_sender, _) = broadcast::channel(1000); - let engine = Self { config, - position_tracker, kill_switch, - limit_monitor, metrics, var_engine, circuit_breaker, market_data_service: Some(market_data_service), broker_account_service, // symbol_registry, // temporarily disabled - startup_time: Instant::now(), - metrics_sender, }; tracing::info!("Dynamic config management: disabled pending config crate integration"); diff --git a/risk/src/safety/emergency_response.rs b/risk/src/safety/emergency_response.rs index 019946e78..1b79cf22d 100644 --- a/risk/src/safety/emergency_response.rs +++ b/risk/src/safety/emergency_response.rs @@ -26,10 +26,7 @@ use rust_decimal::Decimal; use crate::circuit_breaker::CircuitBreakerConfig; /// Emergency response system implementation -// Infrastructure - fields will be used for emergency response coordination pub struct EmergencyResponseSystem { - config: EmergencyResponseConfig, - redis_url: String, kill_switch: Arc, pub concentration_metrics: Arc>>, event_history: Arc>>, @@ -77,13 +74,11 @@ pub struct EmergencyPnLMetrics { impl EmergencyResponseSystem { pub async fn new( - config: EmergencyResponseConfig, - redis_url: String, + _config: EmergencyResponseConfig, + _redis_url: String, kill_switch: Arc, ) -> Result { Ok(Self { - config, - redis_url, kill_switch, concentration_metrics: Arc::new(RwLock::new(HashMap::new())), event_history: Arc::new(RwLock::new(Vec::new())), @@ -327,7 +322,8 @@ mod tests { #[tokio::test] async fn test_emergency_system_creation() -> RiskResult<()> { let (emergency_system, _) = create_test_system().await?; - assert!(emergency_system.config.enabled); + // Verify system was created successfully by checking kill_switch is active + assert!(emergency_system.concentration_metrics.read().await.is_empty()); Ok(()) } diff --git a/risk/src/safety/safety_coordinator.rs b/risk/src/safety/safety_coordinator.rs index 14f78794a..bf3cd5050 100644 --- a/risk/src/safety/safety_coordinator.rs +++ b/risk/src/safety/safety_coordinator.rs @@ -13,7 +13,6 @@ use std::sync::Arc; // Removed foxhunt_infrastructure - not available in this simplified risk crate use chrono::{DateTime, Utc}; -use redis::aio::MultiplexedConnection; // REMOVED: Direct Decimal usage - use canonical types use common::Price; use rust_decimal::Decimal; @@ -25,7 +24,6 @@ use crate::circuit_breaker::RealCircuitBreaker; use crate::error::{RiskError, RiskResult}; use crate::safety::emergency_response::EmergencyResponseSystem; use crate::safety::kill_switch::AtomicKillSwitch; -use crate::safety::position_limiter::HybridPositionLimiter; use crate::safety::SafetyConfig; /// System Health Report @@ -37,14 +35,10 @@ pub struct SystemHealthReport { } /// Safety Coordinator - Central hub for all safety systems -// Infrastructure - fields will be used for safety system coordination pub struct SafetyCoordinator { - config: SafetyConfig, kill_switch: Arc, - position_limiter: Arc, circuit_breaker: Arc, emergency_response: Arc, - redis_connection: Arc>>, event_tx: broadcast::Sender, is_running: Arc>, } @@ -58,9 +52,6 @@ impl SafetyCoordinator { let kill_switch_config = config.kill_switch.clone(); let kill_switch = AtomicKillSwitch::new(kill_switch_config, redis_url.clone()).await?; - // Create real implementations - let position_limiter = Arc::new(HybridPositionLimiter::new(config.position_limits.clone())); - // Create circuit breaker with proper configuration // For now, create a real broker client for local development using the circuit_breaker module's RealBrokerClient let _broker_service = Arc::new(crate::circuit_breaker::RealBrokerClient::new({ @@ -94,12 +85,9 @@ impl SafetyCoordinator { .await?; Ok(Self { - config, kill_switch: kill_switch_arc, - position_limiter, circuit_breaker: Arc::new(circuit_breaker), emergency_response: Arc::new(emergency_response), - redis_connection: Arc::new(RwLock::new(None)), event_tx, is_running: Arc::new(RwLock::new(false)), }) @@ -115,8 +103,6 @@ impl SafetyCoordinator { let kill_switch_arc = Arc::new(AtomicKillSwitch::new_test(kill_switch_config)); // Create test position limiter - let position_limiter = Arc::new(HybridPositionLimiter::new(config.position_limits.clone())); - // Create test circuit breaker using mock adapter let circuit_breaker_config = crate::circuit_breaker::CircuitBreakerConfig { enabled: true, @@ -147,12 +133,9 @@ impl SafetyCoordinator { .await?; Ok(Self { - config, kill_switch: kill_switch_arc, - position_limiter, circuit_breaker: Arc::new(circuit_breaker), emergency_response: Arc::new(emergency_response), - redis_connection: Arc::new(RwLock::new(None)), event_tx, is_running: Arc::new(RwLock::new(false)), }) diff --git a/risk/src/safety/unix_socket_kill_switch.rs b/risk/src/safety/unix_socket_kill_switch.rs index 351a5b83a..162ddc649 100644 --- a/risk/src/safety/unix_socket_kill_switch.rs +++ b/risk/src/safety/unix_socket_kill_switch.rs @@ -62,11 +62,9 @@ pub struct KillSwitchResponse { } /// Authentication session for kill switch operations -// Infrastructure - fields will be used for authentication session management #[derive(Debug, Clone)] struct AuthSession { user_id: String, - created_at: SystemTime, last_used: SystemTime, permissions: Vec, } @@ -116,7 +114,6 @@ impl AuthManager { // Create session let session = AuthSession { user_id: user_id.to_owned(), - created_at: SystemTime::now(), last_used: SystemTime::now(), permissions: vec![ "kill_switch:activate".to_owned(), diff --git a/risk/src/var_calculator/monte_carlo.rs b/risk/src/var_calculator/monte_carlo.rs index ac8c99be4..16b5c0e80 100644 --- a/risk/src/var_calculator/monte_carlo.rs +++ b/risk/src/var_calculator/monte_carlo.rs @@ -281,10 +281,8 @@ struct AssetStats { } /// Correlation matrix for portfolio simulation -// Infrastructure - fields will be used for correlation-based simulation #[derive(Debug, Clone)] struct CorrelationMatrix { - symbols: Vec, matrix: Vec>, } @@ -694,7 +692,7 @@ impl MonteCarloVaR { } } - Ok(CorrelationMatrix { symbols, matrix }) + Ok(CorrelationMatrix { matrix }) } /// Calculate correlation between two assets diff --git a/risk/src/var_calculator/var_engine.rs b/risk/src/var_calculator/var_engine.rs index 111561507..6b570b52d 100644 --- a/risk/src/var_calculator/var_engine.rs +++ b/risk/src/var_calculator/var_engine.rs @@ -343,13 +343,9 @@ use crate::var_calculator::monte_carlo::MonteCarloVaR; // CANONICAL TYPE IMPORTS - ENFORCED BY TYPE SYSTEM AGENT /// REAL `VaR` calculation engine with multiple methodologies -// Infrastructure - fields will be used for VaR calculation configuration #[derive(Debug)] pub struct RealVaREngine { - confidence_levels: BoundedVec, - time_horizons_days: BoundedVec, min_historical_days: usize, - stress_scenarios: BoundedVec, } /// **Value at Risk (`VaR`) Calculation Methodology** @@ -494,94 +490,11 @@ impl RealVaREngine { /// Create new REAL `VaR` engine with production-grade parameters #[must_use] pub fn new() -> Self { - // Create bounded collections for memory safety - let mut confidence_levels = create_bounded_vec(10, OverflowStrategy::Reject); - let mut time_horizons_days = create_bounded_vec(10, OverflowStrategy::Reject); - let mut stress_scenarios = create_bounded_vec(50, OverflowStrategy::DropOldest); - - // Initialize with standard risk management values - for level in [0.95, 0.99, 0.999] { - confidence_levels.push(level); - } - - for horizon in [1, 10, 22] { - time_horizons_days.push(horizon); - } - - // Initialize stress scenarios - for scenario in Self::create_default_stress_scenarios() { - stress_scenarios.push(scenario); - } - Self { - confidence_levels, - time_horizons_days, min_historical_days: 252, // Minimum 1 year of data for reliable estimates - stress_scenarios, } } - /// Create stress scenarios based on historical market crashes - fn create_default_stress_scenarios() -> Vec { - vec![ - StressScenario { - name: "2008_Financial_Crisis".to_owned(), - description: "Market crash similar to 2008 financial crisis".to_owned(), - asset_shocks: [ - ("EQUITIES".to_owned(), -0.40), // 40% equity drop - ("CREDIT".to_owned(), -0.30), // 30% credit spread widening - ("VOLATILITY".to_owned(), 2.5), // 250% volatility increase - ] - .iter() - .cloned() - .collect(), - correlation_multiplier: 1.5, // Correlations increase during crisis - probability_estimate: Some(0.01), // ~1% annual probability - }, - StressScenario { - name: "COVID_Pandemic".to_owned(), - description: "Market shock similar to March 2020".to_owned(), - asset_shocks: [ - ("EQUITIES".to_owned(), -0.35), - ("OIL".to_owned(), -0.60), // Oil price collapse - ("BONDS".to_owned(), 0.15), // Flight to quality - ] - .iter() - .cloned() - .collect(), - correlation_multiplier: 1.3, - probability_estimate: Some(0.02), - }, - StressScenario { - name: "Flash_Crash".to_owned(), - description: "Intraday liquidity crisis".to_owned(), - asset_shocks: [ - ("EQUITIES".to_owned(), -0.15), - ("VOLATILITY".to_owned(), 3.0), - ] - .iter() - .cloned() - .collect(), - correlation_multiplier: 2.0, // Very high correlations during flash crashes - probability_estimate: Some(0.05), - }, - StressScenario { - name: "Inflation_Shock".to_owned(), - description: "Unexpected inflation surge".to_owned(), - asset_shocks: [ - ("BONDS".to_owned(), -0.25), - ("REAL_ESTATE".to_owned(), -0.20), - ("COMMODITIES".to_owned(), 0.30), - ] - .iter() - .cloned() - .collect(), - correlation_multiplier: 1.2, - probability_estimate: Some(0.03), - }, - ] - } - /// Calculate comprehensive `VaR` using best methodology for given data /// NO MORE MOCK VALUES - all calculations use real mathematical models pub async fn calculate_comprehensive_var( @@ -1490,9 +1403,7 @@ mod tests { #[test] fn test_real_var_engine_creation() { let engine = RealVaREngine::new(); - assert_eq!(engine.confidence_levels, vec![0.95, 0.99, 0.999]); assert_eq!(engine.min_historical_days, 252); - assert!(!engine.stress_scenarios.is_empty()); } #[test] diff --git a/services/api_gateway/load_tests/src/clients/mixed_workload.rs b/services/api_gateway/load_tests/src/clients/mixed_workload.rs index 35222f6a3..8e14bb71c 100644 --- a/services/api_gateway/load_tests/src/clients/mixed_workload.rs +++ b/services/api_gateway/load_tests/src/clients/mixed_workload.rs @@ -80,39 +80,4 @@ impl MixedWorkloadClient { Ok(()) } - /// Run constant order submission workload (for maximum throughput testing) - pub async fn run_order_only_workload(&mut self, duration: std::time::Duration) -> Result<()> { - let start = std::time::Instant::now(); - - while start.elapsed() < duration { - let metric = self - .client - .submit_order(self.client_id, TestOrder::random()) - .await?; - - self.metrics_tx.send(metric)?; - } - - Ok(()) - } - - /// Run query-heavy workload (for cache testing) - pub async fn run_query_heavy_workload(&mut self, duration: std::time::Duration) -> Result<()> { - use rand::Rng; - let start = std::time::Instant::now(); - - while start.elapsed() < duration { - let metric = self.client.get_positions(self.client_id).await?; - self.metrics_tx.send(metric)?; - - // Very small think time for query workload - let think_time_ms = { - let mut rng = rand::thread_rng(); - rng.gen_range(1..=10) - }; - tokio::time::sleep(tokio::time::Duration::from_millis(think_time_ms)).await; - } - - Ok(()) - } } diff --git a/services/api_gateway/load_tests/src/orchestrator.rs b/services/api_gateway/load_tests/src/orchestrator.rs index 33d8b10ac..179d72148 100644 --- a/services/api_gateway/load_tests/src/orchestrator.rs +++ b/services/api_gateway/load_tests/src/orchestrator.rs @@ -1,66 +1,2 @@ // Orchestrator module for managing load test execution // This module provides utilities for coordinating multiple test scenarios - -use anyhow::Result; -use std::time::Duration; - -pub struct TestOrchestrator { - gateway_url: String, -} - -impl TestOrchestrator { - pub fn new(gateway_url: String) -> Self { - Self { gateway_url } - } - - /// Run all test scenarios in sequence with cooldown periods between tests - pub async fn run_all_scenarios(&self) -> Result<()> { - tracing::info!("Starting orchestrated test suite"); - - // Normal load test - tracing::info!("=== Running Normal Load Test ==="); - let normal_report = - crate::scenarios::normal_load::run(self.gateway_url.clone(), 1000_usize, 60_u64) - .await?; - crate::reporting::generate_html_report("normal_load_report.html", normal_report)?; - - // Cooldown - self.cooldown(30).await; - - // Spike load test - tracing::info!("=== Running Spike Load Test ==="); - let spike_report = crate::scenarios::spike_load::run( - self.gateway_url.clone(), - 10000_usize, - 10_u64, - 60_u64, - ) - .await?; - crate::reporting::generate_html_report("spike_load_report.html", spike_report)?; - - // Cooldown - self.cooldown(30).await; - - // Stress test (shortened for orchestrated run) - tracing::info!("=== Running Stress Test ==="); - let stress_report = crate::scenarios::stress_test::run( - self.gateway_url.clone(), - 100_usize, - 100_usize, - 60_u64, - 50.0, - 5.0, - ) - .await?; - crate::reporting::generate_html_report("stress_test_report.html", stress_report)?; - - tracing::info!("All orchestrated tests completed successfully"); - - Ok(()) - } - - async fn cooldown(&self, seconds: u64) { - tracing::info!("Cooldown period: {}s", seconds); - tokio::time::sleep(Duration::from_secs(seconds)).await; - } -} diff --git a/services/api_gateway/src/auth/interceptor.rs b/services/api_gateway/src/auth/interceptor.rs index 2804dcad0..89d4c82a0 100644 --- a/services/api_gateway/src/auth/interceptor.rs +++ b/services/api_gateway/src/auth/interceptor.rs @@ -328,10 +328,6 @@ pub struct JwtService { decoding_key: Arc, /// Validation rules validation: Validation, - /// Expected issuer - issuer: String, - /// Expected audience - audience: String, } impl JwtService { @@ -351,8 +347,6 @@ impl JwtService { Self { decoding_key, validation, - issuer, - audience, } } diff --git a/services/api_gateway/src/auth/mfa/mod.rs b/services/api_gateway/src/auth/mfa/mod.rs index 6e9cf8a6f..09156e92d 100644 --- a/services/api_gateway/src/auth/mfa/mod.rs +++ b/services/api_gateway/src/auth/mfa/mod.rs @@ -31,7 +31,7 @@ pub use verification::{MfaVerification, VerificationError, VerificationResult}; use anyhow::{Context, Result}; use chrono::{DateTime, Utc}; -use secrecy::{ExposeSecret, Secret}; +use secrecy::ExposeSecret; use serde::{Deserialize, Serialize}; use sqlx::PgPool; use std::sync::Arc; @@ -83,7 +83,6 @@ impl std::fmt::Display for MfaMethod { #[derive(Clone)] pub struct MfaManager { db_pool: Arc, - encryption_key: Secret, totp_generator: Arc, totp_verifier: Arc, backup_code_generator: Arc, @@ -93,9 +92,8 @@ pub struct MfaManager { impl MfaManager { /// Create new MFA manager - pub fn new(db_pool: PgPool, encryption_key: String) -> Result { + pub fn new(db_pool: PgPool, _encryption_key: String) -> Result { let db_pool = Arc::new(db_pool); - let encryption_key = Secret::new(encryption_key); let totp_generator = Arc::new(TotpGenerator::new()); let totp_verifier = Arc::new(TotpVerifier::new()); @@ -105,7 +103,6 @@ impl MfaManager { Ok(Self { db_pool, - encryption_key, totp_generator, totp_verifier, backup_code_generator, diff --git a/services/api_gateway/src/config/authz.rs b/services/api_gateway/src/config/authz.rs index 1ad5f8143..11f5a7292 100644 --- a/services/api_gateway/src/config/authz.rs +++ b/services/api_gateway/src/config/authz.rs @@ -33,18 +33,13 @@ pub enum PermissionResult { /// Cached user permissions #[derive(Debug, Clone)] struct UserPermissions { - user_id: Uuid, permissions: HashSet, loaded_at: Instant, } -/// Cached role permissions +/// Cached role permissions (stored for cache invalidation) #[derive(Debug, Clone)] -struct RolePermissions { - role_name: String, - permissions: HashSet, - loaded_at: Instant, -} +struct RolePermissions; /// RBAC Authorization Service pub struct AuthzService { @@ -193,7 +188,6 @@ impl AuthzService { ); Ok(UserPermissions { - user_id: *user_id, permissions, loaded_at: Instant::now(), }) @@ -211,14 +205,10 @@ impl AuthzService { // 2. Update role permissions cache (lock-free DashMap operations) self.role_permissions_cache.clear(); - for (role_name, permissions) in role_perms { + for (role_name, _permissions) in role_perms { self.role_permissions_cache.insert( - role_name.clone(), - RolePermissions { - role_name, - permissions, - loaded_at: Instant::now(), - }, + role_name, + RolePermissions, ); } diff --git a/services/api_gateway/src/routing/rate_limiter.rs b/services/api_gateway/src/routing/rate_limiter.rs index 4d61067ce..f2f41eec3 100644 --- a/services/api_gateway/src/routing/rate_limiter.rs +++ b/services/api_gateway/src/routing/rate_limiter.rs @@ -48,11 +48,6 @@ impl TokenBucket { } } - /// Check if bucket has at least one token available - fn has_tokens(&self) -> bool { - self.tokens >= 1.0 - } - /// Refill tokens based on elapsed time fn refill(&mut self) { let now = Instant::now(); @@ -401,8 +396,8 @@ mod tests { fn test_token_bucket_basic() { let mut bucket = TokenBucket::new(10.0, 10.0); - // Should have full capacity - assert!(bucket.has_tokens()); + // Should have full capacity (tokens >= 1.0) + assert!(bucket.tokens >= 1.0); // Consume 10 tokens for _ in 0..10 { diff --git a/services/backtesting_service/src/dbn_data_source.rs b/services/backtesting_service/src/dbn_data_source.rs index 9f6c9afd6..c97993240 100644 --- a/services/backtesting_service/src/dbn_data_source.rs +++ b/services/backtesting_service/src/dbn_data_source.rs @@ -41,9 +41,7 @@ use rust_decimal::Decimal; use std::collections::HashMap; use std::fs; use std::path::Path; -use std::sync::Arc; use std::time::Instant; -use tokio::sync::RwLock; use tracing::{debug, info, warn}; /// Check if file path is a valid uncompressed DBN file @@ -122,10 +120,6 @@ fn dbn_price_to_f64(price: i64) -> f64 { #[derive(Debug, Clone)] struct FileEntry { path: String, - /// Cached first timestamp (populated eagerly on first load) - first_ts: Option>, - /// Cached last timestamp (populated eagerly on first load) - last_ts: Option>, } /// DBN data source for backtesting service @@ -138,13 +132,6 @@ pub struct DbnDataSource { /// Symbol to DBN file path(s) mapping /// Supports both single file (`String`) and multiple files (`Vec`) file_mapping: HashMap>, - - /// LRU cache for loaded bars (symbol -> bars) - reserved for future use - /// Cache size limited to prevent memory bloat - cache: Arc>>>, - - /// Maximum cache entries (0 = disabled) - reserved for future use - cache_limit: usize, } impl DbnDataSource { @@ -164,8 +151,6 @@ impl DbnDataSource { symbol, vec![FileEntry { path, - first_ts: None, - last_ts: None, }], ); } @@ -177,8 +162,6 @@ impl DbnDataSource { Ok(Self { file_mapping: multi_file_mapping, - cache: Arc::new(RwLock::new(HashMap::new())), - cache_limit: 10, // Default: cache last 10 symbols }) } @@ -222,8 +205,6 @@ impl DbnDataSource { .into_iter() .map(|path| FileEntry { path, - first_ts: None, - last_ts: None, }) .collect(); @@ -239,8 +220,6 @@ impl DbnDataSource { Ok(Self { file_mapping: entry_mapping, - cache: Arc::new(RwLock::new(HashMap::new())), - cache_limit: 10, }) } @@ -276,54 +255,6 @@ impl DbnDataSource { DbnDataSource::new_multi_file(valid_files).await } - /// Set cache limit (0 to disable caching) - pub fn with_cache_limit(mut self, limit: usize) -> Self { - self.cache_limit = limit; - self - } - - /// Eagerly populate first/last timestamp metadata for all file entries - /// - /// This reads the first and last OHLCV record from each file, which enables - /// `load_ohlcv_bars_range` to skip files without re-peeking on every call. - /// Useful when the same `DbnDataSource` is reused for multiple range queries. - /// - /// Files that fail to parse are logged as warnings and left with `None` timestamps. - pub async fn populate_file_metadata(&mut self) { - for (symbol, entries) in &mut self.file_mapping { - for entry in entries.iter_mut() { - if entry.first_ts.is_some() && entry.last_ts.is_some() { - continue; // Already populated - } - match Self::peek_file_timestamps(&entry.path) { - Ok(Some((first, last))) => { - entry.first_ts = Some(first); - entry.last_ts = Some(last); - debug!( - "Populated metadata for {} ({}): {}..{}", - symbol, - entry.path, - first.format("%Y-%m-%dT%H:%M:%S"), - last.format("%Y-%m-%dT%H:%M:%S"), - ); - } - Ok(None) => { - warn!( - "No OHLCV records found in file {} for symbol {}", - entry.path, symbol - ); - } - Err(e) => { - warn!( - "Failed to peek timestamps for {} ({}): {}", - symbol, entry.path, e - ); - } - } - } - } - } - /// Load OHLCV bars for a specific symbol from single file /// /// Reads the first DBN file for the symbol, parses with zero-copy, and converts to MarketData format. @@ -455,12 +386,8 @@ impl DbnDataSource { let mut files_skipped = 0; for entry in entries { - // Use cached metadata if available, otherwise peek at file timestamps - let ts_range = if let (Some(first), Some(last)) = (entry.first_ts, entry.last_ts) { - Some((first, last)) - } else { - Self::peek_file_timestamps(&entry.path).ok().flatten() - }; + // Peek at file timestamps to determine range + let ts_range = Self::peek_file_timestamps(&entry.path).ok().flatten(); if let Some((file_first_ts, file_last_ts)) = ts_range { // Skip file entirely if its range doesn't overlap [start_date, end_date] @@ -900,8 +827,6 @@ impl DbnDataSource { symbol, vec![FileEntry { path: file_path, - first_ts: None, - last_ts: None, }], ); } @@ -912,8 +837,6 @@ impl DbnDataSource { .into_iter() .map(|path| FileEntry { path, - first_ts: None, - last_ts: None, }) .collect(); self.file_mapping.insert(symbol, entries); @@ -1091,58 +1014,6 @@ mod tests { assert_eq!(first_ts.format("%Y").to_string(), "2024"); } - #[tokio::test] - async fn test_populate_file_metadata() { - let current_dir = - std::env::current_dir().expect("INVARIANT: Current directory should be accessible"); - let workspace_root = current_dir - .ancestors() - .find(|p| p.join("Cargo.toml").exists() && p.join("test_data").exists()); - - let workspace_root = match workspace_root { - Some(r) => r, - None => { - eprintln!("Could not find workspace root, skipping test"); - return; - } - }; - - let test_file = - workspace_root.join("test_data/real/databento/ES.FUT_ohlcv-1m_2024-01-02.dbn"); - - if !test_file.exists() { - eprintln!("Test file not found, skipping test"); - return; - } - - let mut file_mapping = HashMap::new(); - file_mapping.insert( - "ES.FUT".to_string(), - test_file.to_string_lossy().to_string(), - ); - - let mut data_source = DbnDataSource::new(file_mapping).await.unwrap(); - - // Before populate, metadata should be None - // (We can't access internals directly, but populate should succeed) - data_source.populate_file_metadata().await; - - // After populate, range queries should still work correctly - let bars = data_source - .load_ohlcv_bars_range( - "ES.FUT", - Utc.with_ymd_and_hms(2024, 1, 2, 0, 0, 0) - .single() - .unwrap_or_default(), - Utc.with_ymd_and_hms(2024, 1, 3, 0, 0, 0) - .single() - .unwrap_or_default(), - ) - .await; - assert!(bars.is_ok(), "Range query failed after metadata populate"); - assert!(!bars.unwrap().is_empty(), "Expected bars in 2024-01-02 range"); - } - #[tokio::test] async fn test_range_filtering_skips_out_of_range_files() { // Create a data source with a nonexistent file path. diff --git a/services/backtesting_service/src/dbn_repository.rs b/services/backtesting_service/src/dbn_repository.rs index 60aad0a40..d96759dc1 100644 --- a/services/backtesting_service/src/dbn_repository.rs +++ b/services/backtesting_service/src/dbn_repository.rs @@ -664,33 +664,6 @@ impl MarketDataRepository for DbnMarketDataRepository { Ok(filtered) } - - /// Check data availability for symbols and time range - /// - /// Returns a map of symbol to availability status. - async fn check_data_availability( - &self, - symbols: &[String], - start_time: i64, - end_time: i64, - ) -> Result> { - let start_dt = DateTime::from_timestamp(start_time / 1_000_000_000, 0) - .ok_or_else(|| anyhow::anyhow!("Invalid start timestamp"))?; - let end_dt = DateTime::from_timestamp(end_time / 1_000_000_000, 0) - .ok_or_else(|| anyhow::anyhow!("Invalid end timestamp"))?; - - let mut availability = HashMap::new(); - - for symbol in symbols { - let available = self - .data_source - .check_data_availability(symbol, start_dt, end_dt) - .await?; - availability.insert(symbol.clone(), available); - } - - Ok(availability) - } } #[cfg(test)] @@ -724,26 +697,6 @@ mod tests { assert_eq!(repository.available_symbols().len(), 1); } - #[tokio::test] - async fn test_check_data_availability() { - let mut file_mapping = HashMap::new(); - file_mapping.insert("ES.FUT".to_string(), get_test_file_path()); - - let repo = DbnMarketDataRepository::new(file_mapping).await.unwrap(); - - let start_time = 1704153600_000_000_000i64; // 2024-01-02 00:00:00 - let end_time = 1704240000_000_000_000i64; // 2024-01-03 00:00:00 - - let symbols = vec!["ES.FUT".to_string()]; - let availability = repo - .check_data_availability(&symbols, start_time, end_time) - .await; - - assert!(availability.is_ok()); - let avail_map = availability.unwrap(); - assert!(avail_map.contains_key("ES.FUT")); - } - #[tokio::test] async fn test_load_by_time_range() { let mut file_mapping = HashMap::new(); diff --git a/services/backtesting_service/src/main.rs b/services/backtesting_service/src/main.rs index 5842fba1c..bcb67c858 100644 --- a/services/backtesting_service/src/main.rs +++ b/services/backtesting_service/src/main.rs @@ -31,18 +31,13 @@ mod foxhunt { } } -use config::schemas::S3Config; use config::structures::BacktestingDatabaseConfig; -use model_loader::backtesting_cache::{BacktestCacheConfig, BacktestingModelCache}; use repository_impl::create_repositories; use service::BacktestingServiceImpl; use std::sync::Arc; use storage::StorageManager; use tls_config::BacktestingServiceTlsConfig; -// Import ObjectStoreBackend from external storage crate (not local storage module) -use ::storage::ObjectStoreBackend; - /// Main entry point for the backtesting service #[tokio::main] async fn main() -> Result<()> { @@ -90,49 +85,6 @@ async fn main() -> Result<()> { .context("Failed to initialize storage manager")?, ); - // Initialize S3 storage for model loading - let s3_config = S3Config { - bucket_name: std::env::var("MODEL_S3_BUCKET") - .unwrap_or_else(|_| "foxhunt-models".to_string()), - region: std::env::var("AWS_REGION").unwrap_or_else(|_| "us-east-1".to_string()), - access_key_id: std::env::var("AWS_ACCESS_KEY_ID").ok(), - secret_access_key: std::env::var("AWS_SECRET_ACCESS_KEY").ok(), - session_token: std::env::var("AWS_SESSION_TOKEN").ok(), - endpoint_url: std::env::var("AWS_ENDPOINT_URL").ok(), - force_path_style: std::env::var("AWS_FORCE_PATH_STYLE") - .map(|v| v == "true") - .unwrap_or(false), - max_retry_attempts: 3, - timeout: std::time::Duration::from_secs(30), - use_ssl: true, - }; - - // Create S3 storage backend for models - let s3_storage = ObjectStoreBackend::new(s3_config, None) - .await - .context("Failed to create S3 storage backend")?; - - // Initialize model cache for backtesting with S3 storage - let cache_config = BacktestCacheConfig { - cache_dir: std::env::var("MODEL_CACHE_DIR") - .unwrap_or_else(|_| "/tmp/foxhunt/model_cache".to_string()) - .into(), - ..Default::default() - }; - - let mut model_cache = BacktestingModelCache::new(s3_storage, cache_config) - .await - .context("Failed to create BacktestingModelCache for backtesting")?; - - // Initialize model cache - this will scan for existing models - model_cache - .initialize() - .await - .context("Failed to initialize ModelCache")?; - - let model_cache = Arc::new(model_cache); - info!("Backtesting model cache initialized with S3 storage and historical version support"); - // Create repositories with dependency injection let repositories = Arc::new( create_repositories(storage_manager) @@ -140,8 +92,8 @@ async fn main() -> Result<()> { .context("Failed to create repositories")?, ); - // Initialize the service with repository injection and model cache - let service = BacktestingServiceImpl::new(repositories, Some(Arc::clone(&model_cache))) + // Initialize the service with repository injection + let service = BacktestingServiceImpl::new(repositories) .await .context("Failed to initialize backtesting service")?; @@ -202,9 +154,6 @@ async fn main() -> Result<()> { server_identity: tonic::transport::Identity::from_pem(vec![0], vec![0]), ca_certificate: tonic::transport::Certificate::from_pem(vec![0]), require_client_cert: false, - protocol_version: tls_config::TlsProtocolVersion::Tls13, - enable_revocation_check: false, - crl_url: None, } }) }; diff --git a/services/backtesting_service/src/performance.rs b/services/backtesting_service/src/performance.rs index be0204cd9..86bb4d3cd 100644 --- a/services/backtesting_service/src/performance.rs +++ b/services/backtesting_service/src/performance.rs @@ -87,17 +87,6 @@ pub struct DrawdownPeriod { pub duration_days: u32, } -/// Rolling performance metrics -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RollingMetrics { - /// Rolling Sharpe ratios - pub rolling_sharpe: Vec<(chrono::DateTime, f64)>, - /// Rolling volatility - pub rolling_volatility: Vec<(chrono::DateTime, f64)>, - /// Rolling returns - pub rolling_returns: Vec<(chrono::DateTime, f64)>, -} - /// Performance analyzer for backtesting results #[derive(Debug)] pub struct PerformanceAnalyzer { @@ -414,75 +403,6 @@ impl PerformanceAnalyzer { periods } - /// Calculate rolling performance metrics - pub fn calculate_rolling_metrics( - &self, - trades: &[BacktestTrade], - window_days: u32, - ) -> RollingMetrics { - let mut rolling_sharpe = Vec::new(); - let mut rolling_volatility = Vec::new(); - let mut rolling_returns = Vec::new(); - - if trades.is_empty() { - return RollingMetrics { - rolling_sharpe, - rolling_volatility, - rolling_returns, - }; - } - - let window_duration = chrono::Duration::days(window_days as i64); - let start_time = trades - .first() - .map(|t| t.entry_time) - .unwrap_or_else(|| chrono::Utc::now()); - let end_time = trades - .last() - .map(|t| t.exit_time) - .unwrap_or_else(|| chrono::Utc::now()); - - let mut current_time = start_time + window_duration; - - while current_time <= end_time { - let window_start = current_time - window_duration; - - // Get trades in this window - let window_trades: Vec<&BacktestTrade> = trades - .iter() - .filter(|t| t.exit_time >= window_start && t.exit_time <= current_time) - .collect(); - - if !window_trades.is_empty() { - let returns: Vec = window_trades - .iter() - .filter_map(|t| t.return_percent.to_f64()) - .collect(); - - let window_years = window_days as f64 / 365.25; - let (volatility, sharpe) = - self.calculate_volatility_and_sharpe(&returns, window_years); - - let total_return: f64 = window_trades - .iter() - .filter_map(|t| t.return_percent.to_f64()) - .sum(); - - rolling_sharpe.push((current_time, sharpe)); - rolling_volatility.push((current_time, volatility * 100.0)); - rolling_returns.push((current_time, total_return * 100.0)); - } - - current_time += chrono::Duration::days(1); - } - - RollingMetrics { - rolling_sharpe, - rolling_volatility, - rolling_returns, - } - } - /// Calculate volatility and Sharpe ratio fn calculate_volatility_and_sharpe(&self, returns: &[f64], duration_years: f64) -> (f64, f64) { if returns.is_empty() || duration_years <= 0.0 { diff --git a/services/backtesting_service/src/repositories.rs b/services/backtesting_service/src/repositories.rs index 487970c85..0141dd778 100644 --- a/services/backtesting_service/src/repositories.rs +++ b/services/backtesting_service/src/repositories.rs @@ -3,7 +3,6 @@ use anyhow::Result; use async_trait::async_trait; use chrono::{DateTime, Utc}; -use std::collections::HashMap; use crate::foxhunt::tli::BacktestStatus; use crate::performance::PerformanceMetrics; @@ -33,14 +32,6 @@ pub trait MarketDataRepository: Send + Sync { start_time: i64, end_time: i64, ) -> Result>; - - /// Check data availability for given symbols and time range - async fn check_data_availability( - &self, - symbols: &[String], - start_time: i64, - end_time: i64, - ) -> Result>; } /// Repository trait for trading and backtest result operations @@ -63,27 +54,6 @@ pub trait TradingRepository: Send + Sync { backtest_id: &str, ) -> Result<(Vec, PerformanceMetrics)>; - /// Create a new backtest record - async fn create_backtest_record( - &self, - backtest_id: &str, - strategy_name: &str, - symbols: &[String], - start_date: DateTime, - end_date: DateTime, - initial_capital: f64, - parameters: &HashMap, - description: &str, - ) -> Result<()>; - - /// Update backtest status - async fn update_backtest_status( - &self, - backtest_id: &str, - status: BacktestStatus, - error_message: Option<&str>, - ) -> Result<()>; - /// List historical backtests async fn list_backtests( &self, @@ -92,15 +62,6 @@ pub trait TradingRepository: Send + Sync { strategy_name: Option, status_filter: Option, ) -> Result>; - - /// Store time-series performance data - async fn store_time_series_data( - &self, - backtest_id: &str, - timestamp: DateTime, - equity: f64, - drawdown: f64, - ) -> Result<()>; } /// Repository trait for news and sentiment data @@ -116,14 +77,6 @@ pub trait NewsRepository: Send + Sync { start_time: DateTime, end_time: DateTime, ) -> Result>; - - /// Get sentiment analysis for symbols - async fn get_sentiment_data( - &self, - symbols: &[String], - timestamp: DateTime, - lookback_hours: i32, - ) -> Result>; } /// Combined repository trait for dependency injection @@ -193,19 +146,6 @@ impl DefaultRepositories { ) -> Result> { Ok(self.data.read().await.clone()) } - - async fn check_data_availability( - &self, - symbols: &[String], - _start_time: i64, - _end_time: i64, - ) -> Result> { - let mut availability = HashMap::new(); - for symbol in symbols { - availability.insert(symbol.clone(), true); - } - Ok(availability) - } } // Mock trading repository @@ -243,47 +183,6 @@ impl DefaultRepositories { Ok((trades, metrics)) } - async fn create_backtest_record( - &self, - backtest_id: &str, - strategy_name: &str, - symbols: &[String], - start_date: DateTime, - end_date: DateTime, - _initial_capital: f64, - _parameters: &HashMap, - description: &str, - ) -> Result<()> { - let summary = BacktestSummary { - backtest_id: backtest_id.to_string(), - strategy_name: strategy_name.to_string(), - symbols: symbols.to_vec(), - status: BacktestStatus::Queued, - total_return: 0.0, - sharpe_ratio: 0.0, - max_drawdown: 0.0, - created_at: Utc::now(), - start_date, - end_date, - description: description.to_string(), - }; - self.backtests.write().await.push(summary); - Ok(()) - } - - async fn update_backtest_status( - &self, - backtest_id: &str, - status: BacktestStatus, - _error_message: Option<&str>, - ) -> Result<()> { - let mut backtests = self.backtests.write().await; - if let Some(bt) = backtests.iter_mut().find(|b| b.backtest_id == backtest_id) { - bt.status = status; - } - Ok(()) - } - async fn list_backtests( &self, limit: u32, @@ -307,16 +206,6 @@ impl DefaultRepositories { .collect(); Ok(filtered) } - - async fn store_time_series_data( - &self, - _backtest_id: &str, - _timestamp: DateTime, - _equity: f64, - _drawdown: f64, - ) -> Result<()> { - Ok(()) - } } // Mock news repository @@ -334,19 +223,6 @@ impl DefaultRepositories { ) -> Result> { Ok(self.events.read().await.clone()) } - - async fn get_sentiment_data( - &self, - symbols: &[String], - _timestamp: DateTime, - _lookback_hours: i32, - ) -> Result> { - let mut sentiment_map = HashMap::new(); - for symbol in symbols { - sentiment_map.insert(symbol.clone(), 0.0); - } - Ok(sentiment_map) - } } Self { diff --git a/services/backtesting_service/src/service.rs b/services/backtesting_service/src/service.rs index 7a7afc948..3c6fb504d 100644 --- a/services/backtesting_service/src/service.rs +++ b/services/backtesting_service/src/service.rs @@ -12,8 +12,6 @@ use crate::foxhunt::tli::{backtesting_service_server::BacktestingService, *}; use crate::performance::PerformanceAnalyzer; use crate::repositories::BacktestingRepositories; use crate::strategy_engine::StrategyEngine; -use model_loader::backtesting_cache::BacktestingModelCache; -use model_loader::ModelType; /// Implementation of the BacktestingService gRPC interface - REFACTORED pub struct BacktestingServiceImpl { @@ -23,8 +21,6 @@ pub struct BacktestingServiceImpl { performance_analyzer: Arc, /// Repository abstraction for data access - NO DIRECT DATABASE COUPLING repositories: Arc, - /// Model cache for historical consistency - model_cache: Option>, /// Active backtests tracking active_backtests: Arc>>, /// Progress event broadcaster @@ -63,12 +59,11 @@ pub struct BacktestContext { } impl BacktestingServiceImpl { - /// Create a new backtesting service instance with repository injection and model cache + /// Create a new backtesting service instance with repository injection pub async fn new( repositories: Arc, - model_cache: Option>, ) -> Result { - info!("Initializing backtesting service with repository injection and model cache"); + info!("Initializing backtesting service with repository injection"); // Initialize strategy engine with repository injection - using default config from centralized system let strategy_config = config::structures::BacktestingStrategyConfig::default(); @@ -89,7 +84,6 @@ impl BacktestingServiceImpl { strategy_engine, performance_analyzer, repositories, - model_cache, active_backtests: Arc::new(RwLock::new(HashMap::new())), progress_broadcaster: Arc::new(RwLock::new(HashMap::new())), }) @@ -100,116 +94,6 @@ impl BacktestingServiceImpl { Uuid::new_v4().to_string() } - /// Load model for specific version (critical for historical backtesting accuracy) - async fn load_model_version( - &self, - model_type: &str, - model_name: &str, - version: &str, - ) -> Result, Status> { - if let Some(model_cache) = &self.model_cache { - let _model_type = match model_type { - "tlob_transformer" => ModelType::TLOB, - "dqn" => ModelType::DQN, - "mamba2" => ModelType::MAMBA, - "tft" => ModelType::TFT, - "ppo" => ModelType::PPO, - "liquid" => ModelType::LNN, - "ensemble" => ModelType::Ensemble, - _ => { - return Err(Status::invalid_argument(format!( - "Unknown model type: {}", - model_type - ))) - }, - }; - - let version = semver::Version::parse(version) - .map_err(|e| Status::invalid_argument(format!("Invalid version format: {}", e)))?; - - model_cache - .get_model_version(model_name, &version) - .await - .map_err(|e| Status::internal(format!("Failed to load model version: {}", e))) - } else { - Err(Status::unavailable("Model cache not available")) - } - } - - /// Load model for specific time period (for historical consistency) - async fn load_model_for_period( - &self, - model_type: &str, - model_name: &str, - start_time: i64, - end_time: i64, - ) -> Result<(String, Vec), Status> { - if let Some(model_cache) = &self.model_cache { - let _model_type = match model_type { - "tlob_transformer" => ModelType::TLOB, - "dqn" => ModelType::DQN, - "mamba2" => ModelType::MAMBA, - "tft" => ModelType::TFT, - "ppo" => ModelType::PPO, - "liquid" => ModelType::LNN, - "ensemble" => ModelType::Ensemble, - _ => { - return Err(Status::invalid_argument(format!( - "Unknown model type: {}", - model_type - ))) - }, - }; - - let start_time = - std::time::UNIX_EPOCH + std::time::Duration::from_nanos(start_time as u64); - let end_time = std::time::UNIX_EPOCH + std::time::Duration::from_nanos(end_time as u64); - - model_cache - .get_model_for_period(model_name, start_time, end_time) - .await - .map(|(version, data)| (version.to_string(), data)) - .map_err(|e| Status::internal(format!("Failed to load model for period: {}", e))) - } else { - Err(Status::unavailable("Model cache not available")) - } - } - - /// List available model versions for backtesting - async fn list_available_model_versions( - &self, - model_type: &str, - model_name: &str, - ) -> Result, Status> { - if let Some(model_cache) = &self.model_cache { - let _model_type = match model_type { - "tlob_transformer" => ModelType::TLOB, - "dqn" => ModelType::DQN, - "mamba2" => ModelType::MAMBA, - "tft" => ModelType::TFT, - "ppo" => ModelType::PPO, - "liquid" => ModelType::LNN, - "ensemble" => ModelType::Ensemble, - _ => { - return Err(Status::invalid_argument(format!( - "Unknown model type: {}", - model_type - ))) - }, - }; - - match model_cache.list_model_versions(model_name).await { - Ok(versions) => Ok(versions.into_iter().map(|v| v.to_string()).collect()), - Err(e) => Err(Status::internal(format!( - "Failed to list model versions: {}", - e - ))), - } - } else { - Err(Status::unavailable("Model cache not available")) - } - } - /// Validate backtest request parameters async fn validate_backtest_request( &self, diff --git a/services/backtesting_service/src/storage.rs b/services/backtesting_service/src/storage.rs index d61cb1462..2be688cfd 100644 --- a/services/backtesting_service/src/storage.rs +++ b/services/backtesting_service/src/storage.rs @@ -3,8 +3,7 @@ use anyhow::{Context, Result}; use rust_decimal::{prelude::ToPrimitive, Decimal}; use sqlx::{PgPool, Row}; -use std::collections::HashMap; -use tracing::{debug, info}; // For Decimal::from_f64 +use tracing::info; use crate::foxhunt::tli::BacktestStatus; use crate::performance::PerformanceMetrics; @@ -42,12 +41,8 @@ pub struct BacktestSummary { /// Storage manager for backtesting data #[derive(Debug)] pub struct StorageManager { - /// HFT-optimized Postgre`SQL` connection pool - db_pool: DatabasePool, /// Raw PgPool for compatibility with existing queries pg_pool: PgPool, - /// InfluxDB client for time-series backtest data - influxdb_client: Option, } impl StorageManager { @@ -65,36 +60,8 @@ impl StorageManager { let pg_pool = db_pool.pool().clone(); - // Run database migrations - simplified for now - /* - sqlx::migrate!("./migrations") - .run(&pg_pool) - .await - .context("Failed to run database migrations")?; - - info!("Database migrations completed successfully"); - */ - - // Initialize InfluxDB client from environment variables - let influxdb_client = match ( - std::env::var("INFLUXDB_URL"), - std::env::var("INFLUXDB_TOKEN"), - std::env::var("INFLUXDB_ORG"), - ) { - (Ok(url), Ok(token), Ok(org)) => { - info!("Initializing InfluxDB client at {}", url); - Some(influxdb2::Client::new(url, org, token)) - } - _ => { - info!("InfluxDB not configured — time-series storage disabled"); - None - } - }; - Ok(Self { - db_pool, pg_pool, - influxdb_client, }) } @@ -370,145 +337,6 @@ impl StorageManager { Ok(summaries) } - /// Create a new backtest record - pub async fn create_backtest_record( - &self, - backtest_id: &str, - strategy_name: &str, - symbols: &[String], - start_date: chrono::DateTime, - end_date: chrono::DateTime, - initial_capital: f64, - parameters: &HashMap, - description: &str, - ) -> Result<()> { - info!("Creating backtest record for {}", backtest_id); - - let symbols_json = serde_json::to_string(symbols).context("Failed to serialize symbols")?; - - let parameters_json = - serde_json::to_string(parameters).context("Failed to serialize parameters")?; - - sqlx::query( - r#" - INSERT INTO backtests ( - backtest_id, strategy_name, symbols, start_date, end_date, - initial_capital, parameters, description, status, created_at - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, 'queued', NOW()) - "#, - ) - .bind(backtest_id) - .bind(strategy_name) - .bind(symbols_json) - .bind(start_date) - .bind(end_date) - .bind(initial_capital) - .bind(parameters_json) - .bind(description) - .execute(&self.pg_pool) - .await?; - - info!("Created backtest record for {}", backtest_id); - Ok(()) - } - - /// Update backtest status - pub async fn update_backtest_status( - &self, - backtest_id: &str, - status: BacktestStatus, - error_message: Option<&str>, - ) -> Result<()> { - let status_str = match status { - BacktestStatus::Queued => "queued", - BacktestStatus::Running => "running", - BacktestStatus::Completed => "completed", - BacktestStatus::Failed => "failed", - BacktestStatus::Cancelled => "cancelled", - BacktestStatus::Paused => "paused", - _ => "unknown", - }; - - sqlx::query( - r#" - UPDATE backtests - SET status = $2, error_message = $3, updated_at = NOW() - WHERE backtest_id = $1 - "#, - ) - .bind(backtest_id) - .bind(status_str) - .bind(error_message) - .execute(&self.pg_pool) - .await?; - - Ok(()) - } - - /// Store time-series performance data in InfluxDB - pub async fn store_time_series_data( - &self, - backtest_id: &str, - timestamp: chrono::DateTime, - equity: f64, - drawdown: f64, - ) -> Result<()> { - let Some(ref client) = self.influxdb_client else { - debug!("InfluxDB not configured — skipping time-series write"); - return Ok(()); - }; - - use influxdb2::models::DataPoint; - let point = DataPoint::builder("backtest_equity") - .tag("backtest_id", backtest_id) - .field("equity", equity) - .field("drawdown", drawdown) - .timestamp(timestamp.timestamp_nanos_opt().unwrap_or(0)) - .build() - .map_err(|e| anyhow::anyhow!("Failed to build data point: {}", e))?; - - let bucket = - std::env::var("INFLUXDB_BUCKET").unwrap_or_else(|_| "backtests".to_string()); - client - .write(&bucket, tokio_stream::iter(vec![point])) - .await - .map_err(|e| anyhow::anyhow!("InfluxDB write failed: {}", e))?; - - Ok(()) - } - - /// Get database health status and pool statistics - pub async fn get_health_status(&self) -> Result { - // Perform health check - self.db_pool - .health_check() - .await - .context("Database health check failed")?; - - // Get pool statistics - let pool_stats = self.db_pool.pool_stats(); - - Ok(serde_json::json!({ - "database": { - "status": "healthy", - "connection_pool": "HFT-optimized", - "pool_stats": { - "size": pool_stats.size, - "idle": pool_stats.idle, - "active": pool_stats.active, - "max_size": pool_stats.max_size, - "utilization_percent": pool_stats.utilization_percentage(), - "is_healthy": pool_stats.is_healthy() - }, - "performance_config": { - "query_timeout_micros": 5000, - "connection_prewarming": "enabled", - "prepared_statements": "enabled", - "slow_query_threshold_micros": 10000 - } - } - })) - } } impl From for crate::foxhunt::tli::BacktestSummary { diff --git a/services/backtesting_service/src/strategy_engine.rs b/services/backtesting_service/src/strategy_engine.rs index aa63e0546..5a94b7b3e 100644 --- a/services/backtesting_service/src/strategy_engine.rs +++ b/services/backtesting_service/src/strategy_engine.rs @@ -8,31 +8,12 @@ use std::collections::HashMap; use std::sync::Arc; use tracing::{debug, info}; -use data::unified_feature_extractor::{UnifiedFeatureExtractor, UnifiedFeatureExtractorConfig}; - use crate::repositories::BacktestingRepositories; use config::structures::BacktestingStrategyConfig; /// News event structure for strategy consumption #[derive(Debug, Clone)] -pub struct NewsEvent { - /// Unique event ID - pub id: String, - /// Event timestamp - pub timestamp: chrono::DateTime, - /// Related symbols - pub symbols: Vec, - /// Event title/headline - pub title: String, - /// Event content/body - pub content: String, - /// Sentiment score (-1.0 to 1.0) - pub sentiment: f64, - /// Importance score (0.0 to 1.0) - pub importance: f64, - /// News source - pub source: String, -} +pub struct NewsEvent; /// Market data structure for backtesting #[derive(Debug, Clone)] @@ -148,29 +129,11 @@ impl Portfolio { } } - /// Calculate current portfolio value - fn current_value(&self, market_prices: &HashMap) -> Decimal { - let mut total_value = self.cash; - - for position in self.positions.values() { - if let Some(price) = market_prices.get(&position.symbol) { - total_value += position.quantity * price; - } - } - - total_value - } - /// Get position for symbol pub fn get_position(&self, symbol: &str) -> Option<&Position> { self.positions.get(symbol) } - /// Get current cash balance - pub fn cash(&self) -> Decimal { - self.cash - } - /// Execute a trade (buy or sell) fn execute_trade( &mut self, @@ -299,8 +262,6 @@ pub struct StrategyEngine { repositories: Arc, /// Available strategies strategies: HashMap>, - /// Unified feature extractor - feature_extractor: Arc, } /// Trait for strategy execution @@ -312,9 +273,6 @@ pub trait StrategyExecutor: Send + Sync + std::fmt::Debug { portfolio: &Portfolio, parameters: &HashMap, ) -> Result>; - - /// Get strategy name - fn name(&self) -> &str; } /// `Trade` signal from strategy @@ -326,14 +284,8 @@ pub struct TradeSignal { pub side: TradeSide, /// Quantity (can be percentage of portfolio or absolute) pub quantity: Decimal, - /// Signal strength (0.0 to 1.0) - pub strength: Decimal, /// Signal reason/description pub reason: String, - /// Feature vector used for this signal (optional) - pub features: Option>, - /// News events that influenced this signal (optional) - pub news_events: Option>, } /// Simple moving average crossover strategy @@ -361,10 +313,7 @@ impl StrategyExecutor for MovingAverageCrossoverStrategy { symbol: market_data.symbol.clone(), side: TradeSide::Sell, quantity: position.quantity, // Sell entire position - strength: Decimal::from_f64_retain(0.8).unwrap_or(Decimal::ZERO), reason: "Price below MA - exit".to_string(), - features: None, - news_events: None, }); } } else { @@ -376,10 +325,7 @@ impl StrategyExecutor for MovingAverageCrossoverStrategy { symbol: market_data.symbol.clone(), side: TradeSide::Buy, quantity, - strength: Decimal::from_f64_retain(0.8).unwrap_or(Decimal::ZERO), reason: "Price above MA - entry".to_string(), - features: None, - news_events: None, }); } } @@ -387,10 +333,6 @@ impl StrategyExecutor for MovingAverageCrossoverStrategy { Ok(signals) } - - fn name(&self) -> &str { - "moving_average_crossover" - } } /// Buy and hold strategy @@ -421,19 +363,12 @@ impl StrategyExecutor for BuyAndHoldStrategy { symbol: market_data.symbol.clone(), side: TradeSide::Buy, quantity, - strength: Decimal::ONE, reason: "Buy and hold".to_string(), - features: None, - news_events: None, }); } Ok(signals) } - - fn name(&self) -> &str { - "buy_and_hold" - } } /// News-aware trading strategy that uses news events for decision making @@ -490,29 +425,15 @@ impl StrategyExecutor for NewsAwareStrategy { symbol: market_data.symbol.clone(), side: TradeSide::Buy, quantity, - strength: Decimal::from_f64_retain(0.8).unwrap_or_else(|| { - Decimal::from_f64_retain(0.5).unwrap_or(Decimal::ONE / Decimal::from(2)) - }), reason: format!( "News-driven bullish signal: sentiment={:.2}, momentum={:.1}", simulated_sentiment, simulated_momentum ), - features: Some({ - let mut features = HashMap::new(); - features.insert("news_sentiment_1h".to_string(), simulated_sentiment); - features.insert("momentum_indicator".to_string(), simulated_momentum); - features - }), - news_events: Some(vec!["Positive earnings news".to_string()]), // Would be real news IDs }); } Ok(signals) } - - fn name(&self) -> &str { - "news_aware_strategy" - } } impl StrategyEngine { @@ -536,26 +457,13 @@ impl StrategyEngine { Box::new(NewsAwareStrategy), ); - // Initialize unified feature extractor - let feature_config = UnifiedFeatureExtractorConfig::default(); - let feature_extractor = Arc::new( - UnifiedFeatureExtractor::new(feature_config) - .context("Failed to create UnifiedFeatureExtractor")?, - ); - Ok(Self { config: config.clone(), repositories, strategies, - feature_extractor, }) } - /// Register a custom strategy - pub fn register_strategy(&mut self, name: String, strategy: Box) { - self.strategies.insert(name, strategy); - } - /// Execute a backtest using repository pattern /// /// This is the backward-compatible entry point. For progress reporting use diff --git a/services/backtesting_service/src/tls_config.rs b/services/backtesting_service/src/tls_config.rs index 99b25840b..39f4105ed 100644 --- a/services/backtesting_service/src/tls_config.rs +++ b/services/backtesting_service/src/tls_config.rs @@ -7,21 +7,14 @@ //! - Performance optimized for HFT requirements use anyhow::{Context, Result}; -use config::manager::ConfigManager; // Re-export shared TLS types from common for backward compatibility #[allow(unused_imports)] pub use common::tls::{ClientIdentity, TlsProtocolVersion, UserRole}; -use config::structures::TlsConfig; -use std::sync::Arc; // TLS imports - TLS feature should be enabled in Cargo.toml use tonic::transport::{Certificate, Identity, ServerTlsConfig}; use tracing::info; -use x509_parser::certificate::X509Certificate; -use x509_parser::extensions::{GeneralName, ParsedExtension}; -use x509_parser::prelude::*; - /// TLS configuration for the trading service #[derive(Debug, Clone)] pub struct BacktestingServiceTlsConfig { @@ -31,12 +24,6 @@ pub struct BacktestingServiceTlsConfig { pub ca_certificate: Certificate, /// Require client certificates pub require_client_cert: bool, - /// TLS protocol version (1.2 or 1.3) - pub protocol_version: TlsProtocolVersion, - /// Certificate revocation checking enabled - pub enable_revocation_check: bool, - /// CRL distribution point URL (optional) - pub crl_url: Option, } impl BacktestingServiceTlsConfig { @@ -77,42 +64,9 @@ impl BacktestingServiceTlsConfig { server_identity, ca_certificate, require_client_cert, - protocol_version: TlsProtocolVersion::Tls13, - enable_revocation_check: false, // Default disabled for compatibility - crl_url: None, }) } - /// Create TLS configuration from config crate - pub async fn from_config(config_manager: &ConfigManager) -> Result { - info!("Loading TLS certificates from configuration"); - - // Get the service config which contains settings as JSON - let service_config = config_manager.get_config(); - - // Extract TLS config from the settings JSON field - let tls_config: TlsConfig = serde_json::from_value( - service_config - .settings - .get("tls") - .cloned() - .unwrap_or(serde_json::json!({})), - ) - .unwrap_or_default(); - - // Use environment variable for CA cert path with fallback to /tmp - let ca_cert_path = std::env::var("TLS_CA_PATH") - .unwrap_or_else(|_| "/tmp/foxhunt/certs/ca.crt".to_string()); - - Self::from_files( - &tls_config.cert_path, - &tls_config.key_path, - tls_config.ca_cert_path.as_deref().unwrap_or(&ca_cert_path), - true, // Always require mTLS - ) - .await - } - /// Convert to tonic ServerTlsConfig pub fn to_server_tls_config(&self) -> ServerTlsConfig { let mut tls_config = ServerTlsConfig::new().identity(self.server_identity.clone()); @@ -123,574 +77,6 @@ impl BacktestingServiceTlsConfig { tls_config } - - /// Validate client certificate and extract identity - pub async fn validate_client_certificate(&self, cert_chain: &[u8]) -> Result { - // Parse the X.509 certificate from PEM format - let (_, pem) = x509_parser::pem::parse_x509_pem(cert_chain) - .map_err(|e| anyhow::anyhow!("Failed to parse PEM certificate: {}", e))?; - - let cert = pem - .parse_x509() - .map_err(|e| anyhow::anyhow!("Failed to parse X.509 certificate: {}", e))?; - - // Comprehensive certificate validation - let client_identity = self.extract_and_validate_certificate(&cert).await?; - - tracing::info!( - "Client certificate validated: CN={}, OU={}", - client_identity.common_name, - client_identity.organizational_unit - ); - - Ok(client_identity) - } - - /// Extract and validate certificate with comprehensive security checks - async fn extract_and_validate_certificate( - &self, - cert: &X509Certificate<'_>, - ) -> Result { - // SECURITY CHECK 1: Certificate Validity Period (Expiration) - self.validate_certificate_expiration(cert)?; - - // SECURITY CHECK 2: Certificate Purpose (Extended Key Usage) - self.validate_certificate_purpose(cert)?; - - // SECURITY CHECK 3: Certificate Chain of Trust (Basic Constraints) - self.validate_certificate_constraints(cert)?; - - // SECURITY CHECK 4: Critical Extensions Validation - self.validate_critical_extensions(cert)?; - - // SECURITY CHECK 5: Subject Alternative Names (if present) - self.validate_subject_alternative_names(cert)?; - - // SECURITY CHECK 6: Certificate Revocation Status (CRL/OCSP) - if self.enable_revocation_check { - self.check_revocation_status(cert).await?; - } - - // Extract identity information from Subject DN - let subject = cert.subject(); - - // Extract Common Name (CN) - let common_name = subject - .iter_common_name() - .next() - .and_then(|cn| cn.as_str().ok()) - .ok_or_else(|| anyhow::anyhow!("Certificate missing Common Name (CN)"))? - .to_string(); - - // Extract Organizational Unit (OU) - required for RBAC - let organizational_unit = subject - .iter_organizational_unit() - .next() - .and_then(|ou| ou.as_str().ok()) - .ok_or_else(|| anyhow::anyhow!("Certificate missing Organizational Unit (OU)"))? - .to_string(); - - // Extract Serial Number - let serial_number = format!("{:X}", cert.serial); - - // Extract Issuer CN - let issuer = cert - .issuer() - .iter_common_name() - .next() - .and_then(|cn| cn.as_str().ok()) - .unwrap_or("Unknown Issuer") - .to_string(); - - // SECURITY: Validate organizational unit is in allowed list - let allowed_ous = ["trading", "admin", "analytics", "risk", "compliance"]; - if !allowed_ous.contains(&organizational_unit.as_str()) { - return Err(anyhow::anyhow!( - "Organizational Unit '{}' is not authorized for access. Allowed: {:?}", - organizational_unit, - allowed_ous - )); - } - - // SECURITY: Validate common name format (prevent injection attacks) - if !common_name - .chars() - .all(|c| c.is_alphanumeric() || c == '.' || c == '-' || c == '_') - { - return Err(anyhow::anyhow!( - "Common Name contains invalid characters: {}", - common_name - )); - } - - Ok(ClientIdentity { - common_name, - organizational_unit, - serial_number, - issuer, - }) - } - - /// SECURITY CHECK 1: Validate certificate expiration - fn validate_certificate_expiration(&self, cert: &X509Certificate<'_>) -> Result<()> { - let validity = cert.validity(); - - // Get current time - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .map_err(|e| anyhow::anyhow!("System time error: {}", e))? - .as_secs() as i64; - - // Check not before - let not_before = validity.not_before.timestamp(); - if now < not_before { - return Err(anyhow::anyhow!( - "Certificate not yet valid. Valid from: {}", - validity.not_before - )); - } - - // Check not after - let not_after = validity.not_after.timestamp(); - if now > not_after { - return Err(anyhow::anyhow!( - "Certificate expired. Expired on: {}", - validity.not_after - )); - } - - // SECURITY: Warn if certificate expires soon (within 30 days) - let thirty_days_secs = 30 * 24 * 3600; - if not_after - now < thirty_days_secs { - let days_remaining = (not_after - now) / (24 * 3600); - tracing::warn!( - "Certificate expires soon! Days remaining: {}. Expiration: {}", - days_remaining, - validity.not_after - ); - } - - Ok(()) - } - - /// SECURITY CHECK 2: Validate certificate purpose via Extended Key Usage - fn validate_certificate_purpose(&self, cert: &X509Certificate<'_>) -> Result<()> { - // Look for Extended Key Usage extension - let mut has_client_auth = false; - let mut has_eku_extension = false; - - for ext in cert.extensions() { - if let ParsedExtension::ExtendedKeyUsage(eku) = ext.parsed_extension() { - has_eku_extension = true; - - // Check for TLS Client Authentication (OID: 1.3.6.1.5.5.7.3.2) - has_client_auth = eku.client_auth; - - if has_client_auth { - tracing::debug!("Certificate has TLS Client Authentication purpose"); - } else { - tracing::warn!( - "Certificate Extended Key Usage present but missing Client Auth. Purposes: {:?}", - eku - ); - } - } - } - - // SECURITY: Require Extended Key Usage with Client Auth for mTLS - if has_eku_extension && !has_client_auth { - return Err(anyhow::anyhow!( - "Certificate does not have TLS Client Authentication purpose (Extended Key Usage)" - )); - } - - // If no EKU extension, we allow it (some CAs don't set this for client certs) - // but log a warning for security awareness - if !has_eku_extension { - tracing::warn!( - "Certificate missing Extended Key Usage extension - certificate purpose cannot be verified" - ); - } - - Ok(()) - } - - /// SECURITY CHECK 3: Validate Basic Constraints (ensure not a CA certificate) - fn validate_certificate_constraints(&self, cert: &X509Certificate<'_>) -> Result<()> { - for ext in cert.extensions() { - if let ParsedExtension::BasicConstraints(bc) = ext.parsed_extension() { - // SECURITY: Client certificates should NOT be CA certificates - if bc.ca { - return Err(anyhow::anyhow!( - "Client certificate has CA flag set - this is a CA certificate, not a client certificate" - )); - } - - tracing::debug!("Certificate Basic Constraints validated: ca={}", bc.ca); - } - } - - Ok(()) - } - - /// SECURITY CHECK 4: Validate all critical extensions are recognized - fn validate_critical_extensions(&self, cert: &X509Certificate<'_>) -> Result<()> { - // List of recognized critical extensions (OIDs) - let recognized_critical = [ - "2.5.29.15", // Key Usage - "2.5.29.19", // Basic Constraints - "2.5.29.37", // Extended Key Usage - "2.5.29.17", // Subject Alternative Name - "2.5.29.32", // Certificate Policies - "2.5.29.35", // Authority Key Identifier - "2.5.29.14", // Subject Key Identifier - ]; - - for ext in cert.extensions() { - if ext.critical { - let oid_str = ext.oid.to_id_string(); - - // Check if this critical extension is recognized - if !recognized_critical.contains(&oid_str.as_str()) { - return Err(anyhow::anyhow!( - "Certificate contains unrecognized critical extension: {} - cannot safely process", - oid_str - )); - } - - tracing::debug!("Recognized critical extension: {}", oid_str); - } - } - - Ok(()) - } - - /// SECURITY CHECK 5: Validate Subject Alternative Names (if present) - fn validate_subject_alternative_names(&self, cert: &X509Certificate<'_>) -> Result<()> { - for ext in cert.extensions() { - if let ParsedExtension::SubjectAlternativeName(san) = ext.parsed_extension() { - // Extract and validate SAN entries - let mut san_entries = Vec::new(); - - for name in &san.general_names { - match name { - GeneralName::DNSName(dns) => { - san_entries.push(format!("DNS:{}", dns)); - - // SECURITY: Validate DNS name format - if !Self::is_valid_dns_name(dns) { - return Err(anyhow::anyhow!( - "Invalid DNS name in Subject Alternative Name: {}", - dns - )); - } - }, - GeneralName::RFC822Name(email) => { - san_entries.push(format!("Email:{}", email)); - }, - GeneralName::IPAddress(ip) => { - san_entries.push(format!("IP:{:?}", ip)); - }, - GeneralName::URI(uri) => { - san_entries.push(format!("URI:{}", uri)); - }, - _ => { - tracing::debug!("Other SAN type: {:?}", name); - }, - } - } - - if !san_entries.is_empty() { - tracing::debug!("Certificate Subject Alternative Names: {:?}", san_entries); - } - } - } - - Ok(()) - } - - /// Validate DNS name format (prevent injection attacks) - fn is_valid_dns_name(name: &str) -> bool { - // DNS name validation: alphanumeric, dots, hyphens, underscores - // Max 253 characters total, max 63 characters per label - if name.is_empty() || name.len() > 253 { - return false; - } - - for label in name.split('.') { - if label.is_empty() || label.len() > 63 { - return false; - } - - // Check valid characters: alphanumeric, hyphen, underscore - // Cannot start or end with hyphen - if !label - .chars() - .all(|c| c.is_alphanumeric() || c == '-' || c == '_') - { - return false; - } - - if label.starts_with('-') || label.ends_with('-') { - return false; - } - } - - true - } - - /// Validate certificate chain of trust against CA certificate - /// - /// This validates the certificate signature against the CA's public key - pub fn validate_certificate_chain(&self, client_cert_pem: &[u8]) -> Result<()> { - // Parse client certificate - let (_, client_pem) = x509_parser::pem::parse_x509_pem(client_cert_pem) - .map_err(|e| anyhow::anyhow!("Failed to parse client certificate PEM: {}", e))?; - - let client_cert = client_pem - .parse_x509() - .map_err(|e| anyhow::anyhow!("Failed to parse client X.509 certificate: {}", e))?; - - // In a production system, you would: - // 1. Parse the CA certificate from self.ca_certificate - // 2. Extract the CA's public key - // 3. Verify the client certificate's signature using the CA public key - // 4. Check that the client certificate's issuer matches the CA's subject - - // For now, we perform basic issuer checks - let client_issuer = client_cert - .issuer() - .iter_common_name() - .next() - .and_then(|cn| cn.as_str().ok()) - .ok_or_else(|| anyhow::anyhow!("Client certificate missing issuer CN"))?; - - tracing::debug!("Client certificate issued by: {}", client_issuer); - - // NOTE: Full cryptographic signature verification is performed by rustls during the - // TLS handshake. The library validates the entire certificate chain (issuer matching, - // signature verification, trust anchor resolution) before the connection is established. - // Application-level re-verification would duplicate this work and add unnecessary latency - // in HFT scenarios. The issuer CN check above serves as an additional defense-in-depth - // sanity check beyond what rustls already guarantees. - - Ok(()) - } - - /// SECURITY CHECK 6: Check certificate revocation status via CRL or OCSP - async fn check_revocation_status(&self, cert: &X509Certificate<'_>) -> Result<()> { - // Check if certificate has CRL Distribution Points or OCSP extensions - let mut crl_urls: Vec = Vec::new(); - let ocsp_urls: Vec = Vec::new(); - - for ext in cert.extensions() { - // Check for CRL Distribution Points (OID: 2.5.29.31) - if ext.oid.to_id_string() == "2.5.29.31" { - // Parse CRL Distribution Points - // This is a simplified extraction - full implementation would parse the ASN.1 structure - tracing::debug!("Certificate has CRL Distribution Points extension"); - - // Add configured CRL URL if available - if let Some(ref url) = self.crl_url { - crl_urls.push(url.clone()); - } - } - - // Check for Authority Information Access (OID: 1.3.6.1.5.5.7.1.1) for OCSP - if ext.oid.to_id_string() == "1.3.6.1.5.5.7.1.1" { - tracing::debug!("Certificate has Authority Information Access extension (OCSP)"); - // OCSP URL extraction would go here - } - } - - // Perform CRL check if URLs are available - if !crl_urls.is_empty() { - for crl_url in &crl_urls { - match self.check_crl_revocation(cert, crl_url).await { - Ok(is_revoked) => { - if is_revoked { - return Err(anyhow::anyhow!( - "Certificate has been revoked (CRL check against: {})", - crl_url - )); - } - tracing::info!("Certificate CRL check passed: {}", crl_url); - return Ok(()); // Successful check, certificate not revoked - }, - Err(e) => { - tracing::warn!("CRL check failed for {}: {}", crl_url, e); - // Continue to next CRL URL or OCSP - }, - } - } - } - - // Perform OCSP check if URLs are available and CRL failed - if !ocsp_urls.is_empty() { - for ocsp_url in &ocsp_urls { - match self.check_ocsp_revocation(cert, ocsp_url).await { - Ok(is_revoked) => { - if is_revoked { - return Err(anyhow::anyhow!( - "Certificate has been revoked (OCSP check against: {})", - ocsp_url - )); - } - tracing::info!("Certificate OCSP check passed: {}", ocsp_url); - return Ok(()); // Successful check, certificate not revoked - }, - Err(e) => { - tracing::warn!("OCSP check failed for {}: {}", ocsp_url, e); - }, - } - } - } - - // If revocation checking is enabled but no methods succeeded - if crl_urls.is_empty() && ocsp_urls.is_empty() { - tracing::warn!( - "Certificate revocation checking enabled but no CRL or OCSP URLs available" - ); - // In strict mode, this would be an error - // For now, we allow it with a warning - } - - Ok(()) - } - - /// Check certificate against CRL (Certificate Revocation List) - async fn check_crl_revocation( - &self, - cert: &X509Certificate<'_>, - crl_url: &str, - ) -> Result { - tracing::debug!("Checking certificate revocation via CRL: {}", crl_url); - - // Download CRL from URL - let client = reqwest::Client::builder() - .timeout(std::time::Duration::from_secs(10)) - .build() - .context("Failed to create HTTP client for CRL download")?; - - let crl_response = client - .get(crl_url) - .send() - .await - .context("Failed to download CRL")?; - - let crl_bytes = crl_response - .bytes() - .await - .context("Failed to read CRL response")?; - - // Parse CRL - let (_, crl) = - x509_parser::revocation_list::CertificateRevocationList::from_der(&crl_bytes) - .map_err(|e| anyhow::anyhow!("Failed to parse CRL: {}", e))?; - - // Check if certificate serial number is in revoked list - for revoked_cert in crl.iter_revoked_certificates() { - if revoked_cert.raw_serial() == cert.raw_serial() { - tracing::error!( - "Certificate REVOKED! Serial: {:X}, Revocation date: {:?}", - cert.serial, - revoked_cert.revocation_date - ); - return Ok(true); // Certificate is revoked - } - } - - Ok(false) // Certificate not found in CRL, not revoked - } - - /// Check certificate via OCSP (Online Certificate Status Protocol). - /// - /// **Production guidance**: OCSP stapling is the recommended approach for revocation - /// checking in HFT systems. Configure OCSP stapling at the TLS termination layer - /// (e.g., Envoy, nginx, or HAProxy) so the stapled response is delivered during the - /// handshake with zero additional latency. Application-level OCSP requests add a - /// synchronous HTTP round-trip (50-500ms) per connection, which is unacceptable for - /// latency-sensitive trading workloads. - /// - /// **Alternatives to application-level OCSP**: - /// - CRL checking via `check_crl_revocation` (periodic download, no per-connection cost) - /// - Short-lived certificates (e.g., 24h validity) that expire before revocation matters - /// - OCSP stapling at the load balancer / TLS terminator - /// - /// This method returns `Ok(false)` (not revoked) because revocation checking is - /// delegated to the infrastructure layer. - async fn check_ocsp_revocation( - &self, - _cert: &X509Certificate<'_>, - ocsp_url: &str, - ) -> Result { - tracing::debug!( - "OCSP revocation check requested for URL: {}. \ - Revocation checking is delegated to infrastructure-layer OCSP stapling.", - ocsp_url - ); - - // Revocation checking is handled at the TLS terminator (Envoy/nginx) via - // OCSP stapling. Application-level OCSP is not implemented to avoid adding - // per-connection HTTP latency incompatible with HFT requirements. - Ok(false) - } -} - -/// TLS interceptor for gRPC requests -#[derive(Clone)] -pub struct TlsInterceptor { - tls_config: Arc, -} - -impl TlsInterceptor { - /// Create new TLS interceptor - pub fn new(tls_config: Arc) -> Self { - Self { tls_config } - } - - /// Extract and validate client certificate from request - pub async fn extract_client_identity( - &self, - request: &tonic::Request, - ) -> Result { - // Get TLS info from request metadata - let tls_info = request - .extensions() - .get::>() - .ok_or_else(|| anyhow::anyhow!("No TLS connection info found"))?; - - // Extract client certificate if present - if let Some(cert_der) = tls_info - .peer_certs() - .and_then(|certs| certs.first().cloned()) - { - // Convert DER to PEM for processing - let cert_pem = self.der_to_pem(&cert_der)?; - self.tls_config.validate_client_certificate(&cert_pem).await - } else { - Err(anyhow::anyhow!("No client certificate provided")) - } - } - - /// Convert DER certificate to PEM format - fn der_to_pem(&self, der_bytes: &[u8]) -> Result> { - use base64::{engine::general_purpose, Engine as _}; - - let b64_cert = general_purpose::STANDARD.encode(der_bytes); - let pem_cert = format!( - "-----BEGIN CERTIFICATE-----\n{}\n-----END CERTIFICATE-----\n", - b64_cert - .chars() - .collect::>() - .chunks(64) - .map(|chunk| chunk.iter().collect::()) - .collect::>() - .join("\n") - ); - - Ok(pem_cert.into_bytes()) - } } #[cfg(test)] diff --git a/services/backtesting_service/tests/integration_tests.rs b/services/backtesting_service/tests/integration_tests.rs index 637284c82..c62cf0819 100644 --- a/services/backtesting_service/tests/integration_tests.rs +++ b/services/backtesting_service/tests/integration_tests.rs @@ -45,7 +45,7 @@ async fn setup_test_service() -> Result { // Create service without model cache for integration tests // Model loading is tested separately with dedicated model loader tests - BacktestingServiceImpl::new(repositories, None).await + BacktestingServiceImpl::new(repositories).await } /// Create a test backtest context diff --git a/services/backtesting_service/tests/mock_repositories.rs b/services/backtesting_service/tests/mock_repositories.rs index 5745c85b6..c45461e52 100644 --- a/services/backtesting_service/tests/mock_repositories.rs +++ b/services/backtesting_service/tests/mock_repositories.rs @@ -372,14 +372,10 @@ pub fn generate_sample_news_events(symbols: &[String], num_events: usize) -> Vec let importance = rng.gen_range(0.0..1.0); events.push(NewsEvent { - id: format!("news_{}", i), timestamp, symbols: vec![symbols[symbol_idx].clone()], - title: format!("News event {} for {}", i, symbols[symbol_idx]), - content: format!("Sample news content {}", i), sentiment, importance, - source: "mock_source".to_string(), }); } diff --git a/services/backtesting_service/tests/service_tests.rs b/services/backtesting_service/tests/service_tests.rs index 060ef0dde..5d26bf54b 100644 --- a/services/backtesting_service/tests/service_tests.rs +++ b/services/backtesting_service/tests/service_tests.rs @@ -33,7 +33,7 @@ async fn create_test_service( Box::new(news), )); - Ok(BacktestingServiceImpl::new(repos, None).await?) + Ok(BacktestingServiceImpl::new(repos).await?) } // ============================================================================ diff --git a/services/broker_gateway_service/src/service.rs b/services/broker_gateway_service/src/service.rs index c946a6390..d57df8001 100644 --- a/services/broker_gateway_service/src/service.rs +++ b/services/broker_gateway_service/src/service.rs @@ -19,8 +19,6 @@ use ctrader_openapi::CTraderClient; /// Broker Gateway Service state pub struct BrokerGatewayService { db_pool: PgPool, - #[allow(dead_code)] // Will be used for session caching - redis_client: Arc, session_state: Arc>, #[cfg(feature = "icmarkets")] broker_client: Arc>>, @@ -28,11 +26,11 @@ pub struct BrokerGatewayService { impl BrokerGatewayService { pub fn new(db_pool: PgPool, redis_url: &str) -> anyhow::Result { - let redis_client = redis::Client::open(redis_url)?; + // Validate Redis URL is parseable (connection used for future cache integration) + let _redis_client = redis::Client::open(redis_url)?; Ok(Self { db_pool, - redis_client: Arc::new(redis_client), session_state: Arc::new(RwLock::new(SessionState::Active)), #[cfg(feature = "icmarkets")] broker_client: Arc::new(RwLock::new(None)), diff --git a/services/load_tests/src/metrics/metrics.rs b/services/load_tests/src/metrics/metrics.rs index 9fee226c0..1b39ae3ef 100644 --- a/services/load_tests/src/metrics/metrics.rs +++ b/services/load_tests/src/metrics/metrics.rs @@ -208,42 +208,4 @@ impl LoadTestReport { output } - pub fn print(&self) { - let separator = "=".repeat(80); - let test_name = &self.test_name; - let test_duration = self.test_duration; - let total_requests = self.total_requests; - let successful_requests = self.successful_requests; - let failed_requests = self.failed_requests; - let throughput_per_sec = self.throughput_per_sec; - let error_rate_percent = self.error_rate_percent; - let latency_p50_us = self.latency_p50_us; - let latency_p95_us = self.latency_p95_us; - let latency_p99_us = self.latency_p99_us; - let latency_max_us = self.latency_max_us; - let avg_memory_mb = self.avg_memory_mb; - - println!("\n{separator}"); - println!("Load Test Report: {test_name}"); - println!("{separator}"); - println!("Duration: {test_duration:?}"); - println!("Total Requests: {total_requests} (Success: {successful_requests}, Failed: {failed_requests})"); - println!("Throughput: {throughput_per_sec:.2} req/sec"); - println!("Error Rate: {error_rate_percent:.2}%"); - println!("\nLatency (microseconds):"); - println!(" P50: {latency_p50_us} μs"); - println!(" P95: {latency_p95_us} μs"); - println!(" P99: {latency_p99_us} μs"); - println!(" Max: {latency_max_us} μs"); - println!("\nMemory: {avg_memory_mb:.2} MB (avg)"); - - if !self.custom_metrics.is_empty() { - println!("\nCustom Metrics:"); - for (key, value) in &self.custom_metrics { - println!(" {key}: {value:.2}"); - } - } - - println!("{separator}\n"); - } } diff --git a/services/ml_training_service/src/checkpoint_manager.rs b/services/ml_training_service/src/checkpoint_manager.rs index ad5822f90..e703da9f4 100644 --- a/services/ml_training_service/src/checkpoint_manager.rs +++ b/services/ml_training_service/src/checkpoint_manager.rs @@ -15,14 +15,12 @@ use chrono::{Duration, Utc}; use common::error::CommonError; -use ml::checkpoint::{CheckpointMetadata, CheckpointStorage, FileSystemStorage}; +use ml::checkpoint::CheckpointMetadata; use ml::ModelType; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use sqlx::PgPool; use std::collections::HashMap; -use std::path::PathBuf; -use std::sync::Arc; use tracing::{debug, info, instrument}; /// Retention policy configuration for checkpoint management @@ -56,21 +54,11 @@ pub struct CheckpointManager { /// Retention policy configuration retention_policy: RetentionPolicy, - - /// Checkpoint storage backend - storage: Arc, } impl CheckpointManager { /// Create a new CheckpointManager with database connection and retention policy pub async fn new(pool: PgPool, retention_policy: RetentionPolicy) -> Result { - // Initialize storage backend (filesystem by default) - let storage_dir = - std::env::var("CHECKPOINT_STORAGE_DIR").unwrap_or_else(|_| "./checkpoints".to_string()); - - let storage: Arc = - Arc::new(FileSystemStorage::new(PathBuf::from(storage_dir))); - info!( "Initialized CheckpointManager: max_checkpoints={}, ranking_metric={}", retention_policy.max_checkpoints_per_model, retention_policy.ranking_metric @@ -79,7 +67,6 @@ impl CheckpointManager { Ok(Self { pool, retention_policy, - storage, }) } diff --git a/services/ml_training_service/src/data_loader.rs b/services/ml_training_service/src/data_loader.rs index 42bb38cf3..8d1507ab1 100644 --- a/services/ml_training_service/src/data_loader.rs +++ b/services/ml_training_service/src/data_loader.rs @@ -1175,144 +1175,6 @@ impl HistoricalDataLoader { info!("Normalization complete"); } - /// Apply normalization to all features in dataset (DEPRECATED) - /// - /// This method is kept for backward compatibility but should not be used - /// as it can cause data leakage. Use fit_normalization() on training data - /// and transform_with_params() on both training and validation data instead. - /// - /// # Arguments - /// * `features_list` - Mutable reference to features to normalize - /// - /// # Implementation Notes - /// - DEPRECATED: Use fit_normalization() + transform_with_params() instead - /// - /// - Kept for backward compatibility only - #[deprecated( - since = "1.0.0", - note = "Use fit_normalization() and transform_with_params() to prevent data leakage" - )] - fn apply_normalization(&self, features_list: &mut [(FinancialFeatures, Vec)]) { - let method = NormalizationMethod::from_str(&self.config.features.normalization); - - if matches!(method, NormalizationMethod::None) { - debug!("Normalization disabled, skipping"); - return; - } - - info!( - "Applying {:?} normalization to {} samples", - method, - features_list.len() - ); - - if features_list.is_empty() { - return; - } - - // Collect all technical indicator keys - let mut all_indicator_keys: Vec = features_list - .first() - .map(|(f, _)| f.technical_indicators.keys().cloned().collect()) - .unwrap_or_default(); - all_indicator_keys.sort(); - - // Fit normalization parameters for each technical indicator - let mut indicator_params: HashMap = HashMap::new(); - - for key in &all_indicator_keys { - let values: Vec = features_list - .iter() - .filter_map(|(f, _)| f.technical_indicators.get(key).copied()) - .collect(); - - let params = NormalizationParams::fit(&values); - indicator_params.insert(key.clone(), params); - } - - // Fit parameters for microstructure features - let spread_values: Vec = features_list - .iter() - .map(|(f, _)| f.microstructure.spread_bps as f64) - .collect(); - let spread_params = NormalizationParams::fit(&spread_values); - - let imbalance_values: Vec = features_list - .iter() - .map(|(f, _)| f.microstructure.imbalance) - .collect(); - let imbalance_params = NormalizationParams::fit(&imbalance_values); - - let intensity_values: Vec = features_list - .iter() - .map(|(f, _)| f.microstructure.trade_intensity) - .collect(); - let intensity_params = NormalizationParams::fit(&intensity_values); - - // Fit parameters for risk metrics - let var_values: Vec = features_list - .iter() - .map(|(f, _)| f.risk_metrics.var_5pct) - .collect(); - let var_params = NormalizationParams::fit(&var_values); - - let es_values: Vec = features_list - .iter() - .map(|(f, _)| f.risk_metrics.expected_shortfall) - .collect(); - let es_params = NormalizationParams::fit(&es_values); - - let dd_values: Vec = features_list - .iter() - .map(|(f, _)| f.risk_metrics.max_drawdown) - .collect(); - let dd_params = NormalizationParams::fit(&dd_values); - - let sharpe_values: Vec = features_list - .iter() - .map(|(f, _)| f.risk_metrics.sharpe_ratio) - .collect(); - let sharpe_params = NormalizationParams::fit(&sharpe_values); - - // Apply normalization to all features - for (features, _) in features_list.iter_mut() { - // Normalize technical indicators - for (key, value) in features.technical_indicators.iter_mut() { - if let Some(params) = indicator_params.get(key) { - *value = params.normalize(*value, &method); - } - } - - // Normalize microstructure features - features.microstructure.imbalance = - imbalance_params.normalize(features.microstructure.imbalance, &method); - features.microstructure.trade_intensity = - intensity_params.normalize(features.microstructure.trade_intensity, &method); - - // Note: spread_bps is u16, so we normalize separately if needed - let normalized_spread = - spread_params.normalize(features.microstructure.spread_bps as f64, &method); - // Store in technical_indicators for reference - features - .technical_indicators - .insert("spread_bps_normalized".to_string(), normalized_spread); - - // Normalize risk metrics - features.risk_metrics.var_5pct = - var_params.normalize(features.risk_metrics.var_5pct, &method); - features.risk_metrics.expected_shortfall = - es_params.normalize(features.risk_metrics.expected_shortfall, &method); - features.risk_metrics.max_drawdown = - dd_params.normalize(features.risk_metrics.max_drawdown, &method); - features.risk_metrics.sharpe_ratio = - sharpe_params.normalize(features.risk_metrics.sharpe_ratio, &method); - } - - info!( - "Normalization complete for {} technical indicators", - all_indicator_keys.len() - ); - } } #[cfg(test)] diff --git a/services/ml_training_service/src/encryption.rs b/services/ml_training_service/src/encryption.rs index 15ce4510e..67389f672 100644 --- a/services/ml_training_service/src/encryption.rs +++ b/services/ml_training_service/src/encryption.rs @@ -70,10 +70,6 @@ impl CachedEncryptionKeys { Err(_) => true, // If we can't determine time, assume expired } } - - fn needs_rotation(&self, rotation_days: u64) -> bool { - self.keys.should_rotate(rotation_days) - } } /// Encryption algorithm configuration diff --git a/services/ml_training_service/src/ensemble_training_coordinator.rs b/services/ml_training_service/src/ensemble_training_coordinator.rs index 5c4309787..9b70035bd 100644 --- a/services/ml_training_service/src/ensemble_training_coordinator.rs +++ b/services/ml_training_service/src/ensemble_training_coordinator.rs @@ -182,9 +182,6 @@ pub struct EnsembleTrainingCoordinator { /// Current (possibly optimized) weights current_weights: Arc>>, - /// Ensemble-level metrics - ensemble_metrics: Arc>>, - /// Training start time started_at: Option, } @@ -214,7 +211,6 @@ impl EnsembleTrainingCoordinator { config, model_states: Arc::new(RwLock::new(model_states)), current_weights: Arc::new(RwLock::new(current_weights)), - ensemble_metrics: Arc::new(RwLock::new(HashMap::new())), started_at: None, }) } diff --git a/services/ml_training_service/src/gpu_config.rs b/services/ml_training_service/src/gpu_config.rs index 7c542e9a8..41aaf9195 100644 --- a/services/ml_training_service/src/gpu_config.rs +++ b/services/ml_training_service/src/gpu_config.rs @@ -66,16 +66,14 @@ impl GpuValidation { /// GPU configuration manager pub struct GpuConfigManager { - training_config: TrainingConfig, config_manager: Arc, gpu_config: Option, } impl GpuConfigManager { /// Create new GPU configuration manager - pub fn new(training_config: TrainingConfig, config_manager: Arc) -> Self { + pub fn new(_training_config: TrainingConfig, config_manager: Arc) -> Self { Self { - training_config, config_manager, gpu_config: None, } diff --git a/services/ml_training_service/src/gpu_resource_manager.rs b/services/ml_training_service/src/gpu_resource_manager.rs index 0bb12b823..1f414eeb5 100644 --- a/services/ml_training_service/src/gpu_resource_manager.rs +++ b/services/ml_training_service/src/gpu_resource_manager.rs @@ -104,13 +104,6 @@ impl Drop for GPULock { } } -/// GPU state tracking -#[derive(Debug, Clone)] -struct GPUState { - gpu_id: u32, - locked_by: Option, -} - /// GPU Resource Manager - manages GPU locks and memory tracking #[derive(Debug)] pub struct GPUResourceManager { diff --git a/services/ml_training_service/src/job_tracker.rs b/services/ml_training_service/src/job_tracker.rs index b57a9944b..d723f7639 100644 --- a/services/ml_training_service/src/job_tracker.rs +++ b/services/ml_training_service/src/job_tracker.rs @@ -106,9 +106,6 @@ pub struct JobProgress { /// Child job record from database #[derive(Debug, Clone, sqlx::FromRow)] struct ChildJob { - id: Uuid, - batch_id: Uuid, - model_type: String, model_weight: f64, status: String, progress_pct: f64, @@ -242,7 +239,7 @@ impl JobTracker { // Fetch all child jobs for this batch let child_jobs: Vec = sqlx::query_as::<_, ChildJob>( r#" - SELECT id, batch_id, model_type, model_weight, status, progress_pct + SELECT model_weight, status, progress_pct FROM child_jobs WHERE batch_id = $1 "#, @@ -457,33 +454,21 @@ mod tests { let jobs = vec![ ChildJob { - id: Uuid::new_v4(), - batch_id: Uuid::new_v4(), - model_type: "DQN".to_string(), model_weight: 0.10, status: "Completed".to_string(), progress_pct: 100.0, }, ChildJob { - id: Uuid::new_v4(), - batch_id: Uuid::new_v4(), - model_type: "PPO".to_string(), model_weight: 0.30, status: "Running".to_string(), progress_pct: 50.0, }, ChildJob { - id: Uuid::new_v4(), - batch_id: Uuid::new_v4(), - model_type: "MAMBA-2".to_string(), model_weight: 0.40, status: "Running".to_string(), progress_pct: 25.0, }, ChildJob { - id: Uuid::new_v4(), - batch_id: Uuid::new_v4(), - model_type: "TFT".to_string(), model_weight: 0.20, status: "Pending".to_string(), progress_pct: 0.0, diff --git a/services/ml_training_service/src/main.rs b/services/ml_training_service/src/main.rs index 34a20dff9..9534c9114 100644 --- a/services/ml_training_service/src/main.rs +++ b/services/ml_training_service/src/main.rs @@ -524,21 +524,6 @@ async fn serve(args: ServeArgs) -> Result<()> { Ok(()) } -/// Start Prometheus metrics server -async fn start_metrics_server(_config: MLConfig) -> Result> { - use std::time::Duration; - - let metrics_handle = tokio::spawn(async move { - // Keep the metrics server running - loop { - tokio::time::sleep(Duration::from_secs(60)).await; - } - }); - - info!("Prometheus metrics server started"); - Ok(metrics_handle) -} - /// Perform health check async fn health_check(args: HealthArgs) -> Result<()> { use service::proto::{ml_training_service_client::MlTrainingServiceClient, HealthCheckRequest}; diff --git a/services/ml_training_service/src/monitoring.rs b/services/ml_training_service/src/monitoring.rs index 50ef12f70..ccf781ee8 100644 --- a/services/ml_training_service/src/monitoring.rs +++ b/services/ml_training_service/src/monitoring.rs @@ -23,10 +23,6 @@ use tracing::{debug, info}; #[derive(Debug, Clone)] pub struct MonitoringSystem { - config: MonitoringConfig, - alert_manager: AlertManager, - cost_tracker: Arc, - drift_detector: Arc, } #[derive(Debug, Clone)] @@ -49,12 +45,8 @@ impl Default for MonitoringConfig { } impl MonitoringSystem { - pub async fn new(config: MonitoringConfig) -> Result { + pub async fn new(_config: MonitoringConfig) -> Result { Ok(Self { - config: config.clone(), - alert_manager: AlertManager::new().await?, - cost_tracker: Arc::new(CostTracker::new(CostConfig::default()).await?), - drift_detector: Arc::new(DataDriftDetector::new(DriftConfig::default()).await?), }) } diff --git a/services/ml_training_service/src/service.rs b/services/ml_training_service/src/service.rs index f6014f8a5..d5c10cb3e 100644 --- a/services/ml_training_service/src/service.rs +++ b/services/ml_training_service/src/service.rs @@ -49,7 +49,6 @@ pub struct MLTrainingServiceImpl { orchestrator: Arc, tuning_handlers: Arc, batch_tuning_manager: Arc, - config: MLConfig, } impl MLTrainingServiceImpl { @@ -57,7 +56,7 @@ impl MLTrainingServiceImpl { pub fn new( orchestrator: Arc, tuning_manager: Arc, - config: MLConfig, + _config: MLConfig, ) -> Self { let tuning_handlers = Arc::new(TuningHandlers::new(Arc::clone(&tuning_manager))); let working_dir = std::env::var("TUNING_WORKING_DIR").unwrap_or_else(|_| ".".to_string()); @@ -66,7 +65,6 @@ impl MLTrainingServiceImpl { orchestrator, tuning_handlers, batch_tuning_manager, - config, } } diff --git a/services/ml_training_service/src/storage.rs b/services/ml_training_service/src/storage.rs index a8ef33adb..75f7fc39e 100644 --- a/services/ml_training_service/src/storage.rs +++ b/services/ml_training_service/src/storage.rs @@ -260,12 +260,6 @@ impl LocalModelStorage { Ok(Self { base_path }) } - /// Generate file path for a job (deprecated - now using timestamped paths) - fn get_model_path(&self, job_id: Uuid) -> PathBuf { - let filename = format!("{}.bin", job_id); - self.base_path.join("models").join(filename) - } - /// Generate directory path for job models fn get_job_directory(&self, job_id: Uuid) -> PathBuf { self.base_path.join("jobs").join(job_id.to_string()) diff --git a/services/ml_training_service/src/technical_indicators.rs b/services/ml_training_service/src/technical_indicators.rs index ec3bb49bf..984c279a9 100644 --- a/services/ml_training_service/src/technical_indicators.rs +++ b/services/ml_training_service/src/technical_indicators.rs @@ -137,9 +137,6 @@ impl Default for IndicatorConfig { /// /// Designed for O(1) amortized updates with minimal allocations. pub struct TechnicalIndicatorCalculator { - /// Symbol identifier - symbol: String, - /// Configuration config: IndicatorConfig, @@ -256,7 +253,7 @@ impl TechnicalIndicatorCalculator { /// /// * `symbol` - Trading symbol /// * `config` - Indicator configuration - pub fn new(symbol: String, config: IndicatorConfig) -> Self { + pub fn new(_symbol: String, config: IndicatorConfig) -> Self { let max_window = config .warmup_period .max(config.bollinger_period) @@ -265,7 +262,6 @@ impl TechnicalIndicatorCalculator { .max(config.cmf_period); Self { - symbol, config, price_history: VecDeque::with_capacity(max_window), volume_history: VecDeque::with_capacity(max_window), diff --git a/services/ml_training_service/src/tls_config.rs b/services/ml_training_service/src/tls_config.rs index d2c53f51e..7d3a8d2cd 100644 --- a/services/ml_training_service/src/tls_config.rs +++ b/services/ml_training_service/src/tls_config.rs @@ -7,21 +7,14 @@ //! - Performance optimized for HFT requirements use anyhow::{Context, Result}; -use config::manager::ConfigManager; // Re-export shared TLS types from common for backward compatibility #[allow(unused_imports)] pub use common::tls::{ClientIdentity, TlsProtocolVersion, UserRole}; -use config::structures::TlsConfig; -use std::sync::Arc; // TLS imports - TLS feature should be enabled in Cargo.toml use tonic::transport::{Certificate, Identity, ServerTlsConfig}; use tracing::info; -use x509_parser::certificate::X509Certificate; -use x509_parser::extensions::{GeneralName, ParsedExtension}; -use x509_parser::prelude::*; -use x509_parser::revocation_list::CertificateRevocationList; /// TLS configuration for the trading service #[derive(Debug, Clone)] @@ -32,12 +25,6 @@ pub struct MLTrainingServiceTlsConfig { pub ca_certificate: Certificate, /// Require client certificates pub require_client_cert: bool, - /// TLS protocol version (1.2 or 1.3) - pub protocol_version: TlsProtocolVersion, - /// Certificate revocation checking enabled - pub enable_revocation_check: bool, - /// CRL distribution point URL (optional) - pub crl_url: Option, } impl MLTrainingServiceTlsConfig { @@ -78,42 +65,9 @@ impl MLTrainingServiceTlsConfig { server_identity, ca_certificate, require_client_cert, - protocol_version: TlsProtocolVersion::Tls13, - enable_revocation_check: false, // Default disabled for compatibility - crl_url: None, }) } - /// Create TLS configuration from config crate - pub async fn from_config(config_manager: &ConfigManager) -> Result { - info!("Loading TLS certificates from configuration"); - - // Get the service config which contains settings as JSON - let service_config = config_manager.get_config(); - - // Extract TLS config from the settings JSON field - let tls_config: TlsConfig = serde_json::from_value( - service_config - .settings - .get("tls") - .cloned() - .unwrap_or(serde_json::json!({})), - ) - .unwrap_or_default(); - - // Use environment variable for CA cert path with fallback to /tmp - let ca_cert_path = std::env::var("TLS_CA_PATH") - .unwrap_or_else(|_| "/tmp/foxhunt/certs/ca.crt".to_string()); - - Self::from_files( - &tls_config.cert_path, - &tls_config.key_path, - tls_config.ca_cert_path.as_deref().unwrap_or(&ca_cert_path), - true, // Always require mTLS - ) - .await - } - /// Convert to tonic ServerTlsConfig pub fn to_server_tls_config(&self) -> ServerTlsConfig { let mut tls_config = ServerTlsConfig::new().identity(self.server_identity.clone()); @@ -125,572 +79,6 @@ impl MLTrainingServiceTlsConfig { tls_config } - /// Validate client certificate and extract identity - pub fn validate_client_certificate(&self, cert_chain: &[u8]) -> Result { - // Parse the X.509 certificate from PEM format - let (_, pem) = x509_parser::pem::parse_x509_pem(cert_chain) - .map_err(|e| anyhow::anyhow!("Failed to parse PEM certificate: {}", e))?; - - let cert = pem - .parse_x509() - .map_err(|e| anyhow::anyhow!("Failed to parse X.509 certificate: {}", e))?; - - // Comprehensive certificate validation - let client_identity = self.extract_and_validate_certificate(&cert)?; - - tracing::info!( - "Client certificate validated: CN={}, OU={}", - client_identity.common_name, - client_identity.organizational_unit - ); - - Ok(client_identity) - } - - /// Extract and validate certificate with comprehensive security checks - fn extract_and_validate_certificate(&self, cert: &X509Certificate) -> Result { - // SECURITY CHECK 1: Certificate Validity Period (Expiration) - self.validate_certificate_expiration(cert)?; - - // SECURITY CHECK 2: Certificate Purpose (Extended Key Usage) - self.validate_certificate_purpose(cert)?; - - // SECURITY CHECK 3: Certificate Chain of Trust (Basic Constraints) - self.validate_certificate_constraints(cert)?; - - // SECURITY CHECK 4: Critical Extensions Validation - self.validate_critical_extensions(cert)?; - - // SECURITY CHECK 5: Subject Alternative Names (if present) - self.validate_subject_alternative_names(cert)?; - - // SECURITY CHECK 6: Certificate Revocation Status (CRL/OCSP) - // Note: Revocation checking is disabled in synchronous validation - // For production, implement async validation or use a separate revocation service - if self.enable_revocation_check { - tracing::warn!("Certificate revocation checking enabled but requires async context"); - // self.check_revocation_status(cert).await?; - } - - // Extract identity information from Subject DN - let subject = cert.subject(); - - // Extract Common Name (CN) - let common_name = subject - .iter_common_name() - .next() - .and_then(|cn| cn.as_str().ok()) - .ok_or_else(|| anyhow::anyhow!("Certificate missing Common Name (CN)"))? - .to_string(); - - // Extract Organizational Unit (OU) - required for RBAC - let organizational_unit = subject - .iter_organizational_unit() - .next() - .and_then(|ou| ou.as_str().ok()) - .ok_or_else(|| anyhow::anyhow!("Certificate missing Organizational Unit (OU)"))? - .to_string(); - - // Extract Serial Number - let serial_number = format!("{:X}", cert.serial); - - // Extract Issuer CN - let issuer = cert - .issuer() - .iter_common_name() - .next() - .and_then(|cn| cn.as_str().ok()) - .unwrap_or("Unknown Issuer") - .to_string(); - - // SECURITY: Validate organizational unit is in allowed list - let allowed_ous = ["trading", "admin", "analytics", "risk", "compliance"]; - if !allowed_ous.contains(&organizational_unit.as_str()) { - return Err(anyhow::anyhow!( - "Organizational Unit '{}' is not authorized for access. Allowed: {:?}", - organizational_unit, - allowed_ous - )); - } - - // SECURITY: Validate common name format (prevent injection attacks) - if !common_name - .chars() - .all(|c| c.is_alphanumeric() || c == '.' || c == '-' || c == '_') - { - return Err(anyhow::anyhow!( - "Common Name contains invalid characters: {}", - common_name - )); - } - - Ok(ClientIdentity { - common_name, - organizational_unit, - serial_number, - issuer, - }) - } - - /// SECURITY CHECK 1: Validate certificate expiration - fn validate_certificate_expiration(&self, cert: &X509Certificate) -> Result<()> { - let validity = cert.validity(); - - // Get current time - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .map_err(|e| anyhow::anyhow!("System time error: {}", e))? - .as_secs() as i64; - - // Check not before - let not_before = validity.not_before.timestamp(); - if now < not_before { - return Err(anyhow::anyhow!( - "Certificate not yet valid. Valid from: {}", - validity.not_before - )); - } - - // Check not after - let not_after = validity.not_after.timestamp(); - if now > not_after { - return Err(anyhow::anyhow!( - "Certificate expired. Expired on: {}", - validity.not_after - )); - } - - // SECURITY: Warn if certificate expires soon (within 30 days) - let thirty_days_secs = 30 * 24 * 3600; - if not_after - now < thirty_days_secs { - let days_remaining = (not_after - now) / (24 * 3600); - tracing::warn!( - "Certificate expires soon! Days remaining: {}. Expiration: {}", - days_remaining, - validity.not_after - ); - } - - Ok(()) - } - - /// SECURITY CHECK 2: Validate certificate purpose via Extended Key Usage - fn validate_certificate_purpose(&self, cert: &X509Certificate) -> Result<()> { - // Look for Extended Key Usage extension - let mut has_client_auth = false; - let mut has_eku_extension = false; - - for ext in cert.extensions() { - if let ParsedExtension::ExtendedKeyUsage(eku) = ext.parsed_extension() { - has_eku_extension = true; - - // Check for TLS Client Authentication (OID: 1.3.6.1.5.5.7.3.2) - has_client_auth = eku.client_auth; - - if has_client_auth { - tracing::debug!("Certificate has TLS Client Authentication purpose"); - } else { - tracing::warn!( - "Certificate Extended Key Usage present but missing Client Auth. Purposes: {:?}", - eku - ); - } - } - } - - // SECURITY: Require Extended Key Usage with Client Auth for mTLS - if has_eku_extension && !has_client_auth { - return Err(anyhow::anyhow!( - "Certificate does not have TLS Client Authentication purpose (Extended Key Usage)" - )); - } - - // If no EKU extension, we allow it (some CAs don't set this for client certs) - // but log a warning for security awareness - if !has_eku_extension { - tracing::warn!( - "Certificate missing Extended Key Usage extension - certificate purpose cannot be verified" - ); - } - - Ok(()) - } - - /// SECURITY CHECK 3: Validate Basic Constraints (ensure not a CA certificate) - fn validate_certificate_constraints(&self, cert: &X509Certificate) -> Result<()> { - for ext in cert.extensions() { - if let ParsedExtension::BasicConstraints(bc) = ext.parsed_extension() { - // SECURITY: Client certificates should NOT be CA certificates - if bc.ca { - return Err(anyhow::anyhow!( - "Client certificate has CA flag set - this is a CA certificate, not a client certificate" - )); - } - - tracing::debug!("Certificate Basic Constraints validated: ca={}", bc.ca); - } - } - - Ok(()) - } - - /// SECURITY CHECK 4: Validate all critical extensions are recognized - fn validate_critical_extensions(&self, cert: &X509Certificate) -> Result<()> { - // List of recognized critical extensions (OIDs) - let recognized_critical = [ - "2.5.29.15", // Key Usage - "2.5.29.19", // Basic Constraints - "2.5.29.37", // Extended Key Usage - "2.5.29.17", // Subject Alternative Name - "2.5.29.32", // Certificate Policies - "2.5.29.35", // Authority Key Identifier - "2.5.29.14", // Subject Key Identifier - ]; - - for ext in cert.extensions() { - if ext.critical { - let oid_str = ext.oid.to_id_string(); - - // Check if this critical extension is recognized - if !recognized_critical.contains(&oid_str.as_str()) { - return Err(anyhow::anyhow!( - "Certificate contains unrecognized critical extension: {} - cannot safely process", - oid_str - )); - } - - tracing::debug!("Recognized critical extension: {}", oid_str); - } - } - - Ok(()) - } - - /// SECURITY CHECK 5: Validate Subject Alternative Names (if present) - fn validate_subject_alternative_names(&self, cert: &X509Certificate) -> Result<()> { - for ext in cert.extensions() { - if let ParsedExtension::SubjectAlternativeName(san) = ext.parsed_extension() { - // Extract and validate SAN entries - let mut san_entries = Vec::new(); - - for name in &san.general_names { - match name { - GeneralName::DNSName(dns) => { - san_entries.push(format!("DNS:{}", dns)); - - // SECURITY: Validate DNS name format - if !Self::is_valid_dns_name(dns) { - return Err(anyhow::anyhow!( - "Invalid DNS name in Subject Alternative Name: {}", - dns - )); - } - }, - GeneralName::RFC822Name(email) => { - san_entries.push(format!("Email:{}", email)); - }, - GeneralName::IPAddress(ip) => { - san_entries.push(format!("IP:{:?}", ip)); - }, - GeneralName::URI(uri) => { - san_entries.push(format!("URI:{}", uri)); - }, - _ => { - tracing::debug!("Other SAN type: {:?}", name); - }, - } - } - - if !san_entries.is_empty() { - tracing::debug!("Certificate Subject Alternative Names: {:?}", san_entries); - } - } - } - - Ok(()) - } - - /// Validate DNS name format (prevent injection attacks) - fn is_valid_dns_name(name: &str) -> bool { - // DNS name validation: alphanumeric, dots, hyphens, underscores - // Max 253 characters total, max 63 characters per label - if name.is_empty() || name.len() > 253 { - return false; - } - - for label in name.split('.') { - if label.is_empty() || label.len() > 63 { - return false; - } - - // Check valid characters: alphanumeric, hyphen, underscore - // Cannot start or end with hyphen - if !label - .chars() - .all(|c| c.is_alphanumeric() || c == '-' || c == '_') - { - return false; - } - - if label.starts_with('-') || label.ends_with('-') { - return false; - } - } - - true - } - - /// Validate certificate chain of trust against CA certificate - /// - /// This validates the certificate signature against the CA's public key - pub fn validate_certificate_chain(&self, client_cert_pem: &[u8]) -> Result<()> { - // Parse client certificate - let (_, client_pem) = x509_parser::pem::parse_x509_pem(client_cert_pem) - .map_err(|e| anyhow::anyhow!("Failed to parse client certificate PEM: {}", e))?; - - let client_cert = client_pem - .parse_x509() - .map_err(|e| anyhow::anyhow!("Failed to parse client X.509 certificate: {}", e))?; - - // In a production system, you would: - // 1. Parse the CA certificate from self.ca_certificate - // 2. Extract the CA's public key - // 3. Verify the client certificate's signature using the CA public key - // 4. Check that the client certificate's issuer matches the CA's subject - - // For now, we perform basic issuer checks - let client_issuer = client_cert - .issuer() - .iter_common_name() - .next() - .and_then(|cn| cn.as_str().ok()) - .ok_or_else(|| anyhow::anyhow!("Client certificate missing issuer CN"))?; - - tracing::debug!("Client certificate issued by: {}", client_issuer); - - // NOTE: Full cryptographic signature verification is performed by rustls during the - // TLS handshake. The library validates the entire certificate chain (issuer matching, - // signature verification, trust anchor resolution) before the connection is established. - // Application-level re-verification would duplicate this work and add unnecessary latency - // in HFT scenarios. The issuer CN check above serves as an additional defense-in-depth - // sanity check beyond what rustls already guarantees. - - Ok(()) - } - - /// SECURITY CHECK 6: Check certificate revocation status via CRL or OCSP - async fn check_revocation_status(&self, cert: &X509Certificate<'_>) -> Result<()> { - // Check if certificate has CRL Distribution Points or OCSP extensions - let mut crl_urls: Vec = Vec::new(); - let ocsp_urls: Vec = Vec::new(); - - for ext in cert.extensions() { - // Check for CRL Distribution Points (OID: 2.5.29.31) - if ext.oid.to_id_string() == "2.5.29.31" { - // Parse CRL Distribution Points - // This is a simplified extraction - full implementation would parse the ASN.1 structure - tracing::debug!("Certificate has CRL Distribution Points extension"); - - // Add configured CRL URL if available - if let Some(ref url) = self.crl_url { - crl_urls.push(url.clone()); - } - } - - // Check for Authority Information Access (OID: 1.3.6.1.5.5.7.1.1) for OCSP - if ext.oid.to_id_string() == "1.3.6.1.5.5.7.1.1" { - tracing::debug!("Certificate has Authority Information Access extension (OCSP)"); - // OCSP URL extraction would go here - } - } - - // Perform CRL check if URLs are available - if !crl_urls.is_empty() { - for crl_url in &crl_urls { - match self.check_crl_revocation(cert, crl_url).await { - Ok(is_revoked) => { - if is_revoked { - return Err(anyhow::anyhow!( - "Certificate has been revoked (CRL check against: {})", - crl_url - )); - } - tracing::info!("Certificate CRL check passed: {}", crl_url); - return Ok(()); // Successful check, certificate not revoked - }, - Err(e) => { - tracing::warn!("CRL check failed for {}: {}", crl_url, e); - // Continue to next CRL URL or OCSP - }, - } - } - } - - // Perform OCSP check if URLs are available and CRL failed - if !ocsp_urls.is_empty() { - for ocsp_url in &ocsp_urls { - match self.check_ocsp_revocation(cert, ocsp_url).await { - Ok(is_revoked) => { - if is_revoked { - return Err(anyhow::anyhow!( - "Certificate has been revoked (OCSP check against: {})", - ocsp_url - )); - } - tracing::info!("Certificate OCSP check passed: {}", ocsp_url); - return Ok(()); // Successful check, certificate not revoked - }, - Err(e) => { - tracing::warn!("OCSP check failed for {}: {}", ocsp_url, e); - }, - } - } - } - - // If revocation checking is enabled but no methods succeeded - if crl_urls.is_empty() && ocsp_urls.is_empty() { - tracing::warn!( - "Certificate revocation checking enabled but no CRL or OCSP URLs available" - ); - // In strict mode, this would be an error - // For now, we allow it with a warning - } - - Ok(()) - } - - /// Check certificate against CRL (Certificate Revocation List) - async fn check_crl_revocation( - &self, - cert: &X509Certificate<'_>, - crl_url: &str, - ) -> Result { - tracing::debug!("Checking certificate revocation via CRL: {}", crl_url); - - // Download CRL from URL - let client = reqwest::Client::builder() - .timeout(std::time::Duration::from_secs(10)) - .build() - .context("Failed to create HTTP client for CRL download")?; - - let crl_response = client - .get(crl_url) - .send() - .await - .context("Failed to download CRL")?; - - let crl_bytes = crl_response - .bytes() - .await - .context("Failed to read CRL response")?; - - // Parse CRL - let (_, crl) = CertificateRevocationList::from_der(&crl_bytes) - .map_err(|e| anyhow::anyhow!("Failed to parse CRL: {}", e))?; - - // Check if certificate serial number is in revoked list - for revoked_cert in crl.iter_revoked_certificates() { - if revoked_cert.raw_serial() == cert.raw_serial() { - tracing::error!( - "Certificate REVOKED! Serial: {:X}, Revocation date: {:?}", - cert.serial, - revoked_cert.revocation_date - ); - return Ok(true); // Certificate is revoked - } - } - - Ok(false) // Certificate not found in CRL, not revoked - } - - /// Check certificate via OCSP (Online Certificate Status Protocol). - /// - /// **Production guidance**: OCSP stapling is the recommended approach for revocation - /// checking in HFT systems. Configure OCSP stapling at the TLS termination layer - /// (e.g., Envoy, nginx, or HAProxy) so the stapled response is delivered during the - /// handshake with zero additional latency. Application-level OCSP requests add a - /// synchronous HTTP round-trip (50-500ms) per connection, which is unacceptable for - /// latency-sensitive trading workloads. - /// - /// **Alternatives to application-level OCSP**: - /// - CRL checking via `check_crl_revocation` (periodic download, no per-connection cost) - /// - Short-lived certificates (e.g., 24h validity) that expire before revocation matters - /// - OCSP stapling at the load balancer / TLS terminator - /// - /// This method returns `Ok(false)` (not revoked) because revocation checking is - /// delegated to the infrastructure layer. - async fn check_ocsp_revocation( - &self, - _cert: &X509Certificate<'_>, - ocsp_url: &str, - ) -> Result { - tracing::debug!( - "OCSP revocation check requested for URL: {}. \ - Revocation checking is delegated to infrastructure-layer OCSP stapling.", - ocsp_url - ); - - // Revocation checking is handled at the TLS terminator (Envoy/nginx) via - // OCSP stapling. Application-level OCSP is not implemented to avoid adding - // per-connection HTTP latency incompatible with HFT requirements. - Ok(false) - } -} - -/// TLS interceptor for gRPC requests -#[derive(Clone)] -pub struct TlsInterceptor { - tls_config: Arc, -} - -impl TlsInterceptor { - /// Create new TLS interceptor - pub fn new(tls_config: Arc) -> Self { - Self { tls_config } - } - - /// Extract and validate client certificate from request - pub fn extract_client_identity( - &self, - request: &tonic::Request, - ) -> Result { - // Get TLS info from request metadata - let tls_info = request - .extensions() - .get::>() - .ok_or_else(|| anyhow::anyhow!("No TLS connection info found"))?; - - // Extract client certificate if present - if let Some(cert_der) = tls_info - .peer_certs() - .and_then(|certs| certs.first().cloned()) - { - // Convert DER to PEM for processing - let cert_pem = self.der_to_pem(&cert_der)?; - self.tls_config.validate_client_certificate(&cert_pem) - } else { - Err(anyhow::anyhow!("No client certificate provided")) - } - } - - /// Convert DER certificate to PEM format - fn der_to_pem(&self, der_bytes: &[u8]) -> Result> { - use base64::{engine::general_purpose, Engine as _}; - - let b64_cert = general_purpose::STANDARD.encode(der_bytes); - let pem_cert = format!( - "-----BEGIN CERTIFICATE-----\n{}\n-----END CERTIFICATE-----\n", - b64_cert - .chars() - .collect::>() - .chunks(64) - .map(|chunk| chunk.iter().collect::()) - .collect::>() - .join("\n") - ); - - Ok(pem_cert.into_bytes()) - } } #[cfg(test)] diff --git a/services/trading_agent_service/src/assets.rs b/services/trading_agent_service/src/assets.rs index 86d6dac78..be2ab5bd3 100644 --- a/services/trading_agent_service/src/assets.rs +++ b/services/trading_agent_service/src/assets.rs @@ -122,11 +122,6 @@ pub struct AssetSelector { /// Minimum composite score threshold min_composite_score: f64, - - /// Feature extractor for real-time scoring - /// Reserved for future real-time feature extraction during asset selection. - /// Currently, features are extracted elsewhere in the pipeline. - feature_extractor: Arc, } impl AssetSelector { @@ -135,7 +130,6 @@ impl AssetSelector { Self { min_ml_confidence: 0.0, min_composite_score: 0.0, - feature_extractor: Arc::new(MLFeatureExtractor::new(20)), } } @@ -144,7 +138,6 @@ impl AssetSelector { Self { min_ml_confidence, min_composite_score, - feature_extractor: Arc::new(MLFeatureExtractor::new(20)), } } @@ -152,12 +145,11 @@ impl AssetSelector { pub fn with_feature_extractor( min_ml_confidence: f64, min_composite_score: f64, - feature_extractor: Arc, + _feature_extractor: Arc, ) -> Self { Self { min_ml_confidence, min_composite_score, - feature_extractor, } } diff --git a/services/trading_agent_service/src/autonomous_scaling.rs b/services/trading_agent_service/src/autonomous_scaling.rs index cb404e601..8c6090f33 100644 --- a/services/trading_agent_service/src/autonomous_scaling.rs +++ b/services/trading_agent_service/src/autonomous_scaling.rs @@ -18,7 +18,7 @@ use sqlx::PgPool; use std::str::FromStr; use uuid::Uuid; -use crate::universe::{Instrument, UniverseError, UniverseSelector}; +use crate::universe::{Instrument, UniverseError}; use common::Symbol; /// Error types for autonomous scaling @@ -353,7 +353,6 @@ impl SymbolScore { /// Autonomous universe manager pub struct AutonomousUniverseManager { - universe_selector: UniverseSelector, constraints: SystemConstraints, pool: PgPool, } @@ -362,7 +361,6 @@ impl AutonomousUniverseManager { /// Create a new autonomous universe manager pub fn new(pool: PgPool) -> Self { Self { - universe_selector: UniverseSelector::new(pool.clone()), constraints: SystemConstraints::default(), pool, } @@ -371,7 +369,6 @@ impl AutonomousUniverseManager { /// Create with custom constraints pub fn with_constraints(pool: PgPool, constraints: SystemConstraints) -> Self { Self { - universe_selector: UniverseSelector::new(pool.clone()), constraints, pool, } diff --git a/services/trading_agent_service/src/dynamic_stop_loss.rs b/services/trading_agent_service/src/dynamic_stop_loss.rs index ac131b226..493b24c1e 100644 --- a/services/trading_agent_service/src/dynamic_stop_loss.rs +++ b/services/trading_agent_service/src/dynamic_stop_loss.rs @@ -114,16 +114,12 @@ pub async fn apply_dynamic_stop_loss( #[derive(sqlx::FromRow)] struct RegimeRow { regime: Option, - /// Regime confidence score (0.0-1.0) - /// Reserved for future confidence-based stop-loss adjustments. - /// Currently, we apply regime-specific multipliers without confidence weighting. - confidence: Option, } - + // Query regime state directly instead of using the function // (sqlx doesn't support named parameters in function calls) let regime_result = sqlx::query_as::<_, RegimeRow>( - "SELECT regime, confidence FROM regime_states WHERE symbol = $1 ORDER BY event_timestamp DESC LIMIT 1" + "SELECT regime FROM regime_states WHERE symbol = $1 ORDER BY event_timestamp DESC LIMIT 1" ) .bind(symbol) .fetch_optional(pool) diff --git a/services/trading_service/src/core/broker_routing.rs b/services/trading_service/src/core/broker_routing.rs index 128b772b7..6ebfbf83f 100644 --- a/services/trading_service/src/core/broker_routing.rs +++ b/services/trading_service/src/core/broker_routing.rs @@ -140,10 +140,7 @@ pub struct ICMarketsClient; pub struct ICMarketsConfig; pub struct IBKRClient; pub struct IBKRConfig; -pub struct BrokerMonitor { - broker_id: BrokerId, - heartbeat_interval: Duration, -} +pub struct BrokerMonitor; pub struct ConnectionHealth { pub is_connected: bool, pub avg_latency_ms: f64, @@ -219,11 +216,8 @@ impl IBKRClient { } impl BrokerMonitor { - fn new(broker_id: BrokerId, heartbeat_interval: Duration) -> Self { - Self { - broker_id, - heartbeat_interval, - } + fn new(_broker_id: BrokerId, _heartbeat_interval: Duration) -> Self { + Self } async fn check_health(&self) -> ConnectionHealth { ConnectionHealth { @@ -684,40 +678,6 @@ impl BrokerRouter { } } - async fn route_split_order( - &self, - request: &RoutingRequest, - splits: Vec, - ) -> Result { - let parent_order_id = request.order_id.clone(); - let mut child_results = Vec::new(); - - for split in splits { - let mut child_request = request.clone(); - child_request.order_id = split.child_order_id.clone(); - child_request.quantity = split.quantity; - - match self.route_to_broker(&child_request, split.broker_id).await { - Ok(execution_id) => { - child_results.push(execution_id); - }, - Err(e) => { - warn!( - "Failed to route child order {}: {}", - child_request.order_id, e - ); - // Continue with other children - partial fills are acceptable - }, - } - } - - if child_results.is_empty() { - Err(RoutingError::AllChildOrdersFailed) - } else { - Ok(parent_order_id) // Return parent order ID for tracking - } - } - async fn start_monitoring_tasks(&self) { // Start broker status monitoring for (&broker_id, monitor) in &self.broker_monitors { @@ -884,14 +844,6 @@ impl BrokerRouter { } } -/// `Order` split for multi-broker routing -#[derive(Debug, Clone)] -pub struct OrderSplit { - pub broker_id: BrokerId, - pub quantity: f64, - pub child_order_id: String, -} - /// Routing statistics #[derive(Debug, Clone, Default)] pub struct RoutingStats { diff --git a/services/trading_service/src/core/execution_engine.rs b/services/trading_service/src/core/execution_engine.rs index 4020b0275..8eba336ad 100644 --- a/services/trading_service/src/core/execution_engine.rs +++ b/services/trading_service/src/core/execution_engine.rs @@ -16,12 +16,11 @@ use tokio::sync::{mpsc, RwLock}; use tracing::{debug, error, info, warn}; // Core components - REAL PRODUCTION IMPLEMENTATIONS -use trading_engine::lockfree::{AtomicMetrics, LockFreeRingBuffer, SequenceGenerator}; +use trading_engine::lockfree::SequenceGenerator; use trading_engine::timing::{HftLatencyTracker, LatencyMeasurement}; // Real broker integrations use crate::core::broker_routing::BrokerRouter; -use crate::core::order_manager::ExecutionReport; use crate::core::position_manager::PositionManager; use crate::core::risk_manager::RiskManager; use crate::utils::validation::OrderValidator; @@ -32,9 +31,6 @@ use config::structures::{BrokerConfig, TradingConfig}; // Common types use common::{OrderSide, OrderType, TimeInForce}; -// Import ExecutionReport type if needed -// Already imported from order_manager above - /// Execution venue enumeration #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ExecutionVenue { @@ -136,37 +132,16 @@ pub enum ExecutionUrgency { /// Production-grade ExecutionEngine pub struct ExecutionEngine { // Core components - position_manager: Arc, risk_manager: Arc, - broker_router: Arc, order_validator: Arc, // Execution state and metrics execution_state: Arc, active_instructions: Arc>>, - // Execution queues for different algorithms - market_queue: Arc>, - twap_queue: Arc>, - vwap_queue: Arc>, - iceberg_queue: Arc>, - - // Real-time execution tracking - execution_reports: Arc>, - fill_notifications: mpsc::UnboundedSender, - // Performance monitoring latency_tracker: Arc, - metrics: Arc, sequence_generator: Arc, - - // Venue connections - icmarkets_session: Arc>>, - ibkr_session: Arc>>, - - // Configuration - config: Arc, - broker_configs: HashMap, } impl ExecutionEngine { @@ -174,45 +149,15 @@ impl ExecutionEngine { pub async fn new( config: TradingConfig, broker_configs: HashMap, - position_manager: Arc, + _position_manager: Arc, risk_manager: Arc, ) -> Result { - // Initialize execution queues - let market_queue = Arc::new( - LockFreeRingBuffer::new(4096) - .map_err(|e| ExecutionError::InitializationError(e.to_string()))?, - ); - let twap_queue = Arc::new( - LockFreeRingBuffer::new(4096) - .map_err(|e| ExecutionError::InitializationError(e.to_string()))?, - ); - let vwap_queue = Arc::new( - LockFreeRingBuffer::new(4096) - .map_err(|e| ExecutionError::InitializationError(e.to_string()))?, - ); - let iceberg_queue = Arc::new( - LockFreeRingBuffer::new(4096) - .map_err(|e| ExecutionError::InitializationError(e.to_string()))?, - ); - - // Initialize execution reports buffer - let execution_reports = Arc::new( - LockFreeRingBuffer::new(10000) - .map_err(|e| ExecutionError::InitializationError(e.to_string()))?, - ); - - // Initialize fill notification channel - let (fill_tx, _fill_rx) = mpsc::unbounded_channel(); - - // Initialize broker router + // Initialize broker router (needed for validation during construction) let (execution_tx, _execution_rx) = mpsc::unbounded_channel(); - // AssetClassificationManager::new() takes no arguments let asset_classifier = config::asset_classification::AssetClassificationManager::new(); - - // BrokerRouter::new expects a single BrokerConfig, not HashMap - // Use first available broker config or create default let first_broker_config = broker_configs.values().next().cloned().unwrap_or_default(); - let broker_router = + // Construct broker router to validate config (result not stored) + let _broker_router = Arc::new(BrokerRouter::new(first_broker_config, execution_tx, asset_classifier).await?); // Initialize OrderValidator with config-based limits @@ -225,25 +170,12 @@ impl ExecutionEngine { )); Ok(Self { - position_manager, risk_manager, - broker_router, order_validator, execution_state: Arc::new(AtomicExecutionState::new()), active_instructions: Arc::new(RwLock::new(HashMap::new())), - market_queue, - twap_queue, - vwap_queue, - iceberg_queue, - execution_reports, - fill_notifications: fill_tx, latency_tracker: Arc::new(HftLatencyTracker::default()), - metrics: Arc::new(AtomicMetrics::new()), sequence_generator: Arc::new(SequenceGenerator::new()), - icmarkets_session: Arc::new(RwLock::new(None)), - ibkr_session: Arc::new(RwLock::new(None)), - config: Arc::new(config), - broker_configs, }) } @@ -741,26 +673,6 @@ impl ExecutionEngine { Ok(()) } - // Additional helper method stubs... - async fn execute_volume_weighted_slices( - &self, - _instruction: &ExecutionInstruction, - _routing: &RoutingDecision, - _vwap_target: f64, - ) -> Result<(), ExecutionError> { - Ok(()) - } - async fn detect_sniping_opportunity( - &self, - _book_update: &BookUpdate, - _instruction: &ExecutionInstruction, - ) -> Result { - Ok(SnipingOpportunity { - is_attractive: false, - price: 0.0, - size: 0.0, - }) - } async fn find_internal_cross( &self, _instruction: &ExecutionInstruction, diff --git a/services/trading_service/src/core/order_manager.rs b/services/trading_service/src/core/order_manager.rs index f2de1db74..bd6f18546 100644 --- a/services/trading_service/src/core/order_manager.rs +++ b/services/trading_service/src/core/order_manager.rs @@ -21,7 +21,7 @@ use trading_engine::lockfree::{ AtomicMetrics, BatchMode, SequenceGenerator, SmallBatchOrdersSoA, SmallBatchRing, }; use trading_engine::simd::SimdMarketDataOps; -use trading_engine::timing::{HardwareTimestamp, HftLatencyTracker, LatencyMeasurement}; +use trading_engine::timing::{HardwareTimestamp, LatencyMeasurement}; // Types and configurations use config::structures::{BrokerConfig, TradingConfig}; @@ -75,8 +75,6 @@ pub struct OrderManager { // High-performance components sequence_generator: Arc, - timer: Arc, - latency_tracker: Arc, // Batch processing optimization order_batch: Arc>, @@ -112,9 +110,6 @@ impl OrderManager { // Create broker config with proper selector and commission calculator let broker_config = Arc::new(BrokerConfig::default()); - // Initialize high-performance tracking - let latency_tracker = Arc::new(HftLatencyTracker::default()); - // Initialize sequence generator for order ordering let sequence_generator = Arc::new(SequenceGenerator::new()); @@ -126,8 +121,6 @@ impl OrderManager { sell_orders, active_orders: Arc::new(RwLock::new(HashMap::with_capacity(10000))), sequence_generator, - timer: Arc::new(HardwareTimestamp::now()), - latency_tracker, order_batch: Arc::new(RwLock::new(SmallBatchOrdersSoA::new())), metrics, order_count: AtomicUsize::new(0), diff --git a/services/trading_service/src/core/position_manager.rs b/services/trading_service/src/core/position_manager.rs index c8c4badb3..b060a367a 100644 --- a/services/trading_service/src/core/position_manager.rs +++ b/services/trading_service/src/core/position_manager.rs @@ -16,7 +16,7 @@ use tracing::{debug, error, info, warn}; // Core components - REAL PRODUCTION IMPLEMENTATIONS use trading_engine::lockfree::{AtomicMetrics, SequenceGenerator}; use trading_engine::simd::{AlignedPrices, SimdPriceOps}; -use trading_engine::timing::{HardwareTimestamp, HftLatencyTracker, LatencyMeasurement}; +use trading_engine::timing::{HardwareTimestamp, LatencyMeasurement}; // Types and configurations use config::structures::TradingConfig; @@ -24,20 +24,10 @@ use config::ConfigManager; // Add missing config fields for position management trait PositionConfigExt { - fn max_position_size(&self) -> Option; - fn max_notional_exposure(&self) -> Option; fn max_position_var(&self) -> Option; } impl PositionConfigExt for TradingConfig { - fn max_position_size(&self) -> Option { - Some(1_000_000.0) // Default 1M units - } - - fn max_notional_exposure(&self) -> Option { - Some(10_000_000.0) // Default $10M - } - fn max_position_var(&self) -> Option { Some(50_000.0) // Default $50K VaR } @@ -283,7 +273,6 @@ pub struct PositionManager { // High-performance components - REAL PRODUCTION TIMING sequence_generator: Arc, - latency_tracker: Arc, // Performance metrics metrics: Arc, @@ -311,7 +300,6 @@ impl PositionManager { Ok(Self { positions: Arc::new(RwLock::new(HashMap::with_capacity(10000))), sequence_generator: Arc::new(SequenceGenerator::new()), - latency_tracker: Arc::new(HftLatencyTracker::default()), metrics: Arc::new(AtomicMetrics::new()), position_count: AtomicU64::new(0), update_count: AtomicU64::new(0), diff --git a/services/trading_service/src/core/risk_manager.rs b/services/trading_service/src/core/risk_manager.rs index c76046164..243bef13a 100644 --- a/services/trading_service/src/core/risk_manager.rs +++ b/services/trading_service/src/core/risk_manager.rs @@ -1109,44 +1109,6 @@ impl RiskManager { Ok(()) } - async fn calculate_kelly_size( - &self, - symbol: &str, - _quantity: f64, - price: f64, - ) -> Result { - let returns = self.return_history.read().await; - - if let Some(symbol_returns) = returns.get(symbol) { - if symbol_returns.len() >= 30 { - // Convert &str to Symbol type - use common::Symbol; - let symbol_obj = Symbol::from(symbol); - - return self - .kelly_sizer - .calculate_kelly_fraction(&symbol_obj, "default_strategy") - .map_err(|e| risk::error::RiskError::CalculationError(e.to_string())); - } - } - - // Default conservative sizing if insufficient data - Ok(KellyResult { - // Convert &str to Symbol type for KellyResult - symbol: common::Symbol::from(symbol), - strategy_id: "default".to_string(), - raw_kelly_fraction: 0.1, - adjusted_kelly_fraction: 0.1, - confidence: 0.5, - win_rate: 0.5, - average_win: price * 0.01, - average_loss: price * 0.01, - sample_size: 0, - use_kelly: false, - position_fraction: 0.1, - }) - } - async fn calculate_incremental_var( &self, _account_id: &str, @@ -1338,10 +1300,6 @@ impl RiskManager { (var_score + drawdown_score + incremental_score).min(100.0) } - fn price_to_fixed(&self, price: f64) -> u64 { - (price * 10000.0) as u64 - } - fn fixed_to_price(&self, fixed: u64) -> f64 { fixed as f64 / 10000.0 } diff --git a/services/trading_service/src/ensemble_coordinator.rs b/services/trading_service/src/ensemble_coordinator.rs index 5279f94fa..08c6eea84 100644 --- a/services/trading_service/src/ensemble_coordinator.rs +++ b/services/trading_service/src/ensemble_coordinator.rs @@ -813,9 +813,6 @@ impl Default for ModelRegistry { pub struct SignalAggregator { /// Signal threshold for Buy/Sell actions signal_threshold: f64, - - /// Minimum confidence for high-confidence decisions - min_confidence: f64, } impl SignalAggregator { @@ -823,7 +820,6 @@ impl SignalAggregator { pub fn new() -> Self { Self { signal_threshold: 0.3, - min_confidence: 0.6, } } diff --git a/services/trading_service/src/ensemble_risk_manager.rs b/services/trading_service/src/ensemble_risk_manager.rs index b8598e25b..66dc7bfc7 100644 --- a/services/trading_service/src/ensemble_risk_manager.rs +++ b/services/trading_service/src/ensemble_risk_manager.rs @@ -18,7 +18,6 @@ use ml::ensemble::EnsembleDecision; use ml::{MLError, MLResult}; use risk::circuit_breaker::{BrokerAccountService, CircuitBreakerConfig, RealCircuitBreaker}; use risk::var_calculator::var_engine::PositionInfo; -use risk::RealVaREngine; /// Ensemble risk manager configuration #[derive(Debug, Clone)] @@ -176,7 +175,6 @@ pub struct EnsembleRiskManager { model_health: Arc>>, cascade_state: Arc>, circuit_breaker: Option>, - var_engine: Arc, } impl EnsembleRiskManager { @@ -187,7 +185,6 @@ impl EnsembleRiskManager { model_health: Arc::new(RwLock::new(HashMap::new())), cascade_state: Arc::new(RwLock::new(CascadeState::new())), circuit_breaker: None, - var_engine: Arc::new(RealVaREngine::new()), } } @@ -208,7 +205,6 @@ impl EnsembleRiskManager { model_health: Arc::new(RwLock::new(HashMap::new())), cascade_state: Arc::new(RwLock::new(CascadeState::new())), circuit_breaker: Some(Arc::new(circuit_breaker)), - var_engine: Arc::new(RealVaREngine::new()), }) } diff --git a/services/trading_service/src/main.rs b/services/trading_service/src/main.rs index 06d36ba60..b0f9ca996 100644 --- a/services/trading_service/src/main.rs +++ b/services/trading_service/src/main.rs @@ -42,7 +42,6 @@ use trading_service::questdb_metrics::QuestDBMetricsProvider; use trading_service::state::TradingServiceState; /// Default configuration values -const DEFAULT_CONFIG_TTL: Duration = Duration::from_secs(300); // 5 minutes const DEFAULT_GRPC_PORT: u16 = 50052; // Trading Service port (API Gateway uses 50051) const DEFAULT_HEALTH_PORT: u16 = 8081; // Health check port (separate from API Gateway 8080) diff --git a/services/trading_service/src/paper_trading_executor.rs b/services/trading_service/src/paper_trading_executor.rs index 3c6ddb3a2..4552c6cd5 100644 --- a/services/trading_service/src/paper_trading_executor.rs +++ b/services/trading_service/src/paper_trading_executor.rs @@ -29,9 +29,6 @@ use uuid::Uuid; // Import shared ML strategy (ONE SINGLE SYSTEM) use common::ml_strategy::SharedMLStrategy; -// Import production feature extractor adapter from ml crate -use ml::features::ProductionFeatureExtractorAdapter; - /// Paper Trading Executor Configuration #[derive(Debug, Clone)] pub struct PaperTradingConfig { @@ -144,8 +141,6 @@ pub struct PaperTradingExecutor { config: PaperTradingConfig, position_tracker: Arc>>>, - // ML integration (shared strategy - ONE SINGLE SYSTEM) - ml_strategy: Arc>, position_limits: Arc>>, } @@ -154,18 +149,10 @@ impl PaperTradingExecutor { /// # Errors /// Returns error if ML model adapter construction fails. pub fn new(db_pool: PgPool, config: PaperTradingConfig) -> std::result::Result { - // Initialize with production feature extractor (225 features from ml crate) - let extractor = Box::new(ProductionFeatureExtractorAdapter::new()); - let ml_strategy = SharedMLStrategy::new_with_production_extractor( - extractor, - 0.6, // min_confidence_threshold - )?; - Ok(Self { db_pool, config, position_tracker: Arc::new(RwLock::new(HashMap::new())), - ml_strategy: Arc::new(RwLock::new(ml_strategy)), position_limits: Arc::new(RwLock::new(HashMap::new())), }) } @@ -174,13 +161,12 @@ impl PaperTradingExecutor { pub fn new_with_ml_strategy( db_pool: PgPool, config: PaperTradingConfig, - ml_strategy: SharedMLStrategy, + _ml_strategy: SharedMLStrategy, ) -> Self { Self { db_pool, config, position_tracker: Arc::new(RwLock::new(HashMap::new())), - ml_strategy: Arc::new(RwLock::new(ml_strategy)), position_limits: Arc::new(RwLock::new(HashMap::new())), } } @@ -212,43 +198,6 @@ impl PaperTradingExecutor { }) } - /// Generate rule-based signal (fallback) (NEW) - async fn generate_rule_based_signal( - &self, - market_data: &[(f64, f64, f64, f64, f64)], - ) -> Result { - // Simple moving average crossover strategy - if market_data.len() < 20 { - return Ok(TradingSignal { - action: Some(Action::Hold), - confidence: 0.5, - source: SignalSource::RuleBased, - model_votes: None, - }); - } - - // Calculate short-term (10-period) and long-term (20-period) moving averages - let closes: Vec = market_data.iter().map(|bar| bar.3).collect(); - - let sma_short: f64 = closes[closes.len() - 10..].iter().sum::() / 10.0; - let sma_long: f64 = closes[closes.len() - 20..].iter().sum::() / 20.0; - - let action = if sma_short > sma_long { - Some(Action::Buy) - } else if sma_short < sma_long { - Some(Action::Sell) - } else { - Some(Action::Hold) - }; - - Ok(TradingSignal { - action, - confidence: 0.7, - source: SignalSource::RuleBased, - model_votes: None, - }) - } - /// Generate signal (with automatic fallback) pub async fn generate_signal( &self, @@ -663,26 +612,6 @@ impl PaperTradingExecutor { Ok(order_id) } - /// Link prediction to executed order (DEPRECATED - use link_prediction_to_order_with_entry) - async fn link_prediction_to_order(&self, prediction_id: Uuid, order_id: Uuid) -> Result<()> { - sqlx::query!( - r#" - UPDATE ensemble_predictions - SET order_id = $2 - WHERE id = $1 - "#, - prediction_id, - order_id, - ) - .execute(&self.db_pool) - .await - .context("Failed to link prediction to order")?; - - debug!("Linked prediction {} to order {}", prediction_id, order_id); - - Ok(()) - } - /// Link prediction to executed order WITH entry price and position size (NEW - Agent C7) async fn link_prediction_to_order_with_entry( &self, diff --git a/services/trading_service/src/prediction_generation_loop.rs b/services/trading_service/src/prediction_generation_loop.rs index 2347abe79..42c7ac270 100644 --- a/services/trading_service/src/prediction_generation_loop.rs +++ b/services/trading_service/src/prediction_generation_loop.rs @@ -245,8 +245,6 @@ impl PredictionGenerationLoop { let bars = sqlx::query_as::<_, OhlcvBar>( r#" SELECT - timestamp, - symbol, open, high, low, @@ -458,8 +456,6 @@ struct MarketDataSnapshot { /// OHLCV bar from database #[derive(Debug, Clone, sqlx::FromRow)] struct OhlcvBar { - timestamp: chrono::DateTime, - symbol: String, open: f64, high: f64, low: f64, diff --git a/services/trading_service/src/services/enhanced_ml.rs b/services/trading_service/src/services/enhanced_ml.rs index 97bec7429..bc1ee32b9 100644 --- a/services/trading_service/src/services/enhanced_ml.rs +++ b/services/trading_service/src/services/enhanced_ml.rs @@ -394,125 +394,6 @@ impl EnhancedMLServiceImpl { Ok(0.0) } - /// Hot-load a new model version (production implementation with actual model loading) - async fn hot_load_model( - &self, - model_id: String, - version: String, - model_path: String, - ) -> Result<(), Status> { - info!( - "Hot-loading model {} version {} from {}", - model_id, version, model_path - ); - - // Validate model file exists - if !std::path::Path::new(&model_path).exists() { - return Err(Status::not_found(format!( - "Model file not found: {}", - model_path - ))); - } - - // Load the actual model from file - let model_instance = self.load_model_from_file(&model_id, &model_path).await?; - - // Get model metadata - let ml_metadata = model_instance.get_metadata(); - let model_type = model_instance.model_type(); - - // Determine supported symbols and horizons from model metadata - let supported_symbols = vec![ - "EURUSD".to_string(), - "GBPUSD".to_string(), - "USDJPY".to_string(), - "AUDUSD".to_string(), - ]; - - let supported_horizons = vec![1, 5, 15, 60]; // minutes - - // Create enhanced model metadata - let metadata = RuntimeModelInfo { - model_id: model_id.clone(), - version, - load_time: SystemTime::now(), - last_inference: None, - inference_count: 0, - error_count: 0, - avg_latency_us: 0.0, - confidence_threshold: 0.7, - weight_in_ensemble: 1.0, - fallback_priority: 0, - model_type, - supported_symbols, - supported_horizons, - feature_count: ml_metadata.features_used, - model_instance: Some(model_instance), - }; - - // Add to models registry - { - let mut models = self.models.write().await; - models.insert(model_id.clone(), metadata.clone()); - } - - // Register model with fallback manager - self.ml_fallback_manager - .register_model(model_id.clone(), metadata.fallback_priority) - .await; - - // Update ensemble weights - self.rebalance_ensemble_weights().await; - - info!( - "Successfully hot-loaded model: {} (type: {:?}, features: {})", - model_id, model_type, ml_metadata.features_used - ); - Ok(()) - } - - /// Rebalance ensemble model weights based on performance - async fn rebalance_ensemble_weights(&self) { - let models = self.models.read().await; - let mut weights = self.model_weights.write().await; - - let mut total_score = 0.0; - let mut model_scores = HashMap::new(); - - // Calculate performance scores for each model using MLPerformanceMonitor - for (model_id, _model_meta) in models.iter() { - if let Some(perf_stats) = self.ml_performance_monitor.get_model_stats(model_id).await { - // Score based on accuracy, latency, and reliability - let accuracy_score = perf_stats.avg_accuracy; - let latency_score = if perf_stats.p95_latency_us > 0.0 { - 1.0 / (1.0 + perf_stats.p95_latency_us / 1000.0) // Penalize high latency - } else { - 1.0 - }; - let reliability_score = 1.0 - perf_stats.error_rate; - - let composite_score = - (accuracy_score * 0.5) + (latency_score * 0.3) + (reliability_score * 0.2); - model_scores.insert(model_id.clone(), composite_score); - total_score += composite_score; - } else { - // New model with no statistics - assign neutral weight - model_scores.insert(model_id.clone(), 0.5); - total_score += 0.5; - } - } - - // Normalize weights - if total_score > 0.0 { - for (model_id, score) in model_scores { - let weight = score / total_score; - weights.insert(model_id, weight); - } - } - - debug!("Rebalanced ensemble weights: {:?}", *weights); - } - /// Get ensemble prediction from multiple models async fn get_ensemble_prediction( &self, @@ -735,48 +616,6 @@ impl EnhancedMLServiceImpl { Ok(prediction) } - /// DEPRECATED: simulate_model_inference - Replaced with real ML inference above - /// - /// Kept for backward compatibility during transition - async fn simulate_model_inference( - &self, - model_id: &str, - features: &[f32], - ) -> Result { - if features.is_empty() { - return Err(Status::invalid_argument("Empty features provided")); - } - - // Simple ensemble simulation based on model type - let prediction = match model_id { - id if id.contains("dqn") => { - // Deep Q-Learning prediction - let momentum = features.first().copied().unwrap_or(0.0); - let volume = features.get(1).copied().unwrap_or(0.0); - 0.5 + (momentum * 0.3) + (volume * 0.1).tanh() * 0.2 - }, - id if id.contains("transformer") => { - // Transformer-based prediction - let price_change = features.first().copied().unwrap_or(0.0); - let volatility = features.get(2).copied().unwrap_or(0.0); - 0.5 + (price_change * 0.4) - (volatility * 0.1) - }, - id if id.contains("ensemble") => { - // Ensemble model - let feature_sum: f32 = features.iter().sum(); - let normalized = feature_sum / features.len() as f32; - 0.5 + normalized.tanh() * 0.3 - }, - _ => { - // Default prediction - let avg = features.iter().sum::() / features.len() as f32; - 0.5 + avg.tanh() * 0.2 - }, - }; - - Ok(prediction.clamp(0.0, 1.0) as f64) - } - /// Record model performance metrics with MLPerformanceMonitor and Prometheus (Production implementation) async fn record_model_performance(&self, model_id: &str, latency_us: u64, success: bool) { use crate::ml_metrics; diff --git a/services/trading_service/src/services/ml_fallback_manager.rs b/services/trading_service/src/services/ml_fallback_manager.rs index d093bfcb8..894cb3e40 100644 --- a/services/trading_service/src/services/ml_fallback_manager.rs +++ b/services/trading_service/src/services/ml_fallback_manager.rs @@ -185,8 +185,6 @@ pub struct MLFallbackManager { failover_events: Arc>>, /// Event broadcaster event_broadcaster: Arc>, - /// Circuit breaker states - circuit_breakers: Arc>>, } impl MLFallbackManager { @@ -201,7 +199,6 @@ impl MLFallbackManager { current_primary: Arc::new(RwLock::new(None)), failover_events: Arc::new(RwLock::new(Vec::new())), event_broadcaster: Arc::new(_event_sender), - circuit_breakers: Arc::new(RwLock::new(HashMap::new())), } } diff --git a/services/trading_service/src/services/risk.rs b/services/trading_service/src/services/risk.rs index fe3c66778..98ed321ec 100644 --- a/services/trading_service/src/services/risk.rs +++ b/services/trading_service/src/services/risk.rs @@ -432,7 +432,6 @@ impl RiskService for RiskServiceImpl { // Use the real RiskEngine's configured confidence level and max VaR limit // to produce the 1d VaR estimate. Longer horizons scale by sqrt(T). let risk_engine = self.state.risk_engine.read().await; - let confidence = risk_engine.var_confidence(); // Compute a representative 1-day portfolio VaR via marginal VaR using the // real portfolio notional derived from open positions above. diff --git a/tests/e2e/src/bin/e2e_test_runner.rs b/tests/e2e/src/bin/e2e_test_runner.rs index c73d91306..84a8f47a8 100644 --- a/tests/e2e/src/bin/e2e_test_runner.rs +++ b/tests/e2e/src/bin/e2e_test_runner.rs @@ -38,12 +38,11 @@ pub struct TestExecutionResult { } pub struct CorrodeTestRunner { - config: CorrodeConfig, } impl CorrodeTestRunner { - pub fn new(config: CorrodeConfig) -> Self { - Self { config } + pub fn new(_config: CorrodeConfig) -> Self { + Self {} } pub fn with_default_config() -> Self { diff --git a/tests/e2e/src/workflows.rs b/tests/e2e/src/workflows.rs index dc08e3fa4..419eb5643 100644 --- a/tests/e2e/src/workflows.rs +++ b/tests/e2e/src/workflows.rs @@ -94,21 +94,17 @@ impl WorkflowTestResult { /// Complete trading workflow orchestrator pub struct TradingWorkflow { - database: Arc, ml_pipeline: Arc>, - test_data: Arc, } impl TradingWorkflow { pub fn new( - database: Arc, + _database: Arc, ml_pipeline: Arc>, - test_data: Arc, + _test_data: Arc, ) -> Self { Self { - database, ml_pipeline, - test_data, } } @@ -679,15 +675,11 @@ impl TradingWorkflow { /// Backtesting workflow orchestrator pub struct BacktestingWorkflow { - database: Arc, - test_data: Arc, } impl BacktestingWorkflow { - pub fn new(database: Arc, test_data: Arc) -> Self { + pub fn new(_database: Arc, _test_data: Arc) -> Self { Self { - database, - test_data, } } diff --git a/tests/test_runner.rs b/tests/test_runner.rs index 2b9736ca6..6b7904e8e 100644 --- a/tests/test_runner.rs +++ b/tests/test_runner.rs @@ -201,8 +201,6 @@ pub struct CriticalPathTestRunner { performance_monitor: MockPerformanceMonitor, /// Test counter for unique IDs test_counter: AtomicU64, - /// Test runner start time (reserved for future use) - start_time: Instant, } impl CriticalPathTestRunner { @@ -212,7 +210,6 @@ impl CriticalPathTestRunner { config, performance_monitor: MockPerformanceMonitor::new(), test_counter: AtomicU64::new(0), - start_time: Instant::now(), } } diff --git a/trading_engine/src/compliance/audit_trails.rs b/trading_engine/src/compliance/audit_trails.rs index 0f8274da1..c1d2cc639 100644 --- a/trading_engine/src/compliance/audit_trails.rs +++ b/trading_engine/src/compliance/audit_trails.rs @@ -25,10 +25,8 @@ use rust_decimal::Decimal; /// /// Auto-generated documentation placeholder - enhance with specifics pub struct AuditTrailEngine { - config: AuditTrailConfig, event_buffer: Arc, persistence_engine: Arc, - retention_manager: Arc, query_engine: Arc, _background_tasks: Vec>, } @@ -283,8 +281,6 @@ pub struct LockFreeEventBuffer { pub struct AsyncAuditQueue { /// Sender for audit events (non-blocking) sender: mpsc::UnboundedSender, - /// Receiver for audit events (consumed by background flush) - receiver: Arc>>>, /// WAL file path for crash recovery wal_path: std::path::PathBuf, /// Background flush task handle @@ -298,11 +294,10 @@ pub struct AsyncAuditQueue { impl AsyncAuditQueue { /// Create new async audit queue with WAL pub fn new(wal_path: std::path::PathBuf) -> Self { - let (sender, receiver) = mpsc::unbounded_channel::(); + let (sender, _receiver) = mpsc::unbounded_channel::(); Self { sender, - receiver: Arc::new(RwLock::new(Some(receiver))), wal_path, flush_handle: Arc::new(RwLock::new(None)), queued_events: Arc::new(AtomicU64::new(0)), @@ -600,14 +595,8 @@ pub struct AsyncAuditQueueStats { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct PersistenceEngine { - config: StorageBackendConfig, - batch_processor: Arc>, - compression_engine: Option, - encryption_engine: Option, // PostgreSQL connection pool for audit persistence (wrapped in RwLock for interior mutability) postgres_pool: Arc>>>, - // Async audit queue for non-blocking persistence - async_queue: Option>, } /// Batch processor for efficient persistence @@ -617,9 +606,6 @@ pub struct PersistenceEngine { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct BatchProcessor { - pending_events: Vec, - last_flush: DateTime, - flush_threshold: usize, } /// Compression engine @@ -630,7 +616,6 @@ pub struct BatchProcessor { /// Auto-generated documentation placeholder - enhance with specifics pub struct CompressionEngine { algorithm: CompressionAlgorithm, - compression_level: u32, } /// Compression algorithms @@ -655,7 +640,6 @@ pub enum CompressionAlgorithm { /// Auto-generated documentation placeholder - enhance with specifics pub struct EncryptionEngine { algorithm: EncryptionAlgorithm, - key_id: String, } /// Encryption algorithms @@ -678,7 +662,6 @@ pub enum EncryptionAlgorithm { /// Auto-generated documentation placeholder - enhance with specifics pub struct RetentionManager { config: AuditTrailConfig, - archive_scheduler: Arc, } /// Archive scheduler @@ -688,9 +671,6 @@ pub struct RetentionManager { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ArchiveScheduler { - retention_days: u32, - archive_location: String, - cleanup_schedule: String, } /// Query engine for audit trail searches @@ -700,9 +680,6 @@ pub struct ArchiveScheduler { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct QueryEngine { - config: StorageBackendConfig, - index_manager: Arc, - query_cache: Arc>, // PostgreSQL connection pool for audit queries (wrapped in RwLock for interior mutability) postgres_pool: Arc>>>, } @@ -751,9 +728,6 @@ pub enum IndexType { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct QueryCache { - cache: HashMap, - max_size: usize, - ttl_seconds: u64, } /// Cached query result @@ -881,10 +855,8 @@ impl AuditTrailEngine { background_tasks.push(retention_task); Self { - config, event_buffer, persistence_engine, - retention_manager, query_engine, _background_tasks: background_tasks, } @@ -1205,17 +1177,9 @@ impl LockFreeEventBuffer { } impl PersistenceEngine { - pub fn new(config: &StorageBackendConfig) -> Self { + pub fn new(_config: &StorageBackendConfig) -> Self { Self { - config: config.clone(), - batch_processor: Arc::new(RwLock::new(BatchProcessor::new())), - compression_engine: Some(CompressionEngine::new(CompressionAlgorithm::Gzip, 6)), - encryption_engine: Some(EncryptionEngine::new( - EncryptionAlgorithm::AES256GCM, - "audit-trail-v1".to_owned(), - )), postgres_pool: Arc::new(RwLock::new(None)), // Must be set via set_postgres_pool() - async_queue: None, // Initialized when PostgreSQL pool is set } } @@ -1289,10 +1253,9 @@ impl PersistenceEngine { } impl CompressionEngine { - pub fn new(algorithm: CompressionAlgorithm, compression_level: u32) -> Self { + pub fn new(algorithm: CompressionAlgorithm, _compression_level: u32) -> Self { Self { algorithm, - compression_level, } } @@ -1305,7 +1268,7 @@ impl CompressionEngine { match self.algorithm { CompressionAlgorithm::Gzip => { let mut encoder = - GzEncoder::new(Vec::new(), Compression::new(self.compression_level)); + GzEncoder::new(Vec::new(), Compression::new(6)); encoder.write_all(data).map_err(|e| { AuditTrailError::Compression(format!("Gzip compression failed: {}", e)) })?; @@ -1344,8 +1307,8 @@ impl CompressionEngine { } impl EncryptionEngine { - pub fn new(algorithm: EncryptionAlgorithm, key_id: String) -> Self { - Self { algorithm, key_id } + pub fn new(algorithm: EncryptionAlgorithm, _key_id: String) -> Self { + Self { algorithm } } /// Encrypt data with AEAD (returns ciphertext and nonce) @@ -1416,9 +1379,6 @@ impl EncryptionEngine { impl BatchProcessor { pub fn new() -> Self { Self { - pending_events: Vec::new(), - last_flush: Utc::now(), - flush_threshold: 1000, } } } @@ -1427,7 +1387,6 @@ impl RetentionManager { pub fn new(config: &AuditTrailConfig) -> Self { Self { config: config.clone(), - archive_scheduler: Arc::new(ArchiveScheduler::new(config.retention_days)), } } @@ -1464,21 +1423,15 @@ impl RetentionManager { } impl ArchiveScheduler { - pub fn new(retention_days: u32) -> Self { + pub fn new(_retention_days: u32) -> Self { Self { - retention_days, - archive_location: "audit_archive".to_owned(), - cleanup_schedule: "0 2 * * *".to_owned(), // Daily at 2 AM } } } impl QueryEngine { - pub fn new(config: &StorageBackendConfig) -> Self { + pub fn new(_config: &StorageBackendConfig) -> Self { Self { - config: config.clone(), - index_manager: Arc::new(IndexManager::new()), - query_cache: Arc::new(RwLock::new(QueryCache::new())), postgres_pool: Arc::new(RwLock::new(None)), // Must be set via set_postgres_pool() } } @@ -1805,9 +1758,6 @@ impl IndexManager { impl QueryCache { pub fn new() -> Self { Self { - cache: HashMap::new(), - max_size: 1000, - ttl_seconds: 300, // 5 minutes } } } diff --git a/trading_engine/src/compliance/automated_reporting.rs b/trading_engine/src/compliance/automated_reporting.rs index 4ec5ed337..00af5cb65 100644 --- a/trading_engine/src/compliance/automated_reporting.rs +++ b/trading_engine/src/compliance/automated_reporting.rs @@ -30,7 +30,6 @@ pub struct AutomatedReportingSystem { scheduler: Arc, report_generators: Arc>, submission_engine: Arc, - notification_service: Arc, monitoring: Arc, _background_tasks: Vec>, } @@ -488,10 +487,6 @@ pub struct CronJob { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ReportGenerators { - transaction_reporter: Arc>, - sox_manager: Arc>, - best_execution_analyzer: Arc>, - audit_trail_engine: Arc>, } /// Submission engine @@ -629,8 +624,6 @@ pub enum SubmissionStatus { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct NotificationService { - config: NotificationSettings, - notification_queue: Arc>>, } /// Notification task @@ -693,18 +686,14 @@ impl AutomatedReportingSystem { /// Create new automated reporting system pub fn new( config: AutomatedReportingConfig, - transaction_reporter: Arc>, - sox_manager: Arc>, - best_execution_analyzer: Arc>, - audit_trail_engine: Arc>, + _transaction_reporter: Arc>, + _sox_manager: Arc>, + _best_execution_analyzer: Arc>, + _audit_trail_engine: Arc>, ) -> Self { let scheduler = Arc::new(ReportScheduler::new(&config.schedules)); let report_generators = Arc::new(RwLock::new(ReportGenerators { - transaction_reporter, - sox_manager, - best_execution_analyzer, - audit_trail_engine, })); let submission_engine = Arc::new(SubmissionEngine::new(&config.submission_settings)); @@ -740,7 +729,6 @@ impl AutomatedReportingSystem { scheduler, report_generators, submission_engine, - notification_service, monitoring, _background_tasks: background_tasks, } @@ -1389,10 +1377,8 @@ impl SubmissionEngine { } impl NotificationService { - pub fn new(config: &NotificationSettings) -> Self { + pub fn new(_config: &NotificationSettings) -> Self { Self { - config: config.clone(), - notification_queue: Arc::new(RwLock::new(Vec::new())), } } } diff --git a/trading_engine/src/compliance/best_execution.rs b/trading_engine/src/compliance/best_execution.rs index f9409d1cf..3ee915c89 100644 --- a/trading_engine/src/compliance/best_execution.rs +++ b/trading_engine/src/compliance/best_execution.rs @@ -374,8 +374,6 @@ pub struct VenueMetrics { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct TransactionCostAnalyzer { - cost_models: HashMap, - benchmarks: CostBenchmarks, } /// Cost calculation model @@ -427,8 +425,6 @@ pub struct CostBenchmarks { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ExecutionReportGenerator { - report_templates: HashMap, - output_formats: Vec, } /// Report template definition @@ -931,12 +927,6 @@ impl VenueMetrics { impl TransactionCostAnalyzer { pub fn new() -> Self { Self { - cost_models: HashMap::new(), - benchmarks: CostBenchmarks { - market_average_costs: HashMap::new(), - peer_group_costs: HashMap::new(), - historical_costs: HashMap::new(), - }, } } @@ -1006,8 +996,6 @@ impl TransactionCostAnalyzer { impl ExecutionReportGenerator { pub fn new() -> Self { Self { - report_templates: HashMap::new(), - output_formats: vec![OutputFormat::PDF, OutputFormat::Excel, OutputFormat::JSON], } } } diff --git a/trading_engine/src/compliance/compliance_reporting.rs b/trading_engine/src/compliance/compliance_reporting.rs index 40cb5efb8..29bc72bdb 100644 --- a/trading_engine/src/compliance/compliance_reporting.rs +++ b/trading_engine/src/compliance/compliance_reporting.rs @@ -23,8 +23,6 @@ use std::collections::HashMap; /// scheduled report generation, data retention policies, and audit trail verification. // Infrastructure - fields will be used for compliance engine orchestration pub struct ComplianceReportingEngine { - /// Configuration for the compliance reporting engine - config: ComplianceReportingConfig, /// Event processor for handling compliance events event_processor: EventProcessor, /// Report generator for creating compliance reports @@ -597,8 +595,6 @@ pub struct EventProcessor { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for event enrichment and context caching pub struct EventEnricher { - enrichment_rules: Vec, - context_cache: HashMap, } /// `Enrichment rule` @@ -775,10 +771,6 @@ pub struct BusinessContext { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for batch event processing pub struct BatchProcessor { - batch_size: usize, - processing_interval: Duration, - current_batch: Vec, - last_processing_time: DateTime, } /// `Compliance event` structure @@ -889,10 +881,6 @@ pub enum ComplianceCategory { /// Auto-generated documentation placeholder - enhance with specifics pub struct ReportGenerator { config: ReportGenerationConfig, - db_pool: PgPool, - template_engine: TemplateEngine, - report_scheduler: ReportScheduler, - distributor: ReportDistributor, } /// `Template engine` for report generation @@ -902,8 +890,6 @@ pub struct ReportGenerator { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct TemplateEngine { - templates: HashMap, - template_cache: HashMap, } /// `Report template` @@ -1009,8 +995,6 @@ pub struct CompiledTemplate { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for report scheduling pub struct ReportScheduler { - schedules: Vec, - job_queue: Vec, } /// `Report schedule` @@ -1084,8 +1068,6 @@ pub enum JobStatus { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for report distribution pub struct ReportDistributor { - config: ReportDistributionConfig, - distribution_queue: Vec, } /// `Distribution job` @@ -1155,11 +1137,6 @@ pub enum DistributionStatus { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for storage, archival, compression, and encryption pub struct ComplianceStorageManager { - config: StoragePolicyConfig, - db_pool: PgPool, - archival_engine: ArchivalEngine, - compression_engine: CompressionEngine, - encryption_engine: EncryptionEngine, } /// `Archival engine` // Infrastructure - fields will be used for archival operations @@ -1168,8 +1145,6 @@ pub struct ComplianceStorageManager { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ArchivalEngine { - config: ArchivalConfig, - archival_queue: Vec, } /// `Archival job` @@ -1235,7 +1210,6 @@ pub enum ArchivalStatus { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for data compression pub struct CompressionEngine { - config: CompressionConfig, } /// `Encryption engine` @@ -1245,8 +1219,6 @@ pub struct CompressionEngine { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct EncryptionEngine { - config: EncryptionConfig, - key_manager: KeyManager, } /// `Key manager` @@ -1256,8 +1228,6 @@ pub struct EncryptionEngine { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct KeyManager { - config: KeyManagementConfig, - active_keys: HashMap, } /// `Cryptographic key` @@ -1302,8 +1272,6 @@ pub enum KeyStatus { // Infrastructure - fields will be used for retention policy management pub struct RetentionPolicyManager { policies: Vec, - policy_engine: PolicyEngine, - cleanup_scheduler: CleanupScheduler, } /// `Policy engine` @@ -1313,8 +1281,6 @@ pub struct RetentionPolicyManager { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct PolicyEngine { - active_policies: HashMap, - policy_evaluator: PolicyEvaluator, } /// `Policy evaluator` @@ -1416,10 +1382,6 @@ pub enum CleanupStatus { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for audit trail verification pub struct AuditTrailVerifier { - config: AuditVerificationConfig, - db_pool: PgPool, - hash_calculator: HashCalculator, - signature_verifier: SignatureVerifier, } /// `Hash calculator` @@ -1429,7 +1391,6 @@ pub struct AuditTrailVerifier { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct HashCalculator { - algorithm: HashAlgorithm, } /// `Signature verifier` @@ -1439,8 +1400,6 @@ pub struct HashCalculator { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct SignatureVerifier { - algorithm: Option, - verification_keys: HashMap, } /// `Verification key` @@ -1612,7 +1571,6 @@ impl ComplianceReportingEngine { storage_manager, retention_manager, audit_verifier, - config, }) } @@ -2062,8 +2020,6 @@ impl EventProcessor { impl EventEnricher { pub fn new() -> Self { Self { - enrichment_rules: Vec::new(), - context_cache: HashMap::new(), } } @@ -2101,12 +2057,8 @@ impl EventEnricher { } impl BatchProcessor { - pub fn new(batch_size: usize, processing_interval: Duration) -> Self { + pub fn new(_batch_size: usize, _processing_interval: Duration) -> Self { Self { - batch_size, - processing_interval, - current_batch: Vec::with_capacity(batch_size), - last_processing_time: Utc::now(), } } } @@ -2114,14 +2066,10 @@ impl BatchProcessor { impl ReportGenerator { pub async fn new( config: ReportGenerationConfig, - db_pool: PgPool, + _db_pool: PgPool, ) -> Result { Ok(Self { - template_engine: TemplateEngine::new(), - report_scheduler: ReportScheduler::new(), - distributor: ReportDistributor::new(config.distribution.clone()), config, - db_pool, }) } @@ -2148,8 +2096,6 @@ impl ReportGenerator { impl TemplateEngine { pub fn new() -> Self { Self { - templates: HashMap::new(), - template_cache: HashMap::new(), } } } @@ -2157,32 +2103,23 @@ impl TemplateEngine { impl ReportScheduler { pub const fn new() -> Self { Self { - schedules: Vec::new(), - job_queue: Vec::new(), } } } impl ReportDistributor { - pub const fn new(config: ReportDistributionConfig) -> Self { + pub fn new(_config: ReportDistributionConfig) -> Self { Self { - config, - distribution_queue: Vec::new(), } } } impl ComplianceStorageManager { pub async fn new( - config: StoragePolicyConfig, - db_pool: PgPool, + _config: StoragePolicyConfig, + _db_pool: PgPool, ) -> Result { Ok(Self { - archival_engine: ArchivalEngine::new(config.archival_config.clone()), - compression_engine: CompressionEngine::new(config.compression.clone()), - encryption_engine: EncryptionEngine::new(config.encryption.clone()), - config, - db_pool, }) } @@ -2198,34 +2135,28 @@ impl ComplianceStorageManager { } impl ArchivalEngine { - pub const fn new(config: ArchivalConfig) -> Self { + pub fn new(_config: ArchivalConfig) -> Self { Self { - config, - archival_queue: Vec::new(), } } } impl CompressionEngine { - pub const fn new(config: CompressionConfig) -> Self { - Self { config } + pub const fn new(_config: CompressionConfig) -> Self { + Self {} } } impl EncryptionEngine { - pub fn new(config: EncryptionConfig) -> Self { + pub fn new(_config: EncryptionConfig) -> Self { Self { - key_manager: KeyManager::new(config.key_management.clone()), - config, } } } impl KeyManager { - pub fn new(config: KeyManagementConfig) -> Self { + pub fn new(_config: KeyManagementConfig) -> Self { Self { - config, - active_keys: HashMap::new(), } } } @@ -2233,8 +2164,6 @@ impl KeyManager { impl RetentionPolicyManager { pub async fn new(config: StoragePolicyConfig) -> Result { Ok(Self { - policy_engine: PolicyEngine::new(config.retention_policies.clone()), - cleanup_scheduler: CleanupScheduler::new(), policies: config.retention_policies, }) } @@ -2284,15 +2213,8 @@ impl RetentionPolicyManager { } impl PolicyEngine { - pub fn new(policies: Vec) -> Self { - let mut active_policies = HashMap::new(); - for policy in policies { - active_policies.insert(policy.name.clone(), policy); - } - + pub fn new(_policies: Vec) -> Self { Self { - active_policies, - policy_evaluator: PolicyEvaluator::new(), } } } @@ -2311,14 +2233,10 @@ impl CleanupScheduler { impl AuditTrailVerifier { pub async fn new( - config: AuditVerificationConfig, - db_pool: PgPool, + _config: AuditVerificationConfig, + _db_pool: PgPool, ) -> Result { Ok(Self { - hash_calculator: HashCalculator::new(config.hash_algorithm.clone()), - signature_verifier: SignatureVerifier::new(config.signature_algorithm.clone()), - config, - db_pool, }) } @@ -2343,16 +2261,14 @@ impl AuditTrailVerifier { } impl HashCalculator { - pub const fn new(algorithm: HashAlgorithm) -> Self { - Self { algorithm } + pub const fn new(_algorithm: HashAlgorithm) -> Self { + Self {} } } impl SignatureVerifier { - pub fn new(algorithm: Option) -> Self { + pub fn new(_algorithm: Option) -> Self { Self { - algorithm, - verification_keys: HashMap::new(), } } } diff --git a/trading_engine/src/compliance/iso27001_compliance.rs b/trading_engine/src/compliance/iso27001_compliance.rs index 2ed7fcac7..25743fdc7 100644 --- a/trading_engine/src/compliance/iso27001_compliance.rs +++ b/trading_engine/src/compliance/iso27001_compliance.rs @@ -22,13 +22,11 @@ use std::collections::HashMap; /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for ISO 27001 compliance management pub struct ISO27001ComplianceManager { - config: ISO27001Config, isms: InformationSecurityManagementSystem, risk_manager: SecurityRiskManager, incident_response: IncidentResponseSystem, business_continuity: BusinessContinuityManager, asset_manager: AssetManager, - policy_manager: SecurityPolicyManager, } /// `ISO 27001` configuration @@ -970,11 +968,6 @@ pub enum AuditType { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for ISMS policy and control management pub struct InformationSecurityManagementSystem { - policies: HashMap, - procedures: HashMap, - controls: HashMap, - metrics: SecurityMetrics, - improvement_actions: Vec, } /// Security policy @@ -1358,9 +1351,6 @@ pub struct ProgressUpdate { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for security risk management pub struct SecurityRiskManager { - risk_register: HashMap, - risk_methodology: RiskMethodology, - treatment_plans: HashMap, } /// `Security risk` @@ -1626,10 +1616,6 @@ pub struct PersonnelRequirement { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for incident response management pub struct IncidentResponseSystem { - config: IncidentResponseConfig, - active_incidents: HashMap, - response_procedures: HashMap, - playbooks: HashMap, } /// Security `incident` @@ -2585,10 +2571,6 @@ pub struct HandlingProcedure { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for security policy management pub struct SecurityPolicyManager { - policies: HashMap, - procedures: HashMap, - standards: HashMap, - guidelines: HashMap, } /// Security standard @@ -2858,8 +2840,6 @@ impl ISO27001ComplianceManager { incident_response: IncidentResponseSystem::new(&config.incident_response_config), business_continuity: BusinessContinuityManager::new(&config.business_continuity_config), asset_manager: AssetManager::new(), - policy_manager: SecurityPolicyManager::new(), - config, } } @@ -3080,35 +3060,6 @@ pub enum RecommendationPriority { impl InformationSecurityManagementSystem { pub fn new() -> Self { Self { - policies: HashMap::new(), - procedures: HashMap::new(), - controls: HashMap::new(), - metrics: SecurityMetrics { - security_incidents: SecurityIncidentMetrics { - total_incidents: 0, - critical_incidents: 0, - avg_resolution_time: Duration::hours(4), - trends: vec![], - }, - control_effectiveness: ControlEffectivenessMetrics { - total_controls: 93, - effective_controls: 75, - effectiveness_percentage: 80.6, - controls_by_category: HashMap::new(), - }, - risk_metrics: RiskMetrics { - total_risks: 50, - high_risks: 5, - risk_reduction_percentage: 25.0, - risk_appetite_compliance: 95.0, - }, - compliance_metrics: ComplianceMetrics { - overall_compliance: 85.0, - compliance_by_requirement: HashMap::new(), - non_conformities: 3, - }, - }, - improvement_actions: vec![], } } @@ -3120,9 +3071,6 @@ impl InformationSecurityManagementSystem { impl SecurityRiskManager { pub fn new(_methodology: &RiskMethodology) -> Self { Self { - risk_register: HashMap::new(), - risk_methodology: _methodology.clone(), - treatment_plans: HashMap::new(), } } @@ -3134,10 +3082,6 @@ impl SecurityRiskManager { impl IncidentResponseSystem { pub fn new(_config: &IncidentResponseConfig) -> Self { Self { - config: _config.clone(), - active_incidents: HashMap::new(), - response_procedures: HashMap::new(), - playbooks: HashMap::new(), } } @@ -3232,10 +3176,6 @@ impl AssetManager { impl SecurityPolicyManager { pub fn new() -> Self { Self { - policies: HashMap::new(), - procedures: HashMap::new(), - standards: HashMap::new(), - guidelines: HashMap::new(), } } } diff --git a/trading_engine/src/compliance/sox_compliance.rs b/trading_engine/src/compliance/sox_compliance.rs index f6251e9ab..8a9e040cf 100644 --- a/trading_engine/src/compliance/sox_compliance.rs +++ b/trading_engine/src/compliance/sox_compliance.rs @@ -21,12 +21,10 @@ use std::collections::HashMap; /// /// Auto-generated documentation placeholder - enhance with specifics pub struct SOXComplianceManager { - config: SOXConfig, internal_controls: InternalControlsEngine, segregation_duties: SegregationOfDutiesManager, change_management: ChangeManagementSystem, access_control: AccessControlMatrix, - audit_logger: SOXAuditLogger, } /// `SOX` compliance configuration @@ -181,9 +179,6 @@ pub enum NotificationMethod { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct InternalControlsEngine { - controls_catalog: HashMap, - control_testing: ControlTestingEngine, - deficiency_tracker: DeficiencyTracker, } /// Internal control definition @@ -332,8 +327,6 @@ pub enum ImplementationStatus { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ControlTestingEngine { - test_schedules: HashMap, - test_results: Vec, } /// Test schedule @@ -670,8 +663,6 @@ pub struct ManagementResponse { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct DeficiencyTracker { - deficiencies: HashMap, - metrics: DeficiencyMetrics, } /// Deficiency metrics @@ -700,9 +691,6 @@ pub struct DeficiencyMetrics { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct SegregationOfDutiesManager { - sod_matrix: SegregationMatrix, - conflict_detector: ConflictDetector, - approval_workflows: HashMap, } /// Segregation matrix @@ -795,8 +783,6 @@ pub struct RequiredSeparation { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ConflictDetector { - detection_rules: Vec, - active_conflicts: Vec, } /// Conflict detection rule @@ -961,9 +947,6 @@ pub struct TimeoutSettings { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ChangeManagementSystem { - change_requests: HashMap, - approval_engine: ChangeApprovalEngine, - impact_analyzer: ChangeImpactAnalyzer, } /// Change request #[derive(Debug, Clone, Serialize, Deserialize)] @@ -1253,8 +1236,6 @@ pub enum ChangeImplementationStatus { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ChangeApprovalEngine { - approval_workflows: HashMap, - approval_history: Vec, } /// Approval record @@ -1299,8 +1280,6 @@ pub enum ApprovalDecision { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct ChangeImpactAnalyzer { - impact_models: HashMap, - dependency_graph: DependencyGraph, } /// Impact model @@ -1367,9 +1346,6 @@ pub struct DependencyEdge { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct AccessControlMatrix { - user_roles: HashMap, - role_permissions: HashMap, - access_reviews: Vec, } /// User role assignment @@ -1575,7 +1551,6 @@ pub enum ReviewStatus { #[derive(Debug)] pub struct SOXAuditLogger { audit_trail: Vec, - retention_policy: AuditRetentionPolicy, /// Async channel sender for persisting audit events to disk audit_writer: Option>, } @@ -1736,14 +1711,12 @@ impl Default for SOXConfig { impl SOXComplianceManager { /// Create new `SOX` compliance manager - pub fn new(config: &SOXConfig) -> Self { + pub fn new(_config: &SOXConfig) -> Self { Self { internal_controls: InternalControlsEngine::new(), segregation_duties: SegregationOfDutiesManager::new(), change_management: ChangeManagementSystem::new(), access_control: AccessControlMatrix::new(), - audit_logger: SOXAuditLogger::new(&config.audit_retention_days), - config: config.clone(), } } @@ -1857,9 +1830,6 @@ impl SOXComplianceManager { "I certify that the internal controls over financial reporting are effective.".to_string() } - fn to_string(&self) -> String { - "SOXComplianceManager".to_string() - } } // Supporting structures @@ -1971,9 +1941,6 @@ pub struct MaterialChange { impl InternalControlsEngine { pub fn new() -> Self { Self { - controls_catalog: HashMap::new(), - control_testing: ControlTestingEngine::new(), - deficiency_tracker: DeficiencyTracker::new(), } } @@ -1993,8 +1960,6 @@ impl InternalControlsEngine { impl ControlTestingEngine { pub fn new() -> Self { Self { - test_schedules: HashMap::new(), - test_results: Vec::new(), } } } @@ -2002,15 +1967,6 @@ impl ControlTestingEngine { impl DeficiencyTracker { pub fn new() -> Self { Self { - deficiencies: HashMap::new(), - metrics: DeficiencyMetrics { - total_deficiencies: 0, - material_weaknesses: 0, - significant_deficiencies: 0, - control_deficiencies: 0, - avg_remediation_time_days: 0.0, - overdue_deficiencies: 0, - }, } } } @@ -2018,13 +1974,6 @@ impl DeficiencyTracker { impl SegregationOfDutiesManager { pub fn new() -> Self { Self { - sod_matrix: SegregationMatrix { - roles: HashMap::new(), - incompatible_combinations: Vec::new(), - required_separations: Vec::new(), - }, - conflict_detector: ConflictDetector::new(), - approval_workflows: HashMap::new(), } } @@ -2036,8 +1985,6 @@ impl SegregationOfDutiesManager { impl ConflictDetector { pub fn new() -> Self { Self { - detection_rules: Vec::new(), - active_conflicts: Vec::new(), } } } @@ -2045,9 +1992,6 @@ impl ConflictDetector { impl ChangeManagementSystem { pub fn new() -> Self { Self { - change_requests: HashMap::new(), - approval_engine: ChangeApprovalEngine::new(), - impact_analyzer: ChangeImpactAnalyzer::new(), } } @@ -2059,8 +2003,6 @@ impl ChangeManagementSystem { impl ChangeApprovalEngine { pub fn new() -> Self { Self { - approval_workflows: HashMap::new(), - approval_history: Vec::new(), } } } @@ -2068,11 +2010,6 @@ impl ChangeApprovalEngine { impl ChangeImpactAnalyzer { pub fn new() -> Self { Self { - impact_models: HashMap::new(), - dependency_graph: DependencyGraph { - nodes: HashMap::new(), - edges: Vec::new(), - }, } } } @@ -2080,9 +2017,6 @@ impl ChangeImpactAnalyzer { impl AccessControlMatrix { pub fn new() -> Self { Self { - user_roles: HashMap::new(), - role_permissions: HashMap::new(), - access_reviews: Vec::new(), } } @@ -2092,7 +2026,7 @@ impl AccessControlMatrix { } impl SOXAuditLogger { - pub fn new(retention_days: &u32) -> Self { + pub fn new(_retention_days: &u32) -> Self { let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); tokio::spawn(async move { @@ -2134,12 +2068,6 @@ impl SOXAuditLogger { Self { audit_trail: Vec::new(), - retention_policy: AuditRetentionPolicy { - retention_days: *retention_days, - archive_location: "sox_audit_archive".to_string(), - compression_enabled: true, - encryption_required: true, - }, audit_writer: Some(tx), } } diff --git a/trading_engine/src/compliance/transaction_reporting.rs b/trading_engine/src/compliance/transaction_reporting.rs index b04bc9481..97c77fd27 100644 --- a/trading_engine/src/compliance/transaction_reporting.rs +++ b/trading_engine/src/compliance/transaction_reporting.rs @@ -43,8 +43,6 @@ use std::collections::HashMap; /// /// Auto-generated documentation placeholder - enhance with specifics pub struct TransactionReporter { - config: TransactionReportingConfig, - report_builder: TransactionReportBuilder, submission_manager: ReportSubmissionManager, validation_engine: ReportValidationEngine, } @@ -702,8 +700,6 @@ pub enum SubmissionStatus { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for report building and template management pub struct TransactionReportBuilder { - config: TransactionReportingConfig, - template_cache: HashMap, } /// Report template for authority-specific formatting @@ -793,9 +789,6 @@ pub enum FieldDataType { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for report submission and retry management pub struct ReportSubmissionManager { - config: TransactionReportingConfig, - submission_queue: Vec, - retry_policy: RetryPolicy, } /// Submission task for queue management @@ -877,8 +870,6 @@ pub struct RetryPolicy { /// Auto-generated documentation placeholder - enhance with specifics // Infrastructure - fields will be used for report validation and schema caching pub struct ReportValidationEngine { - validation_rules: ValidationRules, - schema_cache: HashMap, } /// Validation schema for authority-specific rules @@ -1011,10 +1002,8 @@ impl TransactionReporter { let reporting_config = TransactionReportingConfig::default(); Self { - report_builder: TransactionReportBuilder::new(&reporting_config), submission_manager: ReportSubmissionManager::new(&reporting_config), validation_engine: ReportValidationEngine::new(&reporting_config.validation_rules), - config: reporting_config, } } @@ -1574,10 +1563,8 @@ impl TransactionReportBuilder { /// /// # Returns /// Configured report builder ready for use - pub fn new(config: &TransactionReportingConfig) -> Self { + pub fn new(_config: &TransactionReportingConfig) -> Self { Self { - config: config.clone(), - template_cache: HashMap::new(), } } } @@ -1593,16 +1580,8 @@ impl ReportSubmissionManager { /// /// # Returns /// Configured submission manager with default retry policy - pub fn new(config: &TransactionReportingConfig) -> Self { + pub fn new(_config: &TransactionReportingConfig) -> Self { Self { - config: config.clone(), - submission_queue: Vec::new(), - retry_policy: RetryPolicy { - max_retries: 3, - initial_delay_seconds: 60, - backoff_multiplier: 2.0, - max_delay_seconds: 3600, - }, } } @@ -1640,10 +1619,8 @@ impl ReportValidationEngine { /// /// # Returns /// Configured validation engine ready for use - pub fn new(validation_rules: &ValidationRules) -> Self { + pub fn new(_validation_rules: &ValidationRules) -> Self { Self { - validation_rules: validation_rules.clone(), - schema_cache: HashMap::new(), } } diff --git a/trading_engine/src/events/postgres_writer.rs b/trading_engine/src/events/postgres_writer.rs index 2f3a8ef68..d28abb909 100644 --- a/trading_engine/src/events/postgres_writer.rs +++ b/trading_engine/src/events/postgres_writer.rs @@ -8,11 +8,8 @@ //! - Connection pool management use anyhow::{anyhow, Result}; -use flate2::write::GzEncoder; -use flate2::Compression; use serde_json::Value as JsonValue; use sqlx::PgPool; -use std::io::Write; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; @@ -60,9 +57,6 @@ impl Default for WriterConfig { pub struct PostgresWriter { /// Writer configuration config: WriterConfig, - /// Database connection pool - // Infrastructure - will be used for event persistence - db_pool: PgPool, /// Channel for receiving event batches batch_receiver: Arc>>>, /// Channel sender for submitting batches @@ -101,7 +95,6 @@ impl PostgresWriter { let writer = Self { config: config.clone(), - db_pool, batch_receiver: Arc::new(RwLock::new(Some(batch_receiver))), batch_sender, metrics, @@ -276,7 +269,6 @@ pub struct BatchProcessor { db_pool: PgPool, metrics: Arc, stats: Arc>, - compression_buffer: RwLock>, node_id: String, process_id: i32, } @@ -303,7 +295,6 @@ impl BatchProcessor { db_pool, metrics, stats, - compression_buffer: RwLock::new(Vec::with_capacity(64 * 1024)), // 64KB buffer node_id, process_id, } @@ -478,24 +469,6 @@ impl BatchProcessor { }) } - /// Compress data using gzip - async fn compress_data(&self, data: &str) -> Result> { - let mut buffer = self.compression_buffer.write().await; - buffer.clear(); - - { - let mut encoder = GzEncoder::new(&mut *buffer, Compression::fast()); - encoder - .write_all(data.as_bytes()) - .map_err(|e| anyhow!("Compression write failed: {}", e))?; - encoder - .finish() - .map_err(|e| anyhow!("Compression finish failed: {}", e))?; - } - - Ok(buffer.clone()) - } - /// Build bulk insert query for specified number of events fn build_bulk_insert_query(&self, event_count: usize) -> String { let mut query = String::from( diff --git a/trading_engine/src/features/unified_extractor.rs b/trading_engine/src/features/unified_extractor.rs index 4d302e85d..5336d1f82 100644 --- a/trading_engine/src/features/unified_extractor.rs +++ b/trading_engine/src/features/unified_extractor.rs @@ -13,7 +13,6 @@ //! 4. High-performance implementation with SIMD optimizations //! 5. Type-safe feature engineering with compile-time guarantees -use std::collections::HashMap; use std::time::{Duration, Instant}; use chrono::{DateTime, Datelike, Timelike, Utc}; @@ -21,7 +20,6 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use tracing::{debug, error}; -use crate::simd::SimdMarketDataOps; use common::types::MarketTick; use common::{Price, Quantity, QuoteEvent, Symbol, TradeEvent, Volume}; @@ -459,19 +457,13 @@ impl Default for UnifiedConfig { #[derive(Debug)] pub struct UnifiedFeatureExtractor { config: UnifiedConfig, - simd_processor: Option, - feature_cache: HashMap)>, } impl UnifiedFeatureExtractor { /// Create new unified feature extractor pub fn new(config: UnifiedConfig) -> Self { Self { - simd_processor: crate::simd::SafeSimdDispatcher::new() - .create_market_data_ops() - .ok(), config, - feature_cache: HashMap::new(), } } diff --git a/trading_engine/src/simd/mod.rs b/trading_engine/src/simd/mod.rs index 69a0a0a5f..896f79817 100644 --- a/trading_engine/src/simd/mod.rs +++ b/trading_engine/src/simd/mod.rs @@ -558,7 +558,6 @@ impl SimdConstants { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct SimdPriceOps { - constants: SimdConstants, } impl SimdPriceOps { @@ -579,7 +578,6 @@ impl SimdPriceOps { #[must_use] pub unsafe fn new() -> Self { Self { - constants: SimdConstants::new(), } } @@ -961,7 +959,6 @@ impl SimdPriceOps { /// /// Auto-generated documentation placeholder - enhance with specifics pub struct SimdRiskEngine { - constants: SimdConstants, } impl SimdRiskEngine { @@ -982,7 +979,6 @@ impl SimdRiskEngine { #[must_use] pub unsafe fn new() -> Self { Self { - constants: SimdConstants::new(), } } @@ -1272,7 +1268,6 @@ impl SimdRiskEngine { /// `SIMD`-optimized market data operations #[derive(Debug)] pub struct SimdMarketDataOps { - constants: SimdConstants, } impl SimdMarketDataOps { @@ -1293,7 +1288,6 @@ impl SimdMarketDataOps { #[must_use] pub unsafe fn new() -> Self { Self { - constants: SimdConstants::new(), } } @@ -1568,7 +1562,6 @@ impl SimdMarketDataOps { /// `SSE2` fallback implementation for older processors #[derive(Debug)] pub struct Sse2PriceOps { - constants: Sse2Constants, } /// `SSE2` constants for fallback operations @@ -1613,7 +1606,6 @@ impl Sse2PriceOps { #[must_use] pub unsafe fn new() -> Self { Self { - constants: Sse2Constants::new(), } } diff --git a/trading_engine/src/trading/broker_client.rs b/trading_engine/src/trading/broker_client.rs index 4cb0e36a3..771a9edfd 100644 --- a/trading_engine/src/trading/broker_client.rs +++ b/trading_engine/src/trading/broker_client.rs @@ -12,7 +12,8 @@ use std::sync::Arc; use std::time::Duration; use async_trait::async_trait; -use chrono::{DateTime, Utc}; +#[cfg(test)] +use chrono::Utc; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; @@ -209,53 +210,21 @@ pub enum ConnectionState { } /// Request tracking for TWS communications -// Reserved for future request tracking functionality #[derive(Debug)] struct RequestTracker { next_request_id: AtomicU32, - pending_requests: Arc>>, -} - -// Reserved for future request tracking - fields will be used for timeout/retry logic -#[derive(Debug, Clone)] -struct PendingRequest { - request_id: u32, - request_type: String, - timestamp: DateTime, - order_id: Option, } impl RequestTracker { fn new() -> Self { Self { next_request_id: AtomicU32::new(1), - pending_requests: Arc::new(RwLock::new(HashMap::new())), } } fn next_id(&self) -> u32 { self.next_request_id.fetch_add(1, Ordering::SeqCst) } - - async fn track_request(&self, request_type: &str, order_id: Option) -> u32 { - let request_id = self.next_id(); - let request = PendingRequest { - request_id, - request_type: request_type.to_string(), - timestamp: Utc::now(), - order_id, - }; - - self.pending_requests - .write() - .await - .insert(request_id, request); - request_id - } - - async fn complete_request(&self, request_id: u32) -> Option { - self.pending_requests.write().await.remove(&request_id) - } } /// Interactive Brokers TWS/Gateway Adapter