"""Integration tests for portfolio risk management system. Tests the complete risk management flow including concentration limits, correlation monitoring, and drawdown control. """ import pytest from datetime import datetime from typing import Dict, List from openclaw.portfolio.risk import ( PortfolioRiskManager, PositionConcentrationLimit, DrawdownController, RiskAlertLevel, ) from openclaw.core.economy import TradingEconomicTracker, SurvivalStatus class TestPortfolioRiskManagerIntegration: """Integration tests for portfolio risk manager.""" def test_risk_manager_initialization(self): """Test risk manager can be initialized.""" manager = PortfolioRiskManager( max_position_pct=0.20, max_drawdown_pct=0.10, ) assert manager.max_position_pct == 0.20 assert manager.max_drawdown_pct == 0.10 def test_position_concentration_check(self): """Test position concentration limit check.""" from openclaw.portfolio.risk import PositionConcentrationLimit limit = PositionConcentrationLimit(max_position_pct=0.20) # Test with position under limit result = limit.check_limit( symbol="AAPL", position_value=1500.0, total_portfolio_value=10000.0, ) assert result is not None # 15% is under 20% limit assert result.is_allowed or not result.is_allowed def test_excessive_concentration_blocked(self): """Test that excessive concentration is blocked.""" from openclaw.portfolio.risk import PositionConcentrationLimit limit = PositionConcentrationLimit(max_position_pct=0.20) # Test with position over limit (30%) result = limit.check_limit( symbol="AAPL", position_value=3000.0, total_portfolio_value=10000.0, ) # 30% should be blocked assert not result.is_allowed def test_drawdown_control(self): """Test drawdown controller.""" from openclaw.portfolio.risk import DrawdownController controller = DrawdownController(max_drawdown_pct=0.10) # Update with portfolio value controller.update_value(10000.0, datetime.now()) controller.update_value(9500.0, datetime.now()) # 5% drawdown status = controller.get_status() assert status is not None def test_severe_drawdown_blocks_trading(self): """Test that severe drawdown blocks trading.""" from openclaw.portfolio.risk import DrawdownController controller = DrawdownController(max_drawdown_pct=0.10) # Peak value controller.update_value(10000.0, datetime.now()) # Drop 15% (over 10% threshold) controller.update_value(8500.0, datetime.now()) assert controller.should_block_trading() class TestRiskAlertsIntegration: """Tests for risk alert system.""" def test_risk_alert_generation(self): """Test risk alerts are generated correctly.""" from openclaw.portfolio.risk import RiskAlert, RiskAlertLevel alert = RiskAlert( timestamp=datetime.now(), alert_type="position_concentration", level=RiskAlertLevel.WARNING, message="Position exceeds 20% limit", symbol="AAPL", current_value=0.25, threshold=0.20, action_taken="blocked", ) assert alert.level == RiskAlertLevel.WARNING assert alert.symbol == "AAPL" assert alert.current_value > alert.threshold class TestSurvivalRiskManagerIntegration: """Tests for survival risk manager with economic status.""" def test_critical_status_limits(self): """Test that critical status imposes strict limits.""" from openclaw.agents.risk_manager import SurvivalRiskManager tracker = TradingEconomicTracker(agent_id="test_trader") # Set to critical (below 50%) tracker.current_balance = 400.0 manager = SurvivalRiskManager( agent_id="test_trader", economic_tracker=tracker, ) limits = manager.get_position_limits() # Critical: max 5% position, 0.5% risk per trade assert limits["max_position_pct"] <= 0.05 assert limits["max_risk_per_trade"] <= 0.005 def test_thriving_status_allows_more_risk(self): """Test that thriving status allows more risk.""" from openclaw.agents.risk_manager import SurvivalRiskManager tracker = TradingEconomicTracker(agent_id="test_trader") # Set to thriving (above 150%) tracker.current_balance = 2000.0 manager = SurvivalRiskManager( agent_id="test_trader", economic_tracker=tracker, ) limits = manager.get_position_limits() # Thriving: max 25% position, 3% risk per trade assert limits["max_position_pct"] >= 0.20 assert limits["max_risk_per_trade"] >= 0.02 class TestVaRCalculation: """Tests for Value at Risk calculations.""" def test_var_calculation(self): """Test VaR calculation.""" from openclaw.portfolio.risk import PortfolioVaR var_calculator = PortfolioVaR( confidence_level=0.95, time_horizon_days=1, ) # Mock returns data returns = [0.01, -0.02, 0.015, -0.01, 0.005, -0.005, 0.02, -0.015] var = var_calculator.calculate_parametric_var( portfolio_value=10000.0, returns=returns, ) assert var > 0 # VaR should be positive (potential loss) def test_var_blocks_high_risk_positions(self): """Test that high VaR blocks positions.""" from openclaw.portfolio.risk import PortfolioVaR var_calculator = PortfolioVaR( confidence_level=0.99, time_horizon_days=1, max_var_pct=0.02, # 2% max VaR ) # High volatility returns returns = [0.05, -0.08, 0.06, -0.07, 0.04, -0.09] var = var_calculator.calculate_parametric_var( portfolio_value=10000.0, returns=returns, ) # High VaR should trigger risk limit assert var_calculator.is_within_limit(var, portfolio_value=10000.0) is False