feat: replace regime monitor with v2 methodology
This commit is contained in:
+18
-12
@@ -1,7 +1,7 @@
|
||||
"""Market-level endpoints (benchmark regime + AI/Tech regime-change monitor)."""
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.dependencies import get_db, require_access, require_admin
|
||||
@@ -40,12 +40,18 @@ async def backtest_report(
|
||||
|
||||
|
||||
class RegimeConfigUpdate(BaseModel):
|
||||
weights: dict[str, float] | None = None
|
||||
alert_threshold: float | None = None
|
||||
tickers: dict | None = None
|
||||
leader_weight: float | None = None
|
||||
rs_lookback: int | None = None
|
||||
fundamental_staleness_days: int | None = None
|
||||
breadth_basket: list[str] | None = Field(default=None, min_length=20, max_length=100)
|
||||
fundamental_staleness_days: int | None = Field(default=None, ge=30, le=180)
|
||||
|
||||
@field_validator("breadth_basket")
|
||||
@classmethod
|
||||
def normalise_basket(cls, value: list[str] | None) -> list[str] | None:
|
||||
if value is None:
|
||||
return None
|
||||
cleaned = [symbol.strip().upper().replace(".", "-") for symbol in value if symbol.strip()]
|
||||
if len(cleaned) != len(set(cleaned)):
|
||||
raise ValueError("breadth basket symbols must be unique")
|
||||
return cleaned
|
||||
|
||||
|
||||
class RegimeFundamentalsUpdate(BaseModel):
|
||||
@@ -59,7 +65,7 @@ async def regime_monitor(
|
||||
_user: User = Depends(require_access),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Latest AI/Tech regime-change index (0-100) + per-signal breakdown + trend."""
|
||||
"""Latest v2 State and Warning risk-thermometer readings."""
|
||||
data = await regime_monitor_service.get_regime_monitor(db)
|
||||
return APIEnvelope(status="success", data=data)
|
||||
|
||||
@@ -69,7 +75,7 @@ async def regime_config(
|
||||
_admin: User = Depends(require_admin),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Editable weights / thresholds / ticker lists for the regime monitor."""
|
||||
"""Editable fixed breadth basket and fundamental freshness window."""
|
||||
data = await regime_monitor_service.get_regime_config(db)
|
||||
return APIEnvelope(status="success", data=data)
|
||||
|
||||
@@ -80,7 +86,7 @@ async def update_regime_config(
|
||||
_admin: User = Depends(require_admin),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Merge the supplied fields into the stored regime-monitor config."""
|
||||
"""Update the deliberately small v2 operator configuration."""
|
||||
updates = body.model_dump(exclude_none=True)
|
||||
data = await regime_monitor_service.update_regime_config(db, updates)
|
||||
return APIEnvelope(status="success", data=data)
|
||||
@@ -133,10 +139,10 @@ async def regime_event_study(
|
||||
|
||||
@router.get("/regime/history", response_model=APIEnvelope)
|
||||
async def regime_history(
|
||||
days: int = Query(default=400, ge=7, le=2000),
|
||||
days: int = Query(default=800, ge=7, le=2000),
|
||||
_user: User = Depends(require_access),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Daily history of the index / early-warning / combined scores (for the chart)."""
|
||||
"""Point-in-time v2 State/Warning history. Legacy rows are excluded."""
|
||||
data = await regime_monitor_service.get_regime_history(db, days=days)
|
||||
return APIEnvelope(status="success", data=data)
|
||||
|
||||
Reference in New Issue
Block a user