You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
2.9 KiB
Python
65 lines
2.9 KiB
Python
"""
|
|
Pydantic v2 schemas for the Attention subsystem API.
|
|
"""
|
|
|
|
from datetime import date, datetime
|
|
from typing import Any, Dict, List, Optional
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class EntityInfo(BaseModel):
|
|
ticker: str
|
|
canonical_name: str = Field(description="Normalized company name with legal suffixes stripped (e.g. 'Apple')")
|
|
wiki_title: Optional[str] = Field(default=None, description="Matched Wikipedia article title; null if unresolved")
|
|
gdelt_query: Optional[str] = Field(default=None, description="GDELT DOC API query string (quoted OR phrases)")
|
|
aliases: List[str] = Field(default_factory=list, description="Intermediate forms used during name normalization")
|
|
resolver_confidence: float = Field(default=0.0, description="Wikipedia match confidence [0, 1]")
|
|
is_manual_override: bool = Field(default=False, description="If true, automated re-resolution is skipped")
|
|
|
|
|
|
class WikiFeatures(BaseModel):
|
|
views: Optional[int] = Field(default=None, description="Wikipedia pageviews on the event date")
|
|
baseline_10d: Optional[float] = Field(default=None, description="Median pageviews over the prior 10 days")
|
|
spike_10d: Optional[float] = Field(default=None, description="views / baseline_10d; >1 means above-average attention")
|
|
zscore_20d: Optional[float] = Field(default=None, description="Z-score vs prior 20-day mean/stdev; null if stdev=0")
|
|
|
|
|
|
class NewsFeatures(BaseModel):
|
|
article_count_1d: int = Field(default=0, description="GDELT articles published on the event date")
|
|
article_count_3d: int = Field(default=0, description="GDELT articles in the event_date ± 1 day window")
|
|
unique_domains_3d: int = Field(default=0, description="Distinct publisher domains in the 3-day window")
|
|
us_article_count_3d: int = Field(default=0, description="US-sourced articles in the 3-day window")
|
|
gdelt_status: str = Field(
|
|
default="not_collected",
|
|
description=(
|
|
"GDELT data availability for this event date. "
|
|
"'collected' — scheduler has run; counts are accurate (0 means genuinely no articles). "
|
|
"'not_collected' — scheduler has not run yet; POST /admin/collect/gdelt/{ticker}?event_date=... to populate. "
|
|
"'not_available' — event date is before GDELT V2 coverage start (2017-01-01)."
|
|
),
|
|
)
|
|
|
|
|
|
class EventAttentionResponse(BaseModel):
|
|
ticker: str
|
|
event_date: date
|
|
entity: EntityInfo
|
|
wiki: WikiFeatures
|
|
news: NewsFeatures
|
|
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class EntityResolveResponse(BaseModel):
|
|
ticker: str
|
|
entity: EntityInfo
|
|
status: str # "resolved", "already_exists", "failed", "manual_override_skipped"
|
|
message: str
|
|
|
|
|
|
class CollectionStatusResponse(BaseModel):
|
|
ticker: str
|
|
source: str # "wiki" or "gdelt"
|
|
records_collected: int
|
|
date_range: Dict[str, Any] = Field(default_factory=dict)
|
|
status: str
|