This commit is contained in:
2025-11-09 16:49:27 +01:00
parent 22ddfb671d
commit d807a50f77
96 changed files with 3 additions and 9689 deletions

View File

@@ -1,79 +0,0 @@
from statistics import mean, median, pstdev
from typing import Any, Dict, Iterable, List, Mapping, Union, cast
def _extract_results(simulation_results: Iterable[object]) -> List[float]:
values: List[float] = []
for item in simulation_results:
if not isinstance(item, Mapping):
continue
mapping_item = cast(Mapping[str, Any], item)
value = mapping_item.get("result")
if isinstance(value, (int, float)):
values.append(float(value))
return values
def _percentile(values: List[float], percentile: float) -> float:
if not values:
return 0.0
sorted_values = sorted(values)
if len(sorted_values) == 1:
return sorted_values[0]
index = (percentile / 100) * (len(sorted_values) - 1)
lower = int(index)
upper = min(lower + 1, len(sorted_values) - 1)
weight = index - lower
return sorted_values[lower] * (1 - weight) + sorted_values[upper] * weight
def generate_report(
simulation_results: List[Dict[str, float]],
) -> Dict[str, Union[float, int]]:
"""Aggregate basic statistics for simulation outputs."""
values = _extract_results(simulation_results)
if not values:
return {
"count": 0,
"mean": 0.0,
"median": 0.0,
"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]] = {
"count": len(values),
"mean": mean(values),
"median": median(values),
"min": min(values),
"max": max(values),
"percentile_10": _percentile(values, 10),
"percentile_90": _percentile(values, 90),
"percentile_5": _percentile(values, 5),
"percentile_95": _percentile(values, 95),
}
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