feat: wavelets

This commit is contained in:
OpenSquared
2026-07-14 16:23:18 +02:00
parent ce948f6b65
commit b693aca2dc
17 changed files with 2144 additions and 10 deletions

View File

@@ -640,6 +640,13 @@ GEOPOLITICAL_RISK_WEIGHTS = {
}
# A single extreme-severity article (e.g. imminent war, market-moving Fed shock) must not get diluted
# away just because other categories are quiet that day. This floor is driven by the single worst
# category score and stays inert below ~0.7, then ramps up steeply — solved so a lone 0.90 floors the
# final score at 50 (see MAX_CATEGORY_FLOOR_EXPONENT below).
MAX_CATEGORY_FLOOR_EXPONENT = 6.58
def compute_geo_risk_score(events: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Compute a global geopolitical risk score 0-100 from recent events."""
if not events:
@@ -658,7 +665,13 @@ def compute_geo_risk_score(events: List[Dict[str, Any]]) -> Dict[str, Any]:
category_scores.get(cat, 0) * weight
for cat, weight in GEOPOLITICAL_RISK_WEIGHTS.items()
)
score = min(100, round(weighted * 100, 1))
# Non-linear floor: the single most severe category score alone can force the score up,
# even if it's the only hot category — breaks the "many quiet categories dilute one severe one" effect.
max_category_impact = max(category_scores.values(), default=0.0)
floor = max_category_impact ** MAX_CATEGORY_FLOOR_EXPONENT
score = min(100, round(max(weighted, floor) * 100, 1))
if score < 25:
level = "low"