#![allow(missing_docs)] // Internal implementation details
#![allow(missing_debug_implementations)] // Not all types need Debug
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::too_many_lines)]
// Backtesting domain lints: numerical simulation computations
#![allow(clippy::doc_markdown)] // Technical terms in doc comments
#![allow(clippy::unnecessary_wraps)] // Result wrapping needed for trait consistency
#![allow(clippy::missing_errors_doc)] // Internal APIs don't need full error documentation
#![allow(clippy::cast_precision_loss)] // Acceptable in backtesting calculations
#![allow(clippy::cast_possible_truncation)] // Type conversions validated in context
#![allow(clippy::unused_async)] // Async needed for trait implementations
#![allow(clippy::new_without_default)] // Many types need config params
#![allow(clippy::cognitive_complexity)] // Backtesting logic is inherently complex
#![allow(clippy::similar_names)] // Financial variables often have similar names
#![allow(clippy::default_numeric_fallback)] // Float literals are contextually typed
#![allow(clippy::float_arithmetic)] // Backtesting calculations require float arithmetic
#![allow(clippy::as_conversions)] // Type conversions are carefully managed
#![allow(clippy::missing_const_for_fn)] // Const fn not critical
#![allow(clippy::must_use_candidate)] // Not all functions need must_use
#![allow(clippy::integer_division)] // Integer division is intentional
#![allow(clippy::indexing_slicing)] // Bounds checked in context
#![allow(clippy::arithmetic_side_effects)] // Math uses checked where needed
#![allow(clippy::unused_self)] // Self parameter needed for trait consistency
#![allow(clippy::manual_let_else)] // if-let pattern preferred in error paths
#![allow(clippy::if_not_else)] // Negated conditions preferred in some backtesting logic
#![allow(clippy::uninlined_format_args)] // Non-inlined format args for readability
#![allow(clippy::match_same_arms)] // Explicit match arms for clarity
#![allow(clippy::clone_on_copy)] // Explicit clone for clarity on Copy types
#![allow(clippy::cast_sign_loss)] // Sign loss validated in context
#![allow(clippy::cast_possible_wrap)] // Wrap validated in context
#![allow(clippy::map_unwrap_or)] // map().unwrap_or() preferred for readability
#![allow(clippy::used_underscore_binding)] // Underscore-prefixed bindings used intentionally
#![allow(clippy::unreadable_literal)] // Large numeric literals in financial calculations
#![allow(clippy::type_complexity)] // Complex types in strategy generics
#![allow(clippy::cloned_instead_of_copied)] // Explicit cloned() for clarity
#![allow(clippy::wildcard_imports)] // Prelude-style imports
#![allow(clippy::while_immutable_condition)] // Loop conditions managed externally
#![allow(clippy::unnecessary_literal_bound)] // Literal bounds for clarity
#![allow(clippy::single_match_else)] // Explicit match preferred for clarity
#![allow(clippy::redundant_closure_for_method_calls)] // Explicit closures for readability
#![allow(clippy::needless_borrow)] // Explicit borrows for clarity
#![allow(clippy::enum_glob_use)] // Enum glob imports for conciseness
#![allow(clippy::derivable_impls)] // Custom Default impls with domain-specific values
#![allow(clippy::comparison_chain)] // Explicit comparison chains for clarity
#![allow(clippy::collapsible_else_if)] // Separate else-if preferred for readability

//! Historical Market Replay System for Backtesting
//!
//! This crate provides a comprehensive backtesting framework for trading strategies
//! with tick-by-tick historical market data replay, strategy execution, and performance analytics.
//!
//! # Features
//!
//! - **Market Data Replay**: Replay historical market data with configurable speed and filtering
//! - **Strategy Testing**: Execute trading strategies against historical data with realistic execution
//! - **Performance Analytics**: Comprehensive performance metrics including risk, return, and drawdown analysis
//! - **Tick-by-tick Precision**: Support for high-frequency tick-level backtesting
//! - **Multiple Data Sources**: CSV, Parquet, and database support for historical data
//! - **Risk Management**: Built-in position sizing, stop losses, and risk controls
//!
//! # Quick Start
//!
//! ```rust,no_run
//! use backtesting::{BacktestEngine, BacktestConfig};
// ReplayConfig will be imported via re-export
// use chrono::Utc;
// use common::Order;
use common::Symbol;
// Removed unused imports
//
// #[tokio::main]
// async fn main() -> anyhow::Result<()> {
//     let config = BacktestConfig {
//         initial_capital: Decimal::from(100000),
//         replay_config: ReplayConfig {
//             start_time: Utc::now() - Duration::days(30),
//             end_time: Utc::now(),
//             tick_by_tick: true,
//             ..Default::default()
//         },
//         ..Default::default()
//     };
//
//     let mut engine = BacktestEngine::new(config).await?;
//     let results = engine.run().await?;
//
//     info!("Total Return: {:.2}%", results.strategy_result.total_return * Decimal::from(100));
//     info!("Sharpe Ratio: {:.2}", results.strategy_result.sharpe_ratio);
//     info!("Max Drawdown: {:.2}%", results.strategy_result.max_drawdown * Decimal::from(100));
//
//     Ok(())
// }
/// ```
use std::{sync::Arc, time::Instant};

use anyhow::Result;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use tokio::sync::{mpsc, RwLock};
use tracing::{info, warn};

use rust_decimal::Decimal;

// mod types; // Removed - using core::prelude types instead

pub mod dbn_converter;
pub mod dbn_replay;
pub mod metrics;
pub mod model_loader;
pub mod replay_engine;
pub mod slippage;
pub mod strategies;
pub mod strategy_runner;
pub mod strategy_tester;

// Re-export types for public API
pub use model_loader::{load_models_for_backtest, BacktestMLModel, ModelSpec};
pub use metrics::{MetricsCalculator, PerformanceAnalytics};
pub use replay_engine::{MarketReplay, ReplayConfig};
pub use strategies::{DQNAction, DQNReplayStrategy, PositionState, TradingActionType};
pub use strategy_runner::{
    create_adaptive_strategy_with_config, AdaptiveStrategyConfig, FeatureSettings, RiskSettings,
};
pub use slippage::{
    FixedSlippage, RegimeAwareSlippage, SlippageContext, SlippageModel, SpreadProfile,
    VolatilityRegime, VolumeImpactSlippage,
};
pub use strategy_tester::{
    PerformanceSnapshot, SignalType, Strategy, StrategyConfig, StrategyContext, StrategyResult,
    StrategyTester, TradeRecord, TradingSignal,
};

// Import events from trading_engine types
use trading_engine::types::events::MarketEvent;

/// Main backtesting engine configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BacktestConfig {
    /// Initial capital for backtesting
    pub initial_capital: Decimal,
    /// Market data replay configuration
    pub replay_config: ReplayConfig,
    /// Strategy configuration
    pub strategy_config: StrategyConfig,
    /// Risk-free rate for Sharpe ratio calculation
    pub risk_free_rate: Decimal,
    /// Enable detailed logging
    pub enable_logging: bool,
    /// Performance snapshot interval (seconds)
    pub snapshot_interval: u64,
    /// Maximum memory usage (bytes)
    pub max_memory_usage: usize,
}

impl Default for BacktestConfig {
    fn default() -> Self {
        Self {
            initial_capital: Decimal::from(100000),
            replay_config: ReplayConfig::default(),
            strategy_config: StrategyConfig::default(),
            risk_free_rate: Decimal::new(2, 2), // 2% annually
            enable_logging: true,
            snapshot_interval: 3600,              // 1 hour
            max_memory_usage: 1024 * 1024 * 1024, // 1GB
        }
    }
}

/// Main backtesting engine that orchestrates market replay and strategy execution
pub struct BacktestEngine {
    /// Configuration
    config: BacktestConfig,
    /// Market data replay engine
    market_replay: Arc<MarketReplay>,
    /// Strategy tester
    strategy_tester: Option<StrategyTester>,
    /// Performance metrics calculator
    metrics_calculator: Arc<RwLock<MetricsCalculator>>,
    /// Current execution state
    state: Arc<RwLock<BacktestState>>,
    /// Performance monitoring
    performance_monitor: Arc<PerformanceMonitor>,
}

/// Current state of backtesting engine
#[derive(Debug, Clone)]
pub struct BacktestState {
    /// Is backtest running
    pub is_running: bool,
    /// Is backtest paused
    pub is_paused: bool,
    /// Backtest start time (wall clock)
    pub start_time: Option<Instant>,
    /// Current simulation time
    pub current_sim_time: Option<DateTime<Utc>>,
    /// Events processed
    pub events_processed: u64,
    /// Current portfolio value
    pub portfolio_value: Decimal,
    /// Total trades executed
    pub trades_executed: u64,
    /// Last performance snapshot time
    pub last_snapshot: Option<DateTime<Utc>>,
}

impl Default for BacktestState {
    fn default() -> Self {
        Self {
            is_running: false,
            is_paused: false,
            start_time: None,
            current_sim_time: None,
            events_processed: 0,
            portfolio_value: Decimal::ZERO,
            trades_executed: 0,
            last_snapshot: None,
        }
    }
}

/// Performance monitoring for the backtesting engine
#[derive(Debug)]
pub struct PerformanceMonitor {
    /// Memory usage tracking
    memory_usage: Arc<std::sync::atomic::AtomicUsize>,
    /// Event processing rate
    events_per_second: Arc<std::sync::atomic::AtomicU64>,
    /// Last performance check
    last_check: Arc<RwLock<Option<Instant>>>,
}

impl Default for PerformanceMonitor {
    fn default() -> Self {
        Self {
            memory_usage: Arc::new(std::sync::atomic::AtomicUsize::new(0)),
            events_per_second: Arc::new(std::sync::atomic::AtomicU64::new(0)),
            last_check: Arc::new(RwLock::new(None)),
        }
    }
}

impl BacktestEngine {
    /// Create a new backtesting engine
    pub async fn new(config: BacktestConfig) -> Result<Self> {
        info!(
            "Initializing backtesting engine with initial capital: {}",
            config.initial_capital
        );

        let market_replay = Arc::new(MarketReplay::new(config.replay_config.clone()));
        let metrics_calculator =
            Arc::new(RwLock::new(MetricsCalculator::new(config.risk_free_rate)));
        let performance_monitor = Arc::new(PerformanceMonitor::default());

        Ok(Self {
            config,
            market_replay,
            strategy_tester: None,
            metrics_calculator,
            state: Arc::new(RwLock::new(BacktestState::default())),
            performance_monitor,
        })
    }

    /// Set the trading strategy to test
    pub async fn set_strategy(&mut self, strategy: Box<dyn Strategy>) -> Result<()> {
        info!("Setting strategy: {}", strategy.name());

        let strategy_tester = StrategyTester::new(
            strategy,
            self.config.strategy_config.clone(),
            Arc::clone(&self.market_replay),
            self.config.initial_capital,
        );

        self.strategy_tester = Some(strategy_tester);
        Ok(())
    }

    /// Run the complete backtesting process
    pub async fn run(&mut self) -> Result<BacktestResult> {
        if self.strategy_tester.is_none() {
            return Err(anyhow::anyhow!(
                "No strategy set. Call set_strategy() first."
            ));
        }

        info!("Starting backtesting run");

        // Update state
        {
            let mut state = self.state.write().await;
            state.is_running = true;
            state.start_time = Some(Instant::now());
            state.current_sim_time = Some(self.config.replay_config.start_time);
        }

        // Start performance monitoring
        let monitor_handle = self.start_performance_monitoring().await;

        // Run the strategy test
        let strategy_result = match self.strategy_tester.as_mut() {
            Some(tester) => tester.run_test().await?,
            None => return Err(anyhow::anyhow!("Strategy tester not initialized")),
        };

        // Calculate comprehensive analytics
        let analytics = {
            let calculator = self.metrics_calculator.read().await;
            calculator.calculate_analytics()?
        };

        // Stop performance monitoring
        monitor_handle.abort();

        // Update final state
        {
            let mut state = self.state.write().await;
            state.is_running = false;
            state.portfolio_value = strategy_result.final_value;
            state.trades_executed = strategy_result.total_trades;
        }

        let backtest_result = BacktestResult {
            strategy_result,
            analytics,
            execution_stats: self.get_execution_stats().await,
            config: self.config.clone(),
        };

        info!(
            "Backtesting completed. Total return: {:.2}%, Sharpe ratio: {:.2}",
            backtest_result.strategy_result.total_return * Decimal::from(100),
            backtest_result.strategy_result.sharpe_ratio
        );

        Ok(backtest_result)
    }

    /// Run backtesting with real-time monitoring
    pub async fn run_with_monitoring(
        &mut self,
    ) -> Result<(BacktestResult, mpsc::UnboundedReceiver<MonitoringUpdate>)> {
        let (update_sender, update_receiver) = mpsc::unbounded_channel();

        // Clone necessary data for monitoring task
        let state = Arc::clone(&self.state);
        let performance_monitor = Arc::clone(&self.performance_monitor);

        // Start monitoring task
        let monitoring_handle = tokio::spawn(async move {
            let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(1));

            loop {
                interval.tick().await;

                let current_state = state.read().await.clone();
                if !current_state.is_running {
                    break;
                }

                let update = MonitoringUpdate {
                    timestamp: Utc::now(),
                    events_processed: current_state.events_processed,
                    portfolio_value: current_state.portfolio_value,
                    trades_executed: current_state.trades_executed,
                    memory_usage: performance_monitor
                        .memory_usage
                        .load(std::sync::atomic::Ordering::Relaxed),
                    events_per_second: performance_monitor
                        .events_per_second
                        .load(std::sync::atomic::Ordering::Relaxed),
                    current_sim_time: current_state.current_sim_time,
                };

                if update_sender.send(update).is_err() {
                    break; // Receiver dropped
                }
            }
        });

        // Run the backtest
        let result = self.run().await;

        // Clean up monitoring
        monitoring_handle.abort();

        match result {
            Ok(backtest_result) => Ok((backtest_result, update_receiver)),
            Err(e) => Err(e),
        }
    }

    /// Pause the backtesting process
    pub async fn pause(&self) -> Result<()> {
        {
            let mut state = self.state.write().await;
            state.is_paused = true;
        }

        self.market_replay.pause().await;
        info!("Backtesting paused");
        Ok(())
    }

    /// Resume the backtesting process
    pub async fn resume(&self) -> Result<()> {
        {
            let mut state = self.state.write().await;
            state.is_paused = false;
        }

        self.market_replay.resume().await;
        info!("Backtesting resumed");
        Ok(())
    }

    /// Stop the backtesting process
    pub async fn stop(&self) -> Result<()> {
        {
            let mut state = self.state.write().await;
            state.is_running = false;
            state.is_paused = false;
        }

        self.market_replay.stop().await;
        info!("Backtesting stopped");
        Ok(())
    }

    /// Get current backtesting state
    pub async fn get_state(&self) -> BacktestState {
        self.state.read().await.clone()
    }

    /// Get current performance metrics
    pub async fn get_current_analytics(&self) -> Result<PerformanceAnalytics> {
        let calculator = self.metrics_calculator.read().await;
        calculator.calculate_analytics()
    }

    /// Add market data for replay
    pub async fn add_market_data(&self, _symbol: Symbol, _data: Vec<MarketEvent>) -> Result<()> {
        // This would integrate with the market replay engine to add data
        // Implementation depends on the specific data loading mechanism
        warn!("add_market_data not yet implemented - use ReplayConfig data sources instead");
        Ok(())
    }

    /// Run backtesting with adaptive strategy using real ML models
    pub async fn run_with_adaptive_strategy(
        &mut self,
        adaptive_config: AdaptiveStrategyConfig,
    ) -> Result<BacktestResult> {
        info!("Starting backtesting with adaptive ML strategy");

        // Create adaptive strategy
        let adaptive_strategy = Box::new(create_adaptive_strategy_with_config(adaptive_config));

        // Set the strategy
        self.set_strategy(adaptive_strategy).await?;

        // Run the backtest
        let result = self.run().await?;

        info!(
            "Adaptive ML backtesting completed. Models used: {:?}",
            result.config.strategy_config
        );

        Ok(result)
    }

    /// Run backtesting with parallel model evaluation
    pub async fn run_with_parallel_models(
        &mut self,
        model_names: Vec<String>,
    ) -> Result<Vec<BacktestResult>> {
        info!(
            "Starting parallel backtesting with {} models",
            model_names.len()
        );

        let mut results = Vec::new();

        for model_name in model_names {
            info!("Running backtest with model: {}", model_name);

            let adaptive_config = AdaptiveStrategyConfig {
                active_models: vec![model_name.clone()],
                ..AdaptiveStrategyConfig::default()
            };

            // Clone the engine configuration for each model test
            let mut model_engine = BacktestEngine::new(self.config.clone()).await?;
            let result = model_engine
                .run_with_adaptive_strategy(adaptive_config)
                .await?;

            results.push(result);
        }

        info!(
            "Parallel model backtesting completed for {} models",
            results.len()
        );
        Ok(results)
    }

    /// Run ensemble backtesting comparing individual models vs ensemble
    pub async fn run_ensemble_comparison(
        &mut self,
        model_names: Vec<String>,
    ) -> Result<EnsembleComparisonResult> {
        info!(
            "Starting ensemble comparison with {} models",
            model_names.len()
        );

        // Test individual models
        let individual_results = self.run_with_parallel_models(model_names.clone()).await?;

        // Test ensemble
        let ensemble_config = AdaptiveStrategyConfig {
            active_models: model_names.clone(),
            ..AdaptiveStrategyConfig::default()
        };

        let mut ensemble_engine = BacktestEngine::new(self.config.clone()).await?;
        let ensemble_result = ensemble_engine
            .run_with_adaptive_strategy(ensemble_config)
            .await?;

        // Calculate comparison metrics before moving individual_results
        let comparison_metrics = self
            .calculate_comparison_metrics(&individual_results, &ensemble_result)
            .await;

        let comparison = EnsembleComparisonResult {
            individual_results,
            ensemble_result,
            models_tested: model_names,
            comparison_metrics,
        };

        info!(
            "Ensemble comparison completed. Ensemble Sharpe: {:.3}, Best Individual: {:.3}",
            comparison.ensemble_result.strategy_result.sharpe_ratio,
            comparison.comparison_metrics.best_individual_sharpe
        );

        Ok(comparison)
    }

    /// Start performance monitoring task
    async fn start_performance_monitoring(&self) -> tokio::task::JoinHandle<()> {
        let performance_monitor = Arc::clone(&self.performance_monitor);

        tokio::spawn(async move {
            let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(5));

            loop {
                interval.tick().await;

                // Update memory usage
                if let Ok(info) = sys_info::mem_info() {
                    let used_memory = (info.total - info.free) * 1024; // Convert to bytes
                    performance_monitor
                        .memory_usage
                        .store(used_memory as usize, std::sync::atomic::Ordering::Relaxed);
                }

                // Update last check time
                {
                    let mut last_check = performance_monitor.last_check.write().await;
                    *last_check = Some(Instant::now());
                }
            }
        })
    }

    /// Calculate comparison metrics between individual models and ensemble
    async fn calculate_comparison_metrics(
        &self,
        individual_results: &[BacktestResult],
        ensemble_result: &BacktestResult,
    ) -> ComparisonMetrics {
        let individual_sharpes: Vec<Decimal> = individual_results
            .iter()
            .map(|r| r.strategy_result.sharpe_ratio)
            .collect();

        let best_individual_sharpe = individual_sharpes
            .iter()
            .max()
            .copied()
            .unwrap_or(Decimal::ZERO);

        let avg_individual_sharpe = if !individual_sharpes.is_empty() {
            individual_sharpes.iter().sum::<Decimal>() / Decimal::from(individual_sharpes.len())
        } else {
            Decimal::ZERO
        };

        let ensemble_sharpe = ensemble_result.strategy_result.sharpe_ratio;

        ComparisonMetrics {
            best_individual_sharpe,
            avg_individual_sharpe,
            ensemble_sharpe,
            ensemble_improvement: ensemble_sharpe - best_individual_sharpe,
            diversification_benefit: ensemble_sharpe - avg_individual_sharpe,
        }
    }

    /// Get execution statistics
    async fn get_execution_stats(&self) -> ExecutionStats {
        let state = self.state.read().await;
        let wall_time = state
            .start_time
            .map(|start| start.elapsed())
            .unwrap_or_default();

        ExecutionStats {
            wall_time_seconds: wall_time.as_secs(),
            events_processed: state.events_processed,
            trades_executed: state.trades_executed,
            memory_peak_mb: self
                .performance_monitor
                .memory_usage
                .load(std::sync::atomic::Ordering::Relaxed)
                / (1024 * 1024),
            events_per_second: if wall_time.as_secs() > 0 {
                state.events_processed / wall_time.as_secs()
            } else {
                0
            },
        }
    }
}

/// Complete backtesting result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BacktestResult {
    /// Strategy execution results
    pub strategy_result: StrategyResult,
    /// Comprehensive performance analytics
    pub analytics: PerformanceAnalytics,
    /// Execution statistics
    pub execution_stats: ExecutionStats,
    /// Configuration used
    pub config: BacktestConfig,
}

/// Execution performance statistics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionStats {
    /// Wall clock time in seconds
    pub wall_time_seconds: u64,
    /// Total events processed
    pub events_processed: u64,
    /// Total trades executed
    pub trades_executed: u64,
    /// Peak memory usage in MB
    pub memory_peak_mb: usize,
    /// Average events per second
    pub events_per_second: u64,
}

/// Real-time monitoring update
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringUpdate {
    /// Update timestamp
    pub timestamp: DateTime<Utc>,
    /// Events processed so far
    pub events_processed: u64,
    /// Current portfolio value
    pub portfolio_value: Decimal,
    /// Trades executed so far
    pub trades_executed: u64,
    /// Current memory usage in bytes
    pub memory_usage: usize,
    /// Current events per second
    pub events_per_second: u64,
    /// Current simulation time
    pub current_sim_time: Option<DateTime<Utc>>,
}

/// Result of ensemble vs individual model comparison
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnsembleComparisonResult {
    /// Results from individual model backtests
    pub individual_results: Vec<BacktestResult>,
    /// Result from ensemble backtest
    pub ensemble_result: BacktestResult,
    /// Names of models tested
    pub models_tested: Vec<String>,
    /// Comparison metrics
    pub comparison_metrics: ComparisonMetrics,
}

/// Metrics comparing ensemble vs individual model performance
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComparisonMetrics {
    /// Best individual model Sharpe ratio
    pub best_individual_sharpe: Decimal,
    /// Average individual model Sharpe ratio
    pub avg_individual_sharpe: Decimal,
    /// Ensemble Sharpe ratio
    pub ensemble_sharpe: Decimal,
    /// Improvement of ensemble over best individual
    pub ensemble_improvement: Decimal,
    /// Diversification benefit (ensemble vs average)
    pub diversification_benefit: Decimal,
}

// Re-export commonly used types
// Note: DateTime, Utc, and Decimal are already imported above, no need to re-export

#[cfg(test)]
mod tests {
    use super::*;
    use common::{Order, OrderSide, OrderStatus, Position, Price, Quantity};
    use num_traits::ToPrimitive;
    use rust_decimal_macros::dec;
    use std::collections::HashMap;

    #[tokio::test]
    async fn test_backtest_engine_creation() {
        let config = BacktestConfig::default();
        let engine = BacktestEngine::new(config).await;
        assert!(
            engine.is_ok(),
            "BacktestEngine creation should not fail in test: {:?}",
            engine.err()
        );
        let engine = engine.unwrap();

        let state = engine.get_state().await;
        assert!(!state.is_running);
        assert!(!state.is_paused);
    }

    #[tokio::test]
    async fn test_backtest_config_default() {
        let config = BacktestConfig::default();
        assert_eq!(config.initial_capital, Decimal::from(100000));
        assert_eq!(config.risk_free_rate, Decimal::new(2, 2));
        assert!(config.enable_logging);
    }

    // Real Mean Reversion Strategy for Testing
    struct MeanReversionStrategy {
        lookback_period: usize,
        price_history: Vec<Decimal>,
        position_size: Decimal,
        entry_threshold: Decimal,
        exit_threshold: Decimal,
        current_position: Option<Position>,
        position_side: Option<OrderSide>,
        trades_executed: usize,
        total_pnl: Decimal,
        max_drawdown: Decimal,
        peak_value: Decimal,
        initial_capital: Decimal,
    }

    impl MeanReversionStrategy {
        fn new() -> Self {
            Self {
                lookback_period: 20,
                price_history: Vec::new(),
                position_size: dec!(0.02),  // 2% position size
                entry_threshold: dec!(2.0), // 2 standard deviations
                exit_threshold: dec!(0.5),  // 0.5 standard deviations
                current_position: None,
                position_side: None,
                trades_executed: 0,
                total_pnl: Decimal::ZERO,
                max_drawdown: Decimal::ZERO,
                peak_value: Decimal::ZERO,
                initial_capital: Decimal::ZERO,
            }
        }

        fn calculate_z_score(&self, current_price: Decimal) -> Option<Decimal> {
            if self.price_history.len() < self.lookback_period {
                return None;
            }

            let recent_prices =
                &self.price_history[self.price_history.len() - self.lookback_period..];
            let mean = recent_prices.iter().sum::<Decimal>() / Decimal::from(recent_prices.len());

            let variance = recent_prices
                .iter()
                .map(|price| {
                    let diff = *price - mean;
                    diff * diff
                })
                .sum::<Decimal>()
                / Decimal::from(recent_prices.len());

            // Calculate standard deviation using f64 for sqrt operation
            let variance_f64 = variance.to_f64().unwrap_or(0.0);
            let std_dev = Decimal::try_from(variance_f64.sqrt()).unwrap_or(Decimal::ZERO);

            if std_dev > Decimal::ZERO {
                Some((current_price - mean) / std_dev)
            } else {
                None
            }
        }

        fn should_enter_long(&self, z_score: Decimal) -> bool {
            z_score < -self.entry_threshold && self.current_position.is_none()
        }

        fn should_enter_short(&self, z_score: Decimal) -> bool {
            z_score > self.entry_threshold && self.current_position.is_none()
        }

        fn should_exit_position(&self, z_score: Decimal) -> bool {
            if let Some(ref _position) = self.current_position {
                if let Some(ref side) = self.position_side {
                    match side {
                        OrderSide::Buy => z_score > -self.exit_threshold, // Long position
                        OrderSide::Sell => z_score < self.exit_threshold, // Short position
                    }
                } else {
                    false
                }
            } else {
                false
            }
        }
    }

    #[async_trait::async_trait(?Send)]
    impl Strategy for MeanReversionStrategy {
        fn name(&self) -> &str {
            "mean_reversion_strategy"
        }

        async fn initialize(
            &mut self,
            initial_capital: Decimal,
            _config: StrategyConfig,
        ) -> Result<()> {
            self.initial_capital = initial_capital;
            self.peak_value = initial_capital;
            info!(
                "Mean Reversion Strategy initialized with capital: {}",
                initial_capital
            );
            Ok(())
        }

        async fn on_market_event(
            &mut self,
            event: &MarketEvent,
            context: &StrategyContext,
        ) -> Result<Vec<TradingSignal>> {
            let mut signals = Vec::new();

            if let MarketEvent::Trade { symbol, price, .. } = event {
                self.price_history.push((*price).into());

                // Keep only recent price history
                if self.price_history.len() > self.lookback_period * 2 {
                    self.price_history.drain(0..self.lookback_period);
                }

                if let Some(z_score) = self.calculate_z_score((*price).into()) {
                    // Generate trading signals based on mean reversion logic
                    if self.should_enter_long(z_score) {
                        let price_decimal: Decimal = (*price).into();
                        let quantity = (context.account_balance * self.position_size
                            / price_decimal)
                            .round_dp(0);
                        let mut metadata = HashMap::new();
                        metadata
                            .insert("strategy".to_string(), serde_json::json!("mean_reversion"));
                        metadata.insert("z_score".to_string(), serde_json::json!(z_score));
                        metadata.insert("signal_type".to_string(), serde_json::json!("enter_long"));

                        signals.push(TradingSignal {
                            symbol: symbol.clone(),
                            signal_type: SignalType::Buy,
                            quantity: Quantity::from_f64(quantity.to_f64().unwrap_or(0.0))
                                .unwrap_or(Quantity::ZERO),
                            target_price: Some(*price),
                            stop_loss: None,
                            take_profit: None,
                            confidence: dec!(0.8),
                            metadata,
                        });
                    } else if self.should_enter_short(z_score) {
                        let price_decimal: Decimal = (*price).into();
                        let quantity = (context.account_balance * self.position_size
                            / price_decimal)
                            .round_dp(0);
                        let mut metadata = HashMap::new();
                        metadata
                            .insert("strategy".to_string(), serde_json::json!("mean_reversion"));
                        metadata.insert("z_score".to_string(), serde_json::json!(z_score));
                        metadata
                            .insert("signal_type".to_string(), serde_json::json!("enter_short"));

                        signals.push(TradingSignal {
                            symbol: symbol.clone(),
                            signal_type: SignalType::Sell,
                            quantity: Quantity::from_f64(quantity.to_f64().unwrap_or(0.0))
                                .unwrap_or(Quantity::ZERO),
                            target_price: Some(*price),
                            stop_loss: None,
                            take_profit: None,
                            confidence: dec!(0.8),
                            metadata,
                        });
                    } else if self.should_exit_position(z_score) {
                        if let Some(ref position) = self.current_position {
                            if let Some(ref side) = self.position_side {
                                let exit_signal_type = match side {
                                    OrderSide::Buy => SignalType::Sell,   // Exit long position
                                    OrderSide::Sell => SignalType::Cover, // Exit short position
                                };

                                let mut metadata = HashMap::new();
                                metadata.insert(
                                    "strategy".to_string(),
                                    serde_json::json!("mean_reversion"),
                                );
                                metadata.insert("z_score".to_string(), serde_json::json!(z_score));
                                metadata.insert(
                                    "signal_type".to_string(),
                                    serde_json::json!("exit_position"),
                                );

                                signals.push(TradingSignal {
                                    symbol: symbol.clone(),
                                    signal_type: exit_signal_type,
                                    quantity: Quantity::from_f64(
                                        position.quantity.to_f64().unwrap_or(0.0),
                                    )
                                    .unwrap_or(Quantity::ZERO),
                                    target_price: Some(*price),
                                    stop_loss: None,
                                    take_profit: None,
                                    confidence: dec!(0.8),
                                    metadata,
                                });
                            }
                        }
                    }
                }
            }

            Ok(signals)
        }

        async fn on_order_update(
            &mut self,
            order: &Order,
            _context: &StrategyContext,
        ) -> anyhow::Result<()> {
            if order.status == OrderStatus::Filled {
                self.trades_executed += 1;
                let display_price = order
                    .average_price
                    .unwrap_or(order.price.unwrap_or(Price::ZERO));
                info!(
                    "Order filled: {} {} @ {}",
                    order.side, order.quantity, display_price
                );
            }
            Ok(())
        }

        async fn on_position_update(
            &mut self,
            position: &Position,
            context: &StrategyContext,
        ) -> anyhow::Result<()> {
            self.current_position = Some(position.clone());

            // Determine position side based on quantity sign
            let position_value = position.quantity.to_f64().unwrap_or(0.0);
            if position_value > 0.0 {
                self.position_side = Some(OrderSide::Buy); // Long position
            } else if position_value < 0.0 {
                self.position_side = Some(OrderSide::Sell); // Short position
            } else {
                self.position_side = None; // No position
            }

            // Update P&L tracking
            let current_value = context.account_balance;
            if current_value > self.peak_value {
                self.peak_value = current_value;
            }

            let current_drawdown = (self.peak_value - current_value) / self.peak_value;
            if current_drawdown > self.max_drawdown {
                self.max_drawdown = current_drawdown;
            }

            self.total_pnl = current_value - self.initial_capital;

            Ok(())
        }

        async fn finalize(&mut self, context: &StrategyContext) -> Result<StrategyResult> {
            let total_return = if self.initial_capital > Decimal::ZERO {
                self.total_pnl / self.initial_capital
            } else {
                Decimal::ZERO
            };

            let annualized_return = total_return; // Simplified for test

            let win_rate = if self.trades_executed > 0 {
                // Simplified calculation - in reality would track individual trade outcomes
                if self.total_pnl > Decimal::ZERO {
                    dec!(0.6)
                } else {
                    dec!(0.4)
                }
            } else {
                Decimal::ZERO
            };

            let avg_trade_return = if self.trades_executed > 0 {
                self.total_pnl / Decimal::from(self.trades_executed)
            } else {
                Decimal::ZERO
            };

            let sharpe_ratio = if self.max_drawdown > Decimal::ZERO {
                annualized_return / self.max_drawdown // Simplified Sharpe calculation
            } else {
                Decimal::ZERO
            };

            Ok(StrategyResult {
                strategy_name: "mean_reversion_strategy".to_string(),
                total_return,
                annualized_return,
                max_drawdown: self.max_drawdown,
                sharpe_ratio,
                total_trades: self.trades_executed as u64,
                win_rate,
                avg_trade_return,
                final_value: context.account_balance,
                trades: vec![], // Would be populated with actual trade records
                performance_timeline: vec![], // Would be populated with performance snapshots
            })
        }

        async fn get_state(&self) -> Result<serde_json::Value> {
            Ok(serde_json::json!({
                "name": "mean_reversion_strategy",
                "lookback_period": self.lookback_period,
                "position_size": self.position_size,
                "entry_threshold": self.entry_threshold,
                "exit_threshold": self.exit_threshold,
                "trades_executed": self.trades_executed,
                "total_pnl": self.total_pnl,
                "max_drawdown": self.max_drawdown,
                "current_position": self.current_position
            }))
        }
    }

    #[tokio::test]
    async fn test_strategy_setting() {
        let config = BacktestConfig::default();
        let engine_result = BacktestEngine::new(config).await;
        assert!(
            engine_result.is_ok(),
            "BacktestEngine creation should not fail in test: {:?}",
            engine_result.err()
        );
        let mut engine = engine_result.unwrap();

        let strategy = Box::new(MeanReversionStrategy::new());
        let result = engine.set_strategy(strategy).await;
        assert!(
            result.is_ok(),
            "Strategy setting should not fail in test: {:?}",
            result.err()
        );

        assert!(engine.strategy_tester.is_some());
    }
}
