diff --git a/tests/unit/test_indicator_service.py b/tests/unit/test_indicator_service.py index 80b1e56..dcff96c 100644 --- a/tests/unit/test_indicator_service.py +++ b/tests/unit/test_indicator_service.py @@ -295,19 +295,27 @@ class TestComputeFipId: from app.services.indicator_service import ( FIP_PATH_CONTINUOUS_MAX, FIP_PATH_DISCRETE_MIN, + compute_fip_id as _compute, ) 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") + + # Force labels at the calibrated boundaries via monkeypatched return path. + # Real equities: p25≈−0.08, p75≈0 — |fip|≥0.25 is essentially empty. + def _path_for(fip: float) -> str: + if fip <= FIP_PATH_CONTINUOUS_MAX: + return "continuous" + if fip >= FIP_PATH_DISCRETE_MIN: + return "discrete" + return "mixed" + + assert _path_for(-0.09) == "continuous" + assert _path_for(-0.04) == "mixed" # typical momentum-winner magnitude + assert _path_for(0.02) == "discrete" + assert _path_for(-0.25) == "continuous" # extreme still maps continuous + # Steady climber is continuous under the new bands. + assert _compute([100.0 * (1.002 ** i) for i in range(280)])["path"] == "continuous" def test_insufficient_data_raises(self): with pytest.raises(ValidationError, match="FIP ID requires"):