feat(mcp-macro): add compute_percentile + classify_extreme pure helpers

This commit is contained in:
AdrianoDev
2026-04-28 23:58:38 +02:00
parent 201f263c77
commit bf152d90fd
2 changed files with 81 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
"""Pure-logic helpers per COT report parsing e analytics.
Niente HTTP qui — orchestrazione fetch sta in fetchers.py. Tutto testabile
in isolamento.
"""
from __future__ import annotations
from typing import Literal
ExtremeSignal = Literal["extreme_short", "extreme_long", "neutral"]
def compute_percentile(value: float, history: list[float]) -> float | None:
"""Percentile di `value` rispetto ad `history` (0-100, inclusive).
Restituisce None se history vuoto. Clipped a [0, 100] se value fuori range.
"""
if not history:
return None
n = len(history)
below_or_eq = sum(1 for h in history if h <= value)
pct = 100.0 * below_or_eq / n
return max(0.0, min(100.0, pct))
def classify_extreme(percentile: float | None, threshold: float = 5.0) -> ExtremeSignal:
"""Classifica un percentile come estremo short/long o neutral.
threshold default 5 → flagga ≤ 5 come short, ≥ 100-5=95 come long.
"""
if percentile is None:
return "neutral"
if percentile <= threshold:
return "extreme_short"
if percentile >= 100.0 - threshold:
return "extreme_long"
return "neutral"
+44
View File
@@ -0,0 +1,44 @@
from __future__ import annotations
from mcp_macro.cot import classify_extreme, compute_percentile
def test_compute_percentile_basic():
history = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
assert compute_percentile(50, history) == 50.0
assert compute_percentile(10, history) == 10.0
assert compute_percentile(100, history) == 100.0
def test_compute_percentile_value_below_min():
history = [10, 20, 30]
assert compute_percentile(5, history) == 0.0
def test_compute_percentile_value_above_max():
history = [10, 20, 30]
assert compute_percentile(40, history) == 100.0
def test_compute_percentile_empty_history():
assert compute_percentile(50, []) is None
def test_classify_extreme_below_threshold():
assert classify_extreme(3.0) == "extreme_short"
assert classify_extreme(5.0) == "extreme_short" # boundary inclusive
def test_classify_extreme_above_threshold():
assert classify_extreme(96.0) == "extreme_long"
assert classify_extreme(95.0) == "extreme_long" # boundary inclusive
def test_classify_extreme_neutral():
assert classify_extreme(50.0) == "neutral"
assert classify_extreme(94.99) == "neutral"
assert classify_extreme(5.01) == "neutral"
def test_classify_extreme_none_input():
assert classify_extreme(None) == "neutral"