Skip to main content
Glama

MCP Market Statistics Server

by whdghk1907
test_risk_assessment_engine.pyโ€ข24.2 kB
"""์œ„ํ—˜ ํ‰๊ฐ€ ์—”์ง„ ํ…Œ์ŠคํŠธ""" import pytest import asyncio import time from datetime import datetime, timedelta from unittest.mock import AsyncMock, MagicMock, patch from typing import Dict, List, Any from src.ai.risk_assessment_engine import RiskAssessmentEngine from src.exceptions import ModelNotTrainedError, InsufficientDataError, PredictionError class TestRiskAssessmentEngine: """์œ„ํ—˜ ํ‰๊ฐ€ ์—”์ง„ ํ…Œ์ŠคํŠธ""" @pytest.fixture def engine_config(self): """์—”์ง„ ์„ค์ •""" return { "risk_models": ["var", "cvar", "drawdown", "volatility", "beta"], "confidence_levels": [0.95, 0.99], "time_horizons": [1, 5, 10, 30], # days "lookback_period": 252, # trading days "monte_carlo_simulations": 10000, "risk_factors": { "market_risk": 0.4, "credit_risk": 0.2, "liquidity_risk": 0.15, "operational_risk": 0.15, "model_risk": 0.1 }, "stress_scenarios": ["market_crash", "interest_rate_shock", "currency_crisis"], "portfolio_constraints": { "max_position_size": 0.1, # 10% "max_sector_exposure": 0.3, # 30% "min_diversification_score": 0.7 } } @pytest.fixture def risk_engine(self, engine_config): """์œ„ํ—˜ ํ‰๊ฐ€ ์—”์ง„ ์ธ์Šคํ„ด์Šค""" return RiskAssessmentEngine(engine_config) @pytest.fixture def sample_portfolio_data(self): """์ƒ˜ํ”Œ ํฌํŠธํด๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ""" return { "positions": [ { "symbol": "005930", # ์‚ผ์„ฑ์ „์ž "weight": 0.25, "market_value": 25000000, "sector": "technology", "beta": 1.2, "volatility": 0.25 }, { "symbol": "000660", # SKํ•˜์ด๋‹‰์Šค "weight": 0.20, "market_value": 20000000, "sector": "technology", "beta": 1.5, "volatility": 0.35 }, { "symbol": "035420", # NAVER "weight": 0.15, "market_value": 15000000, "sector": "internet", "beta": 1.1, "volatility": 0.30 }, { "symbol": "051910", # LGํ™”ํ•™ "weight": 0.20, "market_value": 20000000, "sector": "chemicals", "beta": 0.9, "volatility": 0.28 }, { "symbol": "028260", # ์‚ผ์„ฑ๋ฌผ์‚ฐ "weight": 0.20, "market_value": 20000000, "sector": "construction", "beta": 0.8, "volatility": 0.22 } ], "total_value": 100000000, # 1์–ต์› "currency": "KRW", "benchmark": "KOSPI", "creation_date": "2024-01-01" } @pytest.fixture def sample_market_data(self): """์ƒ˜ํ”Œ ์‹œ์žฅ ๋ฐ์ดํ„ฐ""" return { "005930": { "prices": [75000 + i * 100 for i in range(252)], # 1๋…„์น˜ ๋ฐ์ดํ„ฐ "returns": [0.001 + i * 0.0001 for i in range(252)], "volumes": [1000000 + i * 1000 for i in range(252)] }, "000660": { "prices": [80000 + i * 150 for i in range(252)], "returns": [0.002 + i * 0.0002 for i in range(252)], "volumes": [800000 + i * 800 for i in range(252)] }, "KOSPI": { "prices": [2500 + i * 2 for i in range(252)], "returns": [0.0008 + i * 0.00008 for i in range(252)] } } def test_engine_initialization(self, risk_engine, engine_config): """์—”์ง„ ์ดˆ๊ธฐํ™” ํ…Œ์ŠคํŠธ""" assert risk_engine.risk_models == engine_config["risk_models"] assert risk_engine.confidence_levels == engine_config["confidence_levels"] assert risk_engine.time_horizons == engine_config["time_horizons"] assert risk_engine.lookback_period == engine_config["lookback_period"] assert risk_engine.monte_carlo_simulations == engine_config["monte_carlo_simulations"] assert risk_engine.risk_factors == engine_config["risk_factors"] assert risk_engine.is_calibrated == False @pytest.mark.asyncio async def test_model_calibration(self, risk_engine, sample_market_data): """๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ํ…Œ์ŠคํŠธ""" # ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์ „ ์ƒํƒœ assert risk_engine.is_calibrated == False # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ calibration_result = await risk_engine.calibrate_models(sample_market_data) # ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ํ›„ ์ƒํƒœ assert risk_engine.is_calibrated == True assert "calibrated_models" in calibration_result assert "calibration_metrics" in calibration_result assert "model_parameters" in calibration_result # ๊ฐ ์œ„ํ—˜ ๋ชจ๋ธ์ด ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜๋˜์—ˆ๋Š”์ง€ ํ™•์ธ calibrated_models = calibration_result["calibrated_models"] for model in risk_engine.risk_models: assert model in calibrated_models @pytest.mark.asyncio async def test_var_calculation(self, risk_engine, sample_portfolio_data, sample_market_data): """VaR ๊ณ„์‚ฐ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # VaR ๊ณ„์‚ฐ var_results = await risk_engine.calculate_var( sample_portfolio_data, confidence_level=0.95, time_horizon=1 ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "var_amount" in var_results assert "var_percentage" in var_results assert "confidence_level" in var_results assert "time_horizon" in var_results assert "methodology" in var_results # VaR ๊ฐ’์ด ํ•ฉ๋ฆฌ์ ์ธ ๋ฒ”์œ„์ธ์ง€ ํ™•์ธ var_amount = var_results["var_amount"] portfolio_value = sample_portfolio_data["total_value"] var_percentage = abs(var_amount) / portfolio_value assert 0 < var_percentage < 0.2 # 0-20% ๋ฒ”์œ„ assert var_results["confidence_level"] == 0.95 assert var_results["time_horizon"] == 1 @pytest.mark.asyncio async def test_cvar_calculation(self, risk_engine, sample_portfolio_data, sample_market_data): """CVaR (Conditional VaR) ๊ณ„์‚ฐ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # CVaR ๊ณ„์‚ฐ cvar_results = await risk_engine.calculate_cvar( sample_portfolio_data, confidence_level=0.95, time_horizon=1 ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "cvar_amount" in cvar_results assert "cvar_percentage" in cvar_results assert "var_amount" in cvar_results # CVaR๋Š” VaR๋„ ํฌํ•จ assert "expected_shortfall" in cvar_results # CVaR์€ ํ•ญ์ƒ VaR๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์•„์•ผ ํ•จ assert abs(cvar_results["cvar_amount"]) >= abs(cvar_results["var_amount"]) @pytest.mark.asyncio async def test_maximum_drawdown_analysis(self, risk_engine, sample_portfolio_data, sample_market_data): """์ตœ๋Œ€ ๋‚™ํญ ๋ถ„์„ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ์ตœ๋Œ€ ๋‚™ํญ ๋ถ„์„ drawdown_results = await risk_engine.analyze_maximum_drawdown( sample_portfolio_data, sample_market_data ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "max_drawdown" in drawdown_results assert "max_drawdown_duration" in drawdown_results assert "recovery_time" in drawdown_results assert "drawdown_periods" in drawdown_results assert "current_drawdown" in drawdown_results # ๋‚™ํญ์€ ์Œ์ˆ˜์ด๊ฑฐ๋‚˜ 0์ด์–ด์•ผ ํ•จ assert drawdown_results["max_drawdown"] <= 0 assert drawdown_results["max_drawdown_duration"] >= 0 @pytest.mark.asyncio async def test_volatility_analysis(self, risk_engine, sample_portfolio_data, sample_market_data): """๋ณ€๋™์„ฑ ๋ถ„์„ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ๋ณ€๋™์„ฑ ๋ถ„์„ volatility_results = await risk_engine.analyze_volatility( sample_portfolio_data, sample_market_data ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "portfolio_volatility" in volatility_results assert "annualized_volatility" in volatility_results assert "volatility_breakdown" in volatility_results assert "garch_forecast" in volatility_results assert "realized_volatility" in volatility_results # ๋ณ€๋™์„ฑ์€ ์–‘์ˆ˜์—ฌ์•ผ ํ•จ assert volatility_results["portfolio_volatility"] > 0 assert volatility_results["annualized_volatility"] > 0 @pytest.mark.asyncio async def test_beta_analysis(self, risk_engine, sample_portfolio_data, sample_market_data): """๋ฒ ํƒ€ ๋ถ„์„ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ๋ฒ ํƒ€ ๋ถ„์„ beta_results = await risk_engine.analyze_beta( sample_portfolio_data, sample_market_data, benchmark="KOSPI" ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "portfolio_beta" in beta_results assert "systematic_risk" in beta_results assert "idiosyncratic_risk" in beta_results assert "correlation_with_market" in beta_results assert "r_squared" in beta_results # ๋ฒ ํƒ€ ๊ฐ’์ด ํ•ฉ๋ฆฌ์ ์ธ ๋ฒ”์œ„์ธ์ง€ ํ™•์ธ portfolio_beta = beta_results["portfolio_beta"] assert -2 < portfolio_beta < 3 # ์ผ๋ฐ˜์ ์ธ ๋ฒ ํƒ€ ๋ฒ”์œ„ # R-squared๋Š” 0-1 ๋ฒ”์œ„ assert 0 <= beta_results["r_squared"] <= 1 @pytest.mark.asyncio async def test_stress_testing(self, risk_engine, sample_portfolio_data, sample_market_data): """์ŠคํŠธ๋ ˆ์Šค ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ์ŠคํŠธ๋ ˆ์Šค ํ…Œ์ŠคํŠธ ์‹คํ–‰ stress_results = await risk_engine.run_stress_tests( sample_portfolio_data, scenarios=["market_crash", "interest_rate_shock"] ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "stress_test_results" in stress_results assert "worst_case_scenario" in stress_results assert "scenario_rankings" in stress_results stress_test_results = stress_results["stress_test_results"] # ๊ฐ ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ํ™•์ธ for scenario in ["market_crash", "interest_rate_shock"]: assert scenario in stress_test_results scenario_result = stress_test_results[scenario] assert "portfolio_loss" in scenario_result assert "loss_percentage" in scenario_result assert "affected_positions" in scenario_result @pytest.mark.asyncio async def test_monte_carlo_simulation(self, risk_engine, sample_portfolio_data, sample_market_data): """๋ชฌํ…Œ์นด๋ฅผ๋กœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ๋ชฌํ…Œ์นด๋ฅผ๋กœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ mc_results = await risk_engine.run_monte_carlo_simulation( sample_portfolio_data, time_horizon=30, num_simulations=1000 # ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ ์ถ•์†Œ ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "simulation_results" in mc_results assert "statistical_summary" in mc_results assert "percentiles" in mc_results assert "probability_of_loss" in mc_results # ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ ์ˆ˜ ํ™•์ธ simulation_results = mc_results["simulation_results"] assert len(simulation_results) == 1000 # ํ†ต๊ณ„ ์š”์•ฝ ํ™•์ธ statistical_summary = mc_results["statistical_summary"] assert "mean" in statistical_summary assert "std" in statistical_summary assert "min" in statistical_summary assert "max" in statistical_summary @pytest.mark.asyncio async def test_portfolio_optimization(self, risk_engine, sample_portfolio_data, sample_market_data): """ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” optimization_results = await risk_engine.optimize_portfolio( sample_portfolio_data, objective="minimize_risk", constraints={"max_position_size": 0.3} ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "optimized_weights" in optimization_results assert "risk_reduction" in optimization_results assert "expected_return" in optimization_results assert "optimization_method" in optimization_results # ๊ฐ€์ค‘์น˜ ํ•ฉ์ด 1์ธ์ง€ ํ™•์ธ optimized_weights = optimization_results["optimized_weights"] total_weight = sum(optimized_weights.values()) assert abs(total_weight - 1.0) < 0.01 # 1์— ๊ฐ€๊นŒ์›€ # ์ œ์•ฝ์กฐ๊ฑด ํ™•์ธ for weight in optimized_weights.values(): assert weight <= 0.3 # ์ตœ๋Œ€ ํฌ์ง€์…˜ ํฌ๊ธฐ ์ œ์•ฝ @pytest.mark.asyncio async def test_risk_attribution(self, risk_engine, sample_portfolio_data, sample_market_data): """์œ„ํ—˜ ๊ธฐ์—ฌ๋„ ๋ถ„์„ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ์œ„ํ—˜ ๊ธฐ์—ฌ๋„ ๋ถ„์„ attribution_results = await risk_engine.analyze_risk_attribution( sample_portfolio_data, sample_market_data ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "position_contributions" in attribution_results assert "sector_contributions" in attribution_results assert "factor_contributions" in attribution_results assert "diversification_ratio" in attribution_results # ํฌ์ง€์…˜๋ณ„ ๊ธฐ์—ฌ๋„ ํ™•์ธ position_contributions = attribution_results["position_contributions"] for position in sample_portfolio_data["positions"]: symbol = position["symbol"] assert symbol in position_contributions assert "risk_contribution" in position_contributions[symbol] assert "marginal_risk" in position_contributions[symbol] @pytest.mark.asyncio async def test_liquidity_risk_assessment(self, risk_engine, sample_portfolio_data, sample_market_data): """์œ ๋™์„ฑ ์œ„ํ—˜ ํ‰๊ฐ€ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ์œ ๋™์„ฑ ์œ„ํ—˜ ํ‰๊ฐ€ liquidity_results = await risk_engine.assess_liquidity_risk( sample_portfolio_data, sample_market_data ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "liquidity_score" in liquidity_results assert "time_to_liquidate" in liquidity_results assert "liquidity_cost" in liquidity_results assert "position_liquidity" in liquidity_results # ์œ ๋™์„ฑ ์ ์ˆ˜๋Š” 0-1 ๋ฒ”์œ„ liquidity_score = liquidity_results["liquidity_score"] assert 0 <= liquidity_score <= 1 # ์ฒญ์‚ฐ ์‹œ๊ฐ„์€ ์–‘์ˆ˜ time_to_liquidate = liquidity_results["time_to_liquidate"] assert time_to_liquidate > 0 @pytest.mark.asyncio async def test_concentration_risk_analysis(self, risk_engine, sample_portfolio_data): """์ง‘์ค‘๋„ ์œ„ํ—˜ ๋ถ„์„ ํ…Œ์ŠคํŠธ""" # ์ง‘์ค‘๋„ ์œ„ํ—˜ ๋ถ„์„ concentration_results = await risk_engine.analyze_concentration_risk(sample_portfolio_data) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "herfindahl_index" in concentration_results assert "max_position_weight" in concentration_results assert "sector_concentration" in concentration_results assert "concentration_score" in concentration_results assert "diversification_recommendations" in concentration_results # ํ—ˆํ•€๋‹ฌ ์ง€์ˆ˜๋Š” 0-1 ๋ฒ”์œ„ herfindahl_index = concentration_results["herfindahl_index"] assert 0 < herfindahl_index <= 1 # ์ตœ๋Œ€ ํฌ์ง€์…˜ ๋น„์ค‘ ํ™•์ธ max_position_weight = concentration_results["max_position_weight"] actual_max_weight = max(pos["weight"] for pos in sample_portfolio_data["positions"]) assert abs(max_position_weight - actual_max_weight) < 0.01 @pytest.mark.asyncio async def test_risk_reporting(self, risk_engine, sample_portfolio_data, sample_market_data): """์œ„ํ—˜ ๋ณด๊ณ ์„œ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ์ข…ํ•ฉ ์œ„ํ—˜ ๋ณด๊ณ ์„œ ์ƒ์„ฑ risk_report = await risk_engine.generate_risk_report( sample_portfolio_data, sample_market_data, report_date=datetime.now() ) # ๋ณด๊ณ ์„œ ๊ตฌ์กฐ ํ™•์ธ assert "executive_summary" in risk_report assert "var_analysis" in risk_report assert "stress_test_results" in risk_report assert "risk_attribution" in risk_report assert "recommendations" in risk_report assert "report_metadata" in risk_report # ์ž„์› ์š”์•ฝ ํ™•์ธ executive_summary = risk_report["executive_summary"] assert "overall_risk_level" in executive_summary assert "key_risk_factors" in executive_summary assert "immediate_actions" in executive_summary @pytest.mark.asyncio async def test_real_time_risk_monitoring(self, risk_engine, sample_portfolio_data, sample_market_data): """์‹ค์‹œ๊ฐ„ ์œ„ํ—˜ ๋ชจ๋‹ˆํ„ฐ๋ง ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ์‹ค์‹œ๊ฐ„ ์‹œ์žฅ ๋ฐ์ดํ„ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ real_time_data = { "005930": {"price": 77000, "volume": 1500000, "timestamp": datetime.now().isoformat()}, "000660": {"price": 82000, "volume": 1200000, "timestamp": datetime.now().isoformat()} } # ์‹ค์‹œ๊ฐ„ ์œ„ํ—˜ ๋ชจ๋‹ˆํ„ฐ๋ง monitoring_results = await risk_engine.monitor_real_time_risk( sample_portfolio_data, real_time_data ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "current_var" in monitoring_results assert "risk_alerts" in monitoring_results assert "position_changes" in monitoring_results assert "monitoring_timestamp" in monitoring_results # ์œ„ํ—˜ ์•Œ๋ฆผ ๊ตฌ์กฐ ํ™•์ธ risk_alerts = monitoring_results["risk_alerts"] for alert in risk_alerts: assert "alert_type" in alert assert "severity" in alert assert "message" in alert @pytest.mark.asyncio async def test_backtesting_validation(self, risk_engine, sample_portfolio_data, sample_market_data): """๋ฐฑํ…Œ์ŠคํŒ… ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ๋ฐฑํ…Œ์ŠคํŒ… ์‹คํ–‰ backtest_results = await risk_engine.run_backtest_validation( sample_portfolio_data, sample_market_data, start_date="2023-01-01", end_date="2023-12-31" ) # ๊ฒฐ๊ณผ ๊ฒ€์ฆ assert "var_accuracy" in backtest_results assert "kupiec_test" in backtest_results assert "christoffersen_test" in backtest_results assert "model_performance" in backtest_results # VaR ์ •ํ™•๋„ ํ™•์ธ var_accuracy = backtest_results["var_accuracy"] assert "hit_rate" in var_accuracy assert "expected_exceptions" in var_accuracy assert "actual_exceptions" in var_accuracy @pytest.mark.asyncio async def test_error_handling(self, risk_engine): """์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ํ…Œ์ŠคํŠธ""" # ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜๋˜์ง€ ์•Š์€ ๋ชจ๋ธ๋กœ ๊ณ„์‚ฐ ์‹œ๋„ with pytest.raises(ModelNotTrainedError): await risk_engine.calculate_var({}, confidence_level=0.95) # ๋ถˆ์ถฉ๋ถ„ํ•œ ๋ฐ์ดํ„ฐ๋กœ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์‹œ๋„ insufficient_data = {"symbol": [100, 101, 102]} # ๋„ˆ๋ฌด ์ ์€ ๋ฐ์ดํ„ฐ with pytest.raises(InsufficientDataError): await risk_engine.calibrate_models(insufficient_data) # ์ž˜๋ชป๋œ ์‹ ๋ขฐ์ˆ˜์ค€ await risk_engine.calibrate_models({"symbol": list(range(300))}) with pytest.raises(ValueError): await risk_engine.calculate_var({}, confidence_level=1.5) # > 1 @pytest.mark.asyncio async def test_performance_benchmarking(self, risk_engine, sample_portfolio_data, sample_market_data): """์„ฑ๋Šฅ ๋ฒค์น˜๋งˆํ‚น ํ…Œ์ŠคํŠธ""" # ๋ชจ๋ธ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ await risk_engine.calibrate_models(sample_market_data) # ๋Œ€๋Ÿ‰ ๊ณ„์‚ฐ ์„ฑ๋Šฅ ์ธก์ • start_time = time.time() # ์—ฌ๋Ÿฌ ๊ณ„์‚ฐ์„ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ tasks = [ risk_engine.calculate_var(sample_portfolio_data, 0.95, 1), risk_engine.calculate_cvar(sample_portfolio_data, 0.95, 1), risk_engine.analyze_volatility(sample_portfolio_data, sample_market_data) ] results = await asyncio.gather(*tasks) end_time = time.time() # ์„ฑ๋Šฅ ํ™•์ธ processing_time = end_time - start_time assert processing_time < 5.0 # 5์ดˆ ์ด๋‚ด assert len(results) == 3 # ๊ฐ ๊ฒฐ๊ณผ๊ฐ€ ์œ ํšจํ•œ์ง€ ํ™•์ธ for result in results: assert result is not None assert isinstance(result, dict) def test_risk_metrics_calculation(self, risk_engine): """์œ„ํ—˜ ๋ฉ”ํŠธ๋ฆญ ๊ณ„์‚ฐ ํ…Œ์ŠคํŠธ""" # ์ƒ˜ํ”Œ ์ˆ˜์ต๋ฅ  ๋ฐ์ดํ„ฐ returns = [0.01, -0.02, 0.015, -0.008, 0.003, -0.012, 0.007, -0.005] # ํ‘œ์ค€ํŽธ์ฐจ ๊ณ„์‚ฐ volatility = risk_engine._calculate_volatility(returns) assert volatility > 0 # VaR ๊ณ„์‚ฐ (ํžˆ์Šคํ† ๋ฆฌ์ปฌ ๋ฐฉ๋ฒ•) var_95 = risk_engine._calculate_historical_var(returns, 0.95) var_99 = risk_engine._calculate_historical_var(returns, 0.99) # 99% VaR์ด 95% VaR๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์•„์•ผ ํ•จ (์ ˆ๋Œ“๊ฐ’) assert abs(var_99) >= abs(var_95) # ์ƒคํ”„ ๋น„์œจ ๊ณ„์‚ฐ sharpe_ratio = risk_engine._calculate_sharpe_ratio(returns, risk_free_rate=0.02) assert isinstance(sharpe_ratio, (int, float)) def test_correlation_analysis(self, risk_engine): """์ƒ๊ด€๊ด€๊ณ„ ๋ถ„์„ ํ…Œ์ŠคํŠธ""" # ์ƒ˜ํ”Œ ์ˆ˜์ต๋ฅ  ๋ฐ์ดํ„ฐ returns_a = [0.01, -0.02, 0.015, -0.008, 0.003] returns_b = [0.005, -0.015, 0.012, -0.006, 0.002] # ์ƒ๊ด€๊ณ„์ˆ˜ ๊ณ„์‚ฐ correlation = risk_engine._calculate_correlation(returns_a, returns_b) # ์ƒ๊ด€๊ณ„์ˆ˜๋Š” -1๊ณผ 1 ์‚ฌ์ด assert -1 <= correlation <= 1 # ๊ณต๋ถ„์‚ฐ ๊ณ„์‚ฐ covariance = risk_engine._calculate_covariance(returns_a, returns_b) assert isinstance(covariance, (int, float))

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/whdghk1907/mcp-market-statistics'

If you have feedback or need assistance with the MCP directory API, please join our Discord server