feat: show FIP path-smoothness in ticker technicals
Deploy / lint (push) Successful in 9s
Deploy / test (push) Successful in 1m20s
Deploy / deploy (push) Successful in 41s

Display-only Da/Gurun/Warachka information discreteness on the ticker
indicator panel. Shared compute with the backtest harness; not wired into
gate or rank.
This commit is contained in:
2026-07-18 19:22:02 +02:00
parent a71dd4adb7
commit 19d674ed62
4 changed files with 159 additions and 37 deletions
+29
View File
@@ -8,6 +8,7 @@ from app.services.indicator_service import (
compute_atr,
compute_ema,
compute_ema_cross,
compute_fip_id,
compute_pivot_points,
compute_rsi,
compute_volume_profile,
@@ -262,3 +263,31 @@ class TestComputeEMACross:
closes = _rising_closes(30)
with pytest.raises(ValidationError, match="EMA Cross requires"):
compute_ema_cross(closes, short_period=20, long_period=50)
# ---------------------------------------------------------------------------
# FIP ID (display / research context — not a gate)
# ---------------------------------------------------------------------------
class TestComputeFipId:
def test_steady_climber_is_continuous(self):
# Many small up days → low (negative) ID for a positive-return path.
closes = [100.0 * (1.002 ** i) for i in range(280)]
result = compute_fip_id(closes)
assert result["fip_id"] < 0
assert result["path"] == "continuous"
assert result["display_only"] is True
assert 0 <= result["score"] <= 100
def test_jump_then_flat_is_more_discrete_than_steady(self):
steady = [100.0 * (1.002 ** i) for i in range(280)]
jumpy = [100.0] * 252
jumpy.append(100.0 * 1.5)
jumpy.extend([100.0 * 1.5] * 40)
id_steady = compute_fip_id(steady)["fip_id"]
id_jumpy = compute_fip_id(jumpy)["fip_id"]
assert id_jumpy > id_steady
def test_insufficient_data_raises(self):
with pytest.raises(ValidationError, match="FIP ID requires"):
compute_fip_id(_rising_closes(50))