feat: Enhance dashboard metrics and summary statistics
- Added new summary fields: variance, 5th percentile, 95th percentile, VaR (95%), and expected shortfall (95%) to the dashboard. - Updated the display logic for summary metrics to handle non-finite values gracefully. - Modified the chart rendering to include additional percentile points and tail risk metrics in tooltips. test: Introduce unit tests for consumption, costs, and other modules - Created a comprehensive test suite for consumption, costs, equipment, maintenance, production, reporting, and simulation modules. - Implemented fixtures for database setup and teardown using an in-memory SQLite database for isolated testing. - Added tests for creating, listing, and validating various entities, ensuring proper error handling and response validation. refactor: Consolidate parameter tests and remove deprecated files - Merged parameter-related tests into a new test file for better organization and clarity. - Removed the old parameter test file that was no longer in use. - Improved test coverage for parameter creation, listing, and validation scenarios. fix: Ensure proper validation and error handling in API endpoints - Added validation to reject negative amounts in consumption and production records. - Implemented checks to prevent duplicate scenario creation and ensure proper error messages are returned. - Enhanced reporting endpoint tests to validate input formats and expected outputs.
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
from statistics import mean, median, pstdev
|
||||
from typing import Dict, Iterable, List, Union
|
||||
from typing import Any, Dict, Iterable, List, Mapping, Union, cast
|
||||
|
||||
|
||||
def _extract_results(simulation_results: Iterable[Dict[str, float]]) -> List[float]:
|
||||
def _extract_results(simulation_results: Iterable[object]) -> List[float]:
|
||||
values: List[float] = []
|
||||
for item in simulation_results:
|
||||
if not isinstance(item, dict):
|
||||
if not isinstance(item, Mapping):
|
||||
continue
|
||||
value = item.get("result")
|
||||
mapping_item = cast(Mapping[str, Any], item)
|
||||
value = mapping_item.get("result")
|
||||
if isinstance(value, (int, float)):
|
||||
values.append(float(value))
|
||||
return values
|
||||
@@ -39,8 +40,13 @@ def generate_report(simulation_results: List[Dict[str, float]]) -> Dict[str, Uni
|
||||
"min": 0.0,
|
||||
"max": 0.0,
|
||||
"std_dev": 0.0,
|
||||
"variance": 0.0,
|
||||
"percentile_10": 0.0,
|
||||
"percentile_90": 0.0,
|
||||
"percentile_5": 0.0,
|
||||
"percentile_95": 0.0,
|
||||
"value_at_risk_95": 0.0,
|
||||
"expected_shortfall_95": 0.0,
|
||||
}
|
||||
|
||||
summary: Dict[str, Union[float, int]] = {
|
||||
@@ -51,7 +57,21 @@ def generate_report(simulation_results: List[Dict[str, float]]) -> Dict[str, Uni
|
||||
"max": max(values),
|
||||
"percentile_10": _percentile(values, 10),
|
||||
"percentile_90": _percentile(values, 90),
|
||||
"percentile_5": _percentile(values, 5),
|
||||
"percentile_95": _percentile(values, 95),
|
||||
}
|
||||
|
||||
summary["std_dev"] = pstdev(values) if len(values) > 1 else 0.0
|
||||
std_dev = pstdev(values) if len(values) > 1 else 0.0
|
||||
summary["std_dev"] = std_dev
|
||||
summary["variance"] = std_dev ** 2
|
||||
|
||||
var_95 = summary["percentile_5"]
|
||||
summary["value_at_risk_95"] = var_95
|
||||
|
||||
tail_values = [value for value in values if value <= var_95]
|
||||
if tail_values:
|
||||
summary["expected_shortfall_95"] = mean(tail_values)
|
||||
else:
|
||||
summary["expected_shortfall_95"] = var_95
|
||||
|
||||
return summary
|
||||
|
||||
Reference in New Issue
Block a user