Add S/R v2 research and validation harness

This commit is contained in:
2026-07-12 21:15:18 +02:00
parent 57ac1d2cdd
commit 19b81c169d
19 changed files with 1575 additions and 117 deletions
+21
View File
@@ -412,6 +412,7 @@ async def scan_ticker(
momentum_percentile: float | None = None,
strategy_rank: float | None = None,
volatility_percentile: float | None = None,
primary_min_rr: float | None = None,
) -> list[TradeSetup]:
"""Scan a single ticker for trade setups meeting the R:R threshold.
@@ -421,6 +422,14 @@ async def scan_ticker(
production ordering score used for top-pick ranking."""
ticker = await _get_ticker(db, symbol)
if primary_min_rr is None:
# Direct single-ticker scans still use the same activation threshold as
# qualification. scan_all_tickers resolves this once for the universe.
from app.services.admin_service import get_activation_config
activation = await get_activation_config(db)
primary_min_rr = float(activation.get("min_rr", rr_threshold))
records = await query_ohlcv(db, symbol)
if not records or len(records) < 15:
logger.info(
@@ -558,6 +567,7 @@ async def scan_ticker(
sr_levels=sr_levels,
sentiment_classification=sentiment_classification,
atr_value=atr_value,
primary_min_rr=primary_min_rr,
available_directions=available_directions,
)
enhanced_setups.append(enhanced)
@@ -610,6 +620,16 @@ async def scan_all_tickers(
logger.exception("Activation ranking refresh failed")
ranks = {}
try:
from app.services.admin_service import get_activation_config
activation = await get_activation_config(db)
primary_min_rr = float(activation.get("min_rr", rr_threshold))
except Exception:
await db.rollback()
logger.exception("Activation config load failed; using scanner R:R floor")
primary_min_rr = rr_threshold
all_setups: list[TradeSetup] = []
for index, symbol in enumerate(symbols):
if progress_callback is not None:
@@ -641,6 +661,7 @@ async def scan_all_tickers(
momentum_percentile=(ranks.get(symbol) or {}).get("momentum_percentile"),
strategy_rank=(ranks.get(symbol) or {}).get("strategy_rank"),
volatility_percentile=(ranks.get(symbol) or {}).get("volatility_percentile"),
primary_min_rr=primary_min_rr,
)
all_setups.extend(setups)
except Exception: