first commit
This commit is contained in:
75
app/routers/scores.py
Normal file
75
app/routers/scores.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""Scores router — scoring engine endpoints."""
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.dependencies import get_db, require_access
|
||||
from app.schemas.common import APIEnvelope
|
||||
from app.schemas.score import (
|
||||
DimensionScoreResponse,
|
||||
RankingEntry,
|
||||
RankingResponse,
|
||||
ScoreResponse,
|
||||
WeightUpdateRequest,
|
||||
)
|
||||
from app.services.scoring_service import get_rankings, get_score, update_weights
|
||||
|
||||
router = APIRouter(tags=["scores"])
|
||||
|
||||
|
||||
@router.get("/scores/{symbol}", response_model=APIEnvelope)
|
||||
async def read_score(
|
||||
symbol: str,
|
||||
_user=Depends(require_access),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Get composite + dimension scores for a symbol. Recomputes stale scores."""
|
||||
result = await get_score(db, symbol)
|
||||
|
||||
data = ScoreResponse(
|
||||
symbol=result["symbol"],
|
||||
composite_score=result["composite_score"],
|
||||
composite_stale=result["composite_stale"],
|
||||
weights=result["weights"],
|
||||
dimensions=[
|
||||
DimensionScoreResponse(**d) for d in result["dimensions"]
|
||||
],
|
||||
missing_dimensions=result["missing_dimensions"],
|
||||
computed_at=result["computed_at"],
|
||||
)
|
||||
return APIEnvelope(status="success", data=data.model_dump(mode="json"))
|
||||
|
||||
|
||||
@router.get("/rankings", response_model=APIEnvelope)
|
||||
async def read_rankings(
|
||||
_user=Depends(require_access),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Get all tickers ranked by composite score descending."""
|
||||
result = await get_rankings(db)
|
||||
|
||||
data = RankingResponse(
|
||||
rankings=[
|
||||
RankingEntry(
|
||||
symbol=r["symbol"],
|
||||
composite_score=r["composite_score"],
|
||||
dimensions=[
|
||||
DimensionScoreResponse(**d) for d in r["dimensions"]
|
||||
],
|
||||
)
|
||||
for r in result["rankings"]
|
||||
],
|
||||
weights=result["weights"],
|
||||
)
|
||||
return APIEnvelope(status="success", data=data.model_dump(mode="json"))
|
||||
|
||||
|
||||
@router.put("/scores/weights", response_model=APIEnvelope)
|
||||
async def update_score_weights(
|
||||
body: WeightUpdateRequest,
|
||||
_user=Depends(require_access),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
) -> APIEnvelope:
|
||||
"""Update dimension weights and recompute all composite scores."""
|
||||
new_weights = await update_weights(db, body.weights)
|
||||
return APIEnvelope(status="success", data={"weights": new_weights})
|
||||
Reference in New Issue
Block a user