feat: add standalone AI/Tech regime-change monitor tab
A new /regime tab scoring how far the AI/Tech bull regime has deteriorated toward a re-rating as a single 0-100 index with per-signal breakdown and a 7/30-day trend. Intentionally decoupled: nothing reads its output to gate or score trades — the daily-pipeline membership is scheduling only. - regime_monitor_service: price sub-scores (P1-P6 via Alpaca, like market_regime), VIX + HY credit spreads via a small FRED helper, weighted aggregation over available signals (missing source -> n/a, dropped from the denominator), one snapshot row/day, and a ~90-day history backfill by replaying the already-fetched series as-of each past day. - F1/F3 fundamentals proposed by the configured grounded LLM (reuses sentiment_provider_service config resolution), with a manual override + lock. - regime_snapshots table (migration 011); endpoints on the existing market router; admin-editable weights/threshold; standalone /regime page. Data needs: prices via Alpaca, VIX/credit via FRED (optional key — signals show n/a without it). No LLM needed for history. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ from app.models.watchlist import WatchlistEntry
|
||||
from app.models.settings import SystemSetting, IngestionProgress
|
||||
from app.models.alert import AlertLog
|
||||
from app.models.paper_trade import PaperTrade
|
||||
from app.models.regime_snapshot import RegimeSnapshot
|
||||
|
||||
__all__ = [
|
||||
"Ticker",
|
||||
@@ -26,4 +27,5 @@ __all__ = [
|
||||
"IngestionProgress",
|
||||
"AlertLog",
|
||||
"PaperTrade",
|
||||
"RegimeSnapshot",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
from datetime import date as date_type
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Date, DateTime, Float, String, Text
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.database import Base
|
||||
|
||||
|
||||
class RegimeSnapshot(Base):
|
||||
"""Daily snapshot of the AI/Tech regime-change index.
|
||||
|
||||
One row per calendar date (unique). ``breakdown_json`` holds the full
|
||||
per-signal breakdown plus the raw inputs, so reads need no recomputation and
|
||||
the 7/30-day trend is just a query over ``total_score``. Decoupled from the
|
||||
rest of the platform: nothing reads this to gate or score trades.
|
||||
"""
|
||||
|
||||
__tablename__ = "regime_snapshots"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
date: Mapped[date_type] = mapped_column(Date, nullable=False, unique=True, index=True)
|
||||
total_score: Mapped[float] = mapped_column(Float, nullable=False)
|
||||
band: Mapped[str] = mapped_column(String(20), nullable=False)
|
||||
breakdown_json: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
||||
Reference in New Issue
Block a user