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.
183 lines
4.4 KiB
Python
183 lines
4.4 KiB
Python
"""Pydantic response models for Stock Oracle API."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Company Info
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class CompanyInfo(BaseModel):
|
|
ticker: str
|
|
name: str | None = None
|
|
cik: str | None = None
|
|
exchange: str | None = None
|
|
sector: str | None = None
|
|
industry: str | None = None
|
|
country: str | None = None
|
|
market_cap: float | None = None
|
|
extra: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# SEC Filings
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class FilingEntry(BaseModel):
|
|
accession_no: str
|
|
form_type: str
|
|
filing_date: str # ISO date string
|
|
accepted_at: str | None = None
|
|
primary_document: str | None = None
|
|
description: str | None = None
|
|
items: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class FilingSearchResponse(BaseModel):
|
|
ticker: str
|
|
filings: list[FilingEntry] = Field(default_factory=list)
|
|
total: int = 0
|
|
|
|
|
|
class ExhibitDocument(BaseModel):
|
|
exhibit_type: str
|
|
filename: str | None = None
|
|
url: str | None = None
|
|
|
|
|
|
class FilingDocumentsResponse(BaseModel):
|
|
accession_no: str
|
|
exhibits: list[ExhibitDocument] = Field(default_factory=list)
|
|
|
|
|
|
class ExhibitResponse(BaseModel):
|
|
accession_no: str
|
|
exhibit_type: str
|
|
content: str
|
|
content_type: str = "text/plain"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Price / Market Data
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class PriceBar(BaseModel):
|
|
date: str # ISO date
|
|
open: float
|
|
high: float
|
|
low: float
|
|
close: float
|
|
volume: int
|
|
vwap: float | None = None
|
|
trade_count: int | None = None
|
|
|
|
|
|
class PriceDataResponse(BaseModel):
|
|
ticker: str
|
|
bars: list[PriceBar] = Field(default_factory=list)
|
|
source: str = "yfinance"
|
|
|
|
|
|
class PriceQuote(BaseModel):
|
|
ticker: str
|
|
price: float
|
|
bid: float | None = None
|
|
ask: float | None = None
|
|
volume: int | None = None
|
|
timestamp: str | None = None
|
|
|
|
|
|
class IntradayBar(BaseModel):
|
|
timestamp: str
|
|
open: float
|
|
high: float
|
|
low: float
|
|
close: float
|
|
volume: int
|
|
|
|
|
|
class IntradayResponse(BaseModel):
|
|
ticker: str
|
|
bars: list[IntradayBar] = Field(default_factory=list)
|
|
timeframe: str = "1m"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Financial / XBRL
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class FinancialPeriod(BaseModel):
|
|
period: str # e.g. "2025-Q4"
|
|
period_end: str # ISO date
|
|
revenue: float | None = None
|
|
net_income: float | None = None
|
|
eps: float | None = None
|
|
gross_margin: float | None = None
|
|
operating_margin: float | None = None
|
|
extra: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class FinancialDataResponse(BaseModel):
|
|
ticker: str
|
|
periods: list[FinancialPeriod] = Field(default_factory=list)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# FRED
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class FredObservation(BaseModel):
|
|
date: str # ISO date
|
|
value: float | None = None
|
|
|
|
|
|
class FredProxyResponse(BaseModel):
|
|
series_id: str
|
|
observations: list[FredObservation] = Field(default_factory=list)
|
|
realtime_start: str | None = None
|
|
realtime_end: str | None = None
|
|
|
|
|
|
class FredSeriesInfo(BaseModel):
|
|
id: str
|
|
title: str | None = None
|
|
frequency: str | None = None
|
|
units: str | None = None
|
|
notes: str | None = None
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# FINRA Short Volume
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class ShortVolumeEntry(BaseModel):
|
|
date: str # ISO date
|
|
short_volume: int
|
|
short_exempt_volume: int | None = None
|
|
total_volume: int | None = None
|
|
|
|
|
|
class ShortVolumeResponse(BaseModel):
|
|
symbol: str
|
|
data: list[ShortVolumeEntry] = Field(default_factory=list)
|
|
|
|
|
|
class ShortRatioPoint(BaseModel):
|
|
date: str
|
|
short_ratio: float | None = None
|
|
short_percent: float | None = None
|
|
|
|
|
|
class ShortRatioResponse(BaseModel):
|
|
symbol: str
|
|
data: list[ShortRatioPoint] = Field(default_factory=list)
|