57 lines
1.4 KiB
Python
57 lines
1.4 KiB
Python
|
|
"""
|
||
|
|
Risk level classification and trend calculation utilities.
|
||
|
|
"""
|
||
|
|
from typing import Literal
|
||
|
|
|
||
|
|
from config import (
|
||
|
|
RISK_HIGH,
|
||
|
|
RISK_MEDIUM_HIGH,
|
||
|
|
RISK_MEDIUM,
|
||
|
|
RISK_MEDIUM_LOW,
|
||
|
|
TREND_SLOPE_THRESHOLD,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def risk_value_to_level(risk_value: float) -> str:
|
||
|
|
"""Convert risk value (0-1) to risk level string."""
|
||
|
|
if risk_value >= RISK_HIGH:
|
||
|
|
return "high"
|
||
|
|
elif risk_value >= RISK_MEDIUM_HIGH:
|
||
|
|
return "medium_high"
|
||
|
|
elif risk_value >= RISK_MEDIUM:
|
||
|
|
return "medium"
|
||
|
|
elif risk_value >= RISK_MEDIUM_LOW:
|
||
|
|
return "medium_low"
|
||
|
|
else:
|
||
|
|
return "low"
|
||
|
|
|
||
|
|
|
||
|
|
def calculate_trend(values: list[float]) -> Literal["up", "down", "stable"]:
|
||
|
|
"""Calculate trend direction from a series of values using linear regression slope."""
|
||
|
|
if len(values) < 2:
|
||
|
|
return "stable"
|
||
|
|
|
||
|
|
n = len(values)
|
||
|
|
x_mean = (n - 1) / 2
|
||
|
|
y_mean = sum(values) / n
|
||
|
|
|
||
|
|
numerator = sum((i - x_mean) * (values[i] - y_mean) for i in range(n))
|
||
|
|
denominator = sum((i - x_mean) ** 2 for i in range(n))
|
||
|
|
|
||
|
|
if denominator == 0:
|
||
|
|
return "stable"
|
||
|
|
|
||
|
|
slope = numerator / denominator
|
||
|
|
|
||
|
|
if y_mean == 0:
|
||
|
|
return "stable"
|
||
|
|
|
||
|
|
relative_slope = slope / y_mean
|
||
|
|
|
||
|
|
if relative_slope > TREND_SLOPE_THRESHOLD:
|
||
|
|
return "up"
|
||
|
|
elif relative_slope < -TREND_SLOPE_THRESHOLD:
|
||
|
|
return "down"
|
||
|
|
else:
|
||
|
|
return "stable"
|