fix: recalibrate FIP path labels to live equity scale
Deploy / lint (push) Successful in 9s
Deploy / test (push) Canceled after 0s
Deploy / deploy (push) Canceled after 0s

Replace inert ±0.25 bands with ~p25/p75 cutoffs from the prod snapshot
(−0.08 / 0.00). Document zero-return dilution and left-skewed distribution.
This commit is contained in:
2026-07-18 19:27:45 +02:00
parent d9c4cd35eb
commit dc08a805a8
3 changed files with 48 additions and 7 deletions
+21
View File
@@ -280,6 +280,8 @@ class TestComputeFipId:
assert 0 <= result["score"] <= 100
def test_jump_then_flat_is_more_discrete_than_steady(self):
# Ordering only: zeros dilute %pos/%neg so a pure jump can land near
# zero ("mixed") rather than "discrete" — paper-faithful, not a bug.
steady = [100.0 * (1.002 ** i) for i in range(280)]
jumpy = [100.0] * 252
jumpy.append(100.0 * 1.5)
@@ -288,6 +290,25 @@ class TestComputeFipId:
id_jumpy = compute_fip_id(jumpy)["fip_id"]
assert id_jumpy > id_steady
def test_label_thresholds_match_live_equity_scale(self):
# Calibrated cutoffs: continuous ≤ 0.08, discrete ≥ 0 (not ±0.25).
from app.services.indicator_service import (
FIP_PATH_CONTINUOUS_MAX,
FIP_PATH_DISCRETE_MIN,
)
assert FIP_PATH_CONTINUOUS_MAX == pytest.approx(-0.08)
assert FIP_PATH_DISCRETE_MIN == pytest.approx(0.0)
# Mild continuous (typical momentum winner scale).
mild = [100.0]
for i in range(1, 280):
# ~54% up days with small steps → fip roughly 0.08…−0.12 region.
mild.append(mild[-1] * (1.0015 if i % 2 == 0 or i % 5 != 0 else 0.9995))
r = compute_fip_id(mild)
assert r["fip_id"] > -0.25 # not textbook extreme
# Labels must fire somewhere in the observed equity band.
assert r["path"] in ("continuous", "mixed", "discrete")
def test_insufficient_data_raises(self):
with pytest.raises(ValidationError, match="FIP ID requires"):
compute_fip_id(_rising_closes(50))