83 lines
2.1 KiB
Python
83 lines
2.1 KiB
Python
"""Pydantic schemas for scoring endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class SubScoreResponse(BaseModel):
|
|
"""A single sub-score within a dimension breakdown."""
|
|
|
|
name: str
|
|
score: float
|
|
weight: float
|
|
raw_value: float | str | None = None
|
|
description: str = ""
|
|
|
|
|
|
class ScoreBreakdownResponse(BaseModel):
|
|
"""Breakdown of a dimension score into sub-scores."""
|
|
|
|
sub_scores: list[SubScoreResponse]
|
|
formula: str
|
|
unavailable: list[dict[str, str]] = []
|
|
|
|
|
|
class CompositeBreakdownResponse(BaseModel):
|
|
"""Breakdown of the composite score showing dimension weights and re-normalization."""
|
|
|
|
weights: dict[str, float]
|
|
available_dimensions: list[str]
|
|
missing_dimensions: list[str]
|
|
renormalized_weights: dict[str, float]
|
|
formula: str
|
|
|
|
|
|
class DimensionScoreResponse(BaseModel):
|
|
"""A single dimension score."""
|
|
|
|
dimension: str
|
|
score: float
|
|
is_stale: bool
|
|
computed_at: datetime | None = None
|
|
breakdown: ScoreBreakdownResponse | None = None
|
|
|
|
|
|
class ScoreResponse(BaseModel):
|
|
"""Full score response for a ticker: composite + all dimensions."""
|
|
|
|
symbol: str
|
|
composite_score: float | None = None
|
|
composite_stale: bool = False
|
|
weights: dict[str, float] = {}
|
|
dimensions: list[DimensionScoreResponse] = []
|
|
missing_dimensions: list[str] = []
|
|
computed_at: datetime | None = None
|
|
composite_breakdown: CompositeBreakdownResponse | None = None
|
|
|
|
|
|
class WeightUpdateRequest(BaseModel):
|
|
"""Request to update dimension weights."""
|
|
|
|
weights: dict[str, float] = Field(
|
|
...,
|
|
description="Dimension name → weight mapping. All weights must be positive.",
|
|
)
|
|
|
|
|
|
class RankingEntry(BaseModel):
|
|
"""A single entry in the rankings list."""
|
|
|
|
symbol: str
|
|
composite_score: float
|
|
dimensions: list[DimensionScoreResponse] = []
|
|
|
|
|
|
class RankingResponse(BaseModel):
|
|
"""Rankings response: tickers sorted by composite score descending."""
|
|
|
|
rankings: list[RankingEntry] = []
|
|
weights: dict[str, float] = {}
|