promote residual momentum ranking
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 1m8s
Deploy / deploy (push) Successful in 35s

This commit is contained in:
2026-07-02 21:00:39 +02:00
parent 849489a4b5
commit aadec7d403
21 changed files with 310 additions and 185 deletions
+13 -13
View File
@@ -2,12 +2,12 @@
A single predicate, driven by the admin activation config, used by the
performance stats (server) and mirrored on the frontend. The core selection is
cross-sectional momentum: a setup's ticker must rank in the top
``min_momentum_percentile`` of the universe by 12-1 month momentum — the one
signal the backtest showed actually sorts forward returns. R:R and confidence
remain as floors, and conviction/conflict survive as optional tighteners (off by
default). The momentum percentile is computed across the universe and attached to
each setup upstream; when it's absent the gate falls back to the floors.
residual cross-sectional momentum: a setup's ticker must rank in the top
``min_momentum_percentile`` of the universe by beta-adjusted 12-1 month momentum.
R:R and confidence remain as floors, and conviction/conflict survive as optional
tighteners (off by default). The activation percentile is computed across the
universe and attached to each setup upstream; when it's absent the gate falls
back to the floors.
"""
from __future__ import annotations
@@ -65,12 +65,12 @@ def setup_qualifies(setup: Any, config: dict) -> bool:
return False
if (setup.confidence_score or 0.0) < config["min_confidence"]:
return False
# Cross-sectional momentum: the core selection. A setup's ticker must rank in
# the top ``min_momentum_percentile`` of the universe by 12-1 momentum. The
# validated edge is long-only, so while the gate is active shorts (which fight
# the trend) never qualify. The percentile floor is only enforced when a
# percentile is attached (live setups / backtest); callers that don't attach
# it defer to the floors above.
# Residual cross-sectional momentum: the core selection. A setup's ticker
# must rank in the top ``min_momentum_percentile`` of the universe by
# beta-adjusted 12-1 momentum. The validated edge is long-only, so while the
# gate is active shorts (which fight the trend) never qualify. The percentile
# floor is only enforced when a percentile is attached (live setups /
# backtest); callers that don't attach it defer to the floors above.
min_pct = float(config.get("min_momentum_percentile", 0.0))
if min_pct > 0:
if (getattr(setup, "direction", "long") or "long") == "short":
@@ -81,7 +81,7 @@ def setup_qualifies(setup: Any, config: dict) -> bool:
# A NEUTRAL recommendation means the engine found no clear directional setup —
# not an actionable signal, so by default it doesn't qualify (and can't be a
# top pick). ``exclude_neutral`` defaults on; turn it off to also count
# no-clear-direction momentum leaders.
# no-clear-direction residual momentum leaders.
if config.get("exclude_neutral"):
if (setup.recommended_action or "NEUTRAL") == "NEUTRAL":
return False