feat: breadth-divergence early-warning indicator + event study
Adds a leading-by-construction candidate and the harness to measure whether it actually leads regime breaks, before any of it earns weight in the live index. - breadth_service: % of the stored universe above its own 200-DMA + a divergence score (benchmark price up while breadth falls, nudged by low breadth). Genuinely leading because it keys on divergence, not level. Not wired into the live score. - event_study_service: detect drawdown events on the benchmark, then measure each indicator's median lead time (event-centered) and precision/recall vs. the base rate (signal-centered). Compares breadth-divergence against the deterministic coincident price composite (reuses the regime price sub-scores). Price/breadth only — reproducible, no LLM/FRED. - Manual "Event Study" job (Admin → Jobs), GET /regime/event-study, and an inline early-warning panel on the Regime tab with an honest small-sample caveat. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+13
-1
@@ -7,7 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.dependencies import get_db, require_access, require_admin
|
||||
from app.models.user import User
|
||||
from app.schemas.common import APIEnvelope
|
||||
from app.services import regime_monitor_service
|
||||
from app.services import event_study_service, regime_monitor_service
|
||||
from app.services.backtest_service import get_backtest_report
|
||||
from app.services.market_regime_service import get_market_regime
|
||||
|
||||
@@ -117,3 +117,15 @@ async def refresh_regime_fundamentals(
|
||||
"""Ask the configured LLM to re-estimate F1/F3 now (forces past a lock)."""
|
||||
data = await regime_monitor_service.refresh_fundamental_overrides(db, force=True)
|
||||
return APIEnvelope(status="success", data=data)
|
||||
|
||||
|
||||
@router.get("/regime/event-study", response_model=APIEnvelope)
|
||||
async def regime_event_study(
|
||||
_user: User = Depends(require_access),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Cached early-warning event study (lead time vs. historical drawdowns).
|
||||
|
||||
None until the manual "Event Study" job has run (Admin → Jobs)."""
|
||||
data = await event_study_service.get_event_study_report(db)
|
||||
return APIEnvelope(status="success", data=data)
|
||||
|
||||
Reference in New Issue
Block a user