//! Risk management unit tests
//! 
//! Tests risk controls, position limits, and safety mechanisms
//! with focus on preventing financial losses.

// CANONICAL TYPE IMPORTS - Use types::prelude::Decimal
use std::collections::HashMap;

#[cfg(test)]
mod tests {
    use super::*;
    
    #[tokio::test]
    async fn test_position_limit_validation() {
        let mut risk_engine = RiskEngine::new();
        risk_engine.set_position_limit(
            Symbol::new("AAPL".to_string()).unwrap(),
            Quantity::new(Decimal::from(10000)).map_err(|e| format!("Failed to create position limit: {}", e)).unwrap()
        );
        
        let large_order = Order {
            id: OrderId::from("LARGE-001"),
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Market,
            quantity: Quantity::new(Decimal::from(15000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(), // Exceeds limit
            price: None,
            time_in_force: TimeInForce::ImmediateOrCancel,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let validation_result = risk_engine.validate_order(&large_order).await;
        assert!(validation_result.is_err());
        
        let error = validation_result.unwrap_err();
        assert!(error.to_string().contains("position limit"));
    }
    
    #[tokio::test]
    async fn test_concentration_risk_check() {
        let mut risk_engine = RiskEngine::new();
        risk_engine.set_concentration_limit(Decimal::from_str("0.25").unwrap()); // 25% max
        
        // Current portfolio value: $1,000,000
        let portfolio_value = Money::new(Decimal::from(1_000_000), Currency::USD);
        risk_engine.set_portfolio_value(portfolio_value);
        
        // Existing position: AAPL $200,000 (20% of portfolio)
        let existing_position = Position {
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create position quantity: {}", e)).unwrap(),
            average_price: Price::new(Decimal::from(200)).unwrap(),
            realized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
            unrealized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
            last_updated: chrono::Utc::now(),
        };
        risk_engine.add_position(existing_position);
        
        // New order would add $100,000 more AAPL (total would be 30%, exceeding 25% limit)
        let concentration_order = Order {
            id: OrderId::from("CONC-001"),
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(500)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(200)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let validation_result = risk_engine.validate_order(&concentration_order).await;
        assert!(validation_result.is_err());
        
        let error = validation_result.unwrap_err();
        assert!(error.to_string().contains("concentration"));
    }
    
    #[tokio::test]
    async fn test_daily_loss_limit() {
        let mut risk_engine = RiskEngine::new();
        risk_engine.set_daily_loss_limit(Money::new(Decimal::from(50_000), Currency::USD));
        
        // Simulate daily losses approaching the limit
        risk_engine.record_pnl(PnL::new(Decimal::from(-45_000)).map_err(|e| format!("Failed to create PnL: {}", e)).unwrap());
        
        // Order that would cause additional loss if it goes against us
        let risky_order = Order {
            id: OrderId::from("RISKY-001"),
            symbol: Symbol::new("VOLATILE".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Market,
            quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: None,
            time_in_force: TimeInForce::ImmediateOrCancel,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        // Set high volatility for the symbol
        risk_engine.set_symbol_volatility(
            Symbol::new("VOLATILE".to_string()).unwrap(),
            Decimal::from_str("0.20").unwrap() // 20% daily volatility
        );
        
        let validation_result = risk_engine.validate_order(&risky_order).await;
        
        // Should be rejected due to potential additional loss
        assert!(validation_result.is_err());
    }
    
    #[tokio::test]
    async fn test_var_calculation() {
        let positions = vec![
            Position {
                symbol: Symbol::new("AAPL".to_string()).unwrap(),
                quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create position quantity: {}", e)).unwrap(),
                average_price: Price::new(Decimal::from(150)).unwrap(),
                realized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
                unrealized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
                last_updated: chrono::Utc::now(),
            },
            Position {
                symbol: Symbol::new("MSFT".to_string()).unwrap(),
                quantity: Quantity::new(Decimal::from(500)).map_err(|e| format!("Failed to create position quantity: {}", e)).unwrap(),
                average_price: Price::new(Decimal::from(300)).unwrap(),
                realized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
                unrealized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
                last_updated: chrono::Utc::now(),
            },
        ];
        
        // Mock volatilities and correlations
        let mut volatilities = HashMap::new();
        volatilities.insert(Symbol::new("AAPL".to_string()).unwrap(), Decimal::from_str("0.25").unwrap());
        volatilities.insert(Symbol::new("MSFT".to_string()).unwrap(), Decimal::from_str("0.20").unwrap());
        
        let mut correlations = HashMap::new();
        correlations.insert(
            (Symbol::new("AAPL".to_string()).unwrap(), Symbol::new("MSFT".to_string()).unwrap()),
            Decimal::from_str("0.7").unwrap()
        );
        
        let var_engine = VarEngine::new(volatilities, correlations);
        let var_result = var_engine.calculate_portfolio_var(&positions, Decimal::from_str("0.95").unwrap())
            .expect("Should calculate VaR");
        
        // VaR should be positive and reasonable
        assert!(var_result.var_1_day.amount > Decimal::ZERO);
        assert!(var_result.var_1_day.amount < Decimal::from(100_000)); // Sanity check
        
        // 5-day VaR should be higher than 1-day VaR
        assert!(var_result.var_5_day.amount > var_result.var_1_day.amount);
    }
    
    #[tokio::test]
    async fn test_margin_requirements() {
        let mut risk_engine = RiskEngine::new();
        
        // Set margin requirements for different instruments
        risk_engine.set_margin_requirement(
            Symbol::new("AAPL".to_string()).unwrap(),
            Decimal::from_str("0.25").unwrap() // 25% margin
        );
        risk_engine.set_margin_requirement(
            Symbol::new("VOLATILE_ETF".to_string()).unwrap(),
            Decimal::from_str("0.50").unwrap() // 50% margin for volatile instruments
        );
        
        // Available cash: $100,000
        risk_engine.set_available_cash(Money::new(Decimal::from(100_000), Currency::USD));
        
        // Order requiring $50,000 margin (25% of $200,000 order)
        let margin_order = Order {
            id: OrderId::from("MARGIN-001"),
            symbol: Symbol::new("AAPL".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(200)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let validation_result = risk_engine.validate_order(&margin_order).await;
        assert!(validation_result.is_ok()); // Should pass - $50k margin available
        
        // Order requiring $100,000 margin (50% of $200,000 order) - should fail
        let high_margin_order = Order {
            id: OrderId::from("HIGH-MARGIN-001"),
            symbol: Symbol::new("VOLATILE_ETF".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Limit,
            quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: Some(Price::new(Decimal::from(200)).unwrap()),
            time_in_force: TimeInForce::Day,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let high_validation_result = risk_engine.validate_order(&high_margin_order).await;
        assert!(high_validation_result.is_err());
    }
    
    #[tokio::test]
    async fn test_circuit_breaker() {
        let mut risk_engine = RiskEngine::new();
        
        // Set circuit breaker at 5% portfolio loss
        risk_engine.set_circuit_breaker_threshold(Decimal::from_str("0.05").unwrap());
        risk_engine.set_portfolio_value(Money::new(Decimal::from(1_000_000), Currency::USD));
        
        // Simulate losses approaching threshold
        risk_engine.record_pnl(PnL::new(Decimal::from(-40_000)).map_err(|e| format!("Failed to create PnL: {}", e)).unwrap());
        assert!(!risk_engine.is_circuit_breaker_triggered());

        // Additional loss that triggers circuit breaker
        risk_engine.record_pnl(PnL::new(Decimal::from(-15_000)).map_err(|e| format!("Failed to create PnL: {}", e)).unwrap());
        assert!(risk_engine.is_circuit_breaker_triggered());
        
        // All new orders should be rejected
        let order_after_breaker = Order {
            id: OrderId::from("AFTER-BREAKER"),
            symbol: Symbol::new("ANY".to_string()).unwrap(),
            side: Side::Buy,
            order_type: OrderType::Market,
            quantity: Quantity::new(Decimal::from(100)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            price: None,
            time_in_force: TimeInForce::ImmediateOrCancel,
            timestamp: chrono::Utc::now(),
            status: OrderStatus::New,
            client_id: ClientId::new("CLIENT-001".to_string()),
        };
        
        let validation_result = risk_engine.validate_order(&order_after_breaker).await;
        assert!(validation_result.is_err());
        assert!(validation_result.unwrap_err().to_string().contains("circuit breaker"));
    }
    
    #[tokio::test]
    async fn test_stress_testing() {
        let positions = vec![
            Position {
                symbol: Symbol::new("TECH_STOCK".to_string()).unwrap(),
                quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
                average_price: Price::new(Decimal::from(100)).unwrap(),
                realized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
                unrealized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
                last_updated: chrono::Utc::now(),
            },
        ];
        
        let stress_tester = StressTester::new();
        
        // Test market crash scenario: -30% tech stocks
        let crash_scenario = StressScenario {
            name: "Tech Crash".to_string(),
            price_shocks: {
                let mut shocks = HashMap::new();
                shocks.insert(
                    Symbol::new("TECH_STOCK".to_string()).unwrap(),
                    Decimal::from_str("-0.30").unwrap()
                );
                shocks
            },
            correlation_changes: HashMap::new(),
            volatility_multipliers: HashMap::new(),
        };
        
        let stress_result = stress_tester.run_stress_test(&positions, &crash_scenario)
            .expect("Should run stress test");
        
        // Portfolio should lose $30,000 (30% of $100,000)
        let expected_loss = Decimal::from(-30_000);
        let tolerance = Decimal::from(1000);
        
        assert!((stress_result.total_pnl.value() - expected_loss).abs() < tolerance);
        assert_eq!(stress_result.scenario_name, "Tech Crash");
    }
    
    #[tokio::test]
    async fn test_real_time_risk_monitoring() {
        let mut risk_monitor = RealTimeRiskMonitor::new();
        
        // Set up initial portfolio
        risk_monitor.set_portfolio_value(Money::new(Decimal::from(1_000_000), Currency::USD));
        risk_monitor.add_position(Position {
            symbol: Symbol::new("SPY".to_string()).unwrap(),
            quantity: Quantity::new(Decimal::from(1000)).map_err(|e| format!("Failed to create test quantity: {}", e)).unwrap(),
            average_price: Price::new(Decimal::from(400)).unwrap(),
            realized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
            unrealized_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
            last_updated: chrono::Utc::now(),
        });
        
        // Simulate rapid price movement
        let price_update = MarketDataEvent {
            symbol: Symbol::new("SPY".to_string()).unwrap(),
            price: Price::new(Decimal::from(380)).unwrap(), // 5% drop
            timestamp: chrono::Utc::now(),
            volume: Volume::new(Decimal::from(1_000_000)).map_err(|e| format!("Failed to create volume: {}", e)).unwrap(),
        };
        
        let risk_alert = risk_monitor.process_price_update(&price_update).await
            .expect("Should process price update");
        
        // Should generate risk alert for significant position movement
        assert!(risk_alert.is_some());
        let alert = risk_alert.unwrap();
        assert_eq!(alert.severity, AlertSeverity::High);
        assert!(alert.message.contains("position loss"));
    }
}

// Production implementations for testing
#[derive(Debug)]
struct RiskEngine {
    position_limits: HashMap<Symbol, Quantity>,
    concentration_limit: Option<Decimal>,
    daily_loss_limit: Option<Money>,
    portfolio_value: Option<Money>,
    positions: Vec<Position>,
    daily_pnl: PnL,
    circuit_breaker_threshold: Option<Decimal>,
    circuit_breaker_triggered: bool,
    margin_requirements: HashMap<Symbol, Decimal>,
    available_cash: Option<Money>,
    symbol_volatilities: HashMap<Symbol, Decimal>,
}

impl RiskEngine {
    fn new() -> Self {
        Self {
            position_limits: HashMap::new(),
            concentration_limit: None,
            daily_loss_limit: None,
            portfolio_value: None,
            positions: Vec::new(),
            daily_pnl: PnL::new(Decimal::ZERO).map_err(|e| format!("Failed to create zero PnL: {}", e)).unwrap(),
            circuit_breaker_threshold: None,
            circuit_breaker_triggered: false,
            margin_requirements: HashMap::new(),
            available_cash: None,
            symbol_volatilities: HashMap::new(),
        }
    }
    
    fn set_position_limit(&mut self, symbol: Symbol, limit: Quantity) {
        self.position_limits.insert(symbol, limit);
    }
    
    fn set_concentration_limit(&mut self, limit: Decimal) {
        self.concentration_limit = Some(limit);
    }
    
    fn set_daily_loss_limit(&mut self, limit: Money) {
        self.daily_loss_limit = Some(limit);
    }
    
    fn set_portfolio_value(&mut self, value: Money) {
        self.portfolio_value = Some(value);
    }
    
    fn add_position(&mut self, position: Position) {
        self.positions.push(position);
    }
    
    fn record_pnl(&mut self, pnl: PnL) {
        self.daily_pnl = PnL::new(self.daily_pnl.value() + pnl.value()).map_err(|e| format!("Failed to create daily PnL: {}", e)).unwrap();
        
        // Check circuit breaker
        if let (Some(threshold), Some(portfolio_value)) = (&self.circuit_breaker_threshold, &self.portfolio_value) {
            let loss_percentage = (-self.daily_pnl.value()) / portfolio_value.amount;
            if loss_percentage >= *threshold {
                self.circuit_breaker_triggered = true;
            }
        }
    }
    
    fn set_circuit_breaker_threshold(&mut self, threshold: Decimal) {
        self.circuit_breaker_threshold = Some(threshold);
    }
    
    fn is_circuit_breaker_triggered(&self) -> bool {
        self.circuit_breaker_triggered
    }
    
    fn set_margin_requirement(&mut self, symbol: Symbol, requirement: Decimal) {
        self.margin_requirements.insert(symbol, requirement);
    }
    
    fn set_available_cash(&mut self, cash: Money) {
        self.available_cash = Some(cash);
    }
    
    fn set_symbol_volatility(&mut self, symbol: Symbol, volatility: Decimal) {
        self.symbol_volatilities.insert(symbol, volatility);
    }
    
    async fn validate_order(&self, order: &Order) -> Result<(), Box<dyn std::error::Error>> {
        // Circuit breaker check
        if self.circuit_breaker_triggered {
            return Err("Order rejected: circuit breaker triggered".into());
        }
        
        // Position limit check
        if let Some(limit) = self.position_limits.get(&order.symbol) {
            if order.quantity.value() > limit.value() {
                return Err("Order rejected: exceeds position limit".into());
            }
        }
        
        // Concentration risk check
        if let (Some(conc_limit), Some(portfolio_value)) = (&self.concentration_limit, &self.portfolio_value) {
            let current_position_value = self.positions.iter()
                .find(|p| p.symbol == order.symbol)
                .map(|p| p.quantity.value() * p.average_price.value())
                .unwrap_or(Decimal::ZERO);
            
            let order_value = order.quantity.value() * 
                order.price.as_ref().unwrap_or(&Price::new(Decimal::from(100)).unwrap()).value();
            
            let total_position_value = current_position_value + order_value;
            let concentration = total_position_value / portfolio_value.amount;
            
            if concentration > *conc_limit {
                return Err("Order rejected: exceeds concentration limit".into());
            }
        }
        
        // Daily loss limit check with volatility consideration
        if let Some(loss_limit) = &self.daily_loss_limit {
            let current_loss = -self.daily_pnl.value();
            if current_loss > loss_limit.amount * Decimal::from_str("0.8").unwrap() { // 80% of limit
                if let Some(volatility) = self.symbol_volatilities.get(&order.symbol) {
                    if *volatility > Decimal::from_str("0.15").unwrap() { // High volatility
                        return Err("Order rejected: approaching daily loss limit with high volatility".into());
                    }
                }
            }
        }
        
        // Margin requirement check
        if let (Some(margin_req), Some(available_cash)) = 
            (self.margin_requirements.get(&order.symbol), &self.available_cash) {
            
            let order_value = order.quantity.value() * 
                order.price.as_ref().unwrap_or(&Price::new(Decimal::from(100)).unwrap()).value();
            let required_margin = order_value * margin_req;
            
            if required_margin > available_cash.amount {
                return Err("Order rejected: insufficient margin".into());
            }
        }
        
        Ok(())
    }
}

#[derive(Debug)]
struct VarEngine {
    volatilities: HashMap<Symbol, Decimal>,
    correlations: HashMap<(Symbol, Symbol), Decimal>,
}

impl VarEngine {
    fn new(volatilities: HashMap<Symbol, Decimal>, correlations: HashMap<(Symbol, Symbol), Decimal>) -> Self {
        Self {
            volatilities,
            correlations,
        }
    }
    
    fn calculate_portfolio_var(&self, positions: &[Position], confidence_level: Decimal) -> Result<VarPrediction, Box<dyn std::error::Error>> {
        // Simplified VaR calculation
        let z_score = if confidence_level == Decimal::from_str("0.95").unwrap() {
            Decimal::from_str("1.645").unwrap() // 95% confidence
        } else {
            Decimal::from_str("2.33").unwrap() // 99% confidence
        };
        
        // Calculate portfolio volatility (simplified - assuming uncorrelated for simplicity)
        let mut portfolio_variance = Decimal::ZERO;
        
        for position in positions {
            let position_value = position.quantity.value() * position.average_price.value();
            let volatility = self.volatilities.get(&position.symbol).unwrap_or(&Decimal::from_str("0.20").unwrap());
            let position_variance = (position_value * volatility).powi(2);
            portfolio_variance += position_variance;
        }
        
        let portfolio_volatility = portfolio_variance.sqrt().unwrap_or(Decimal::ZERO);
        let var_1_day = portfolio_volatility * z_score;
        let var_5_day = var_1_day * Decimal::from_str("2.236").unwrap(); // sqrt(5)
        
        Ok(VarPrediction {
            confidence_level,
            var_1_day: Money::new(var_1_day, Currency::USD),
            var_5_day: Money::new(var_5_day, Currency::USD),
            expected_shortfall: Money::new(var_1_day * Decimal::from_str("1.2").unwrap(), Currency::USD),
            calculation_timestamp: chrono::Utc::now(),
        })
    }
}

#[derive(Debug)]
struct StressTester;

#[derive(Debug)]
struct StressScenario {
    name: String,
    price_shocks: HashMap<Symbol, Decimal>,
    correlation_changes: HashMap<(Symbol, Symbol), Decimal>,
    volatility_multipliers: HashMap<Symbol, Decimal>,
}

#[derive(Debug)]
struct StressTestResult {
    scenario_name: String,
    total_pnl: PnL,
    position_impacts: HashMap<Symbol, PnL>,
    max_drawdown: Decimal,
}

impl StressTester {
    fn new() -> Self {
        Self
    }
    
    fn run_stress_test(&self, positions: &[Position], scenario: &StressScenario) -> Result<StressTestResult, Box<dyn std::error::Error>> {
        let mut total_pnl = Decimal::ZERO;
        let mut position_impacts = HashMap::new();
        
        for position in positions {
            if let Some(price_shock) = scenario.price_shocks.get(&position.symbol) {
                let position_value = position.quantity.value() * position.average_price.value();
                let impact = position_value * price_shock;
                total_pnl += impact;
                position_impacts.insert(position.symbol.clone(), PnL::new(impact).map_err(|e| format!("Failed to create position impact PnL: {}", e)).unwrap());
            }
        }
        
        Ok(StressTestResult {
            scenario_name: scenario.name.clone(),
            total_pnl: PnL::new(total_pnl).map_err(|e| format!("Failed to create total PnL: {}", e)).unwrap(),
            position_impacts,
            max_drawdown: (-total_pnl / Decimal::from(1_000_000)).abs(), // Assuming $1M portfolio
        })
    }
}

#[derive(Debug)]
struct RealTimeRiskMonitor {
    portfolio_value: Option<Money>,
    positions: Vec<Position>,
}

#[derive(Debug)]
struct RiskAlert {
    severity: AlertSeverity,
    message: String,
    timestamp: chrono::DateTime<chrono::Utc>,
}

impl RealTimeRiskMonitor {
    fn new() -> Self {
        Self {
            portfolio_value: None,
            positions: Vec::new(),
        }
    }
    
    fn set_portfolio_value(&mut self, value: Money) {
        self.portfolio_value = Some(value);
    }
    
    fn add_position(&mut self, position: Position) {
        self.positions.push(position);
    }
    
    async fn process_price_update(&self, event: &MarketDataEvent) -> Result<Option<RiskAlert>, Box<dyn std::error::Error>> {
        // Find position affected by price update
        if let Some(position) = self.positions.iter().find(|p| p.symbol == event.symbol) {
            let old_value = position.quantity.value() * position.average_price.value();
            let new_value = position.quantity.value() * event.price.value();
            let change = new_value - old_value;
            let change_percent = change / old_value;
            
            // Generate alert for significant moves
            if change_percent.abs() > Decimal::from_str("0.03").unwrap() { // 3% threshold
                let severity = if change_percent.abs() > Decimal::from_str("0.05").unwrap() {
                    AlertSeverity::High
                } else {
                    AlertSeverity::Medium
                };
                
                return Ok(Some(RiskAlert {
                    severity,
                    message: format!(
                        "Significant position loss in {}: {}%",
                        event.symbol.as_str(),
                        (change_percent * Decimal::from(100)).round_dp(2)
                    ),
                    timestamp: chrono::Utc::now(),
                }));
            }
        }
        
        Ok(None)
    }
}