feat(dolt): migration 026 + models — fundamentals/earnings schema (A1 schema)
First reviewable slice of workstream A: schema only, no importers, no data. - data_import_runs: lean batch-import audit (source/revision/status, row_counts_json + validation_json as Text-holding-JSON per repo convention). - fundamental_snapshots: CIK-keyed, one immutable row per accession; stores per-period raw facts (duration = cumulative YTD/FY, balance-sheet = period-end) plus period_start/period_end/fiscal_year/fiscal_period so discrete quarters, Q4, TTM and YoY are derived at read time. - earnings_events: Dolt-sourced calendar + surprise history, unique (ticker_id, announce_date). - tickers: nullable cik/sic/sic_description — the ticker<->issuer join point. fundamental_data is left untouched (cutover gated separately at A5). Models registered in app/models/__init__.py; Ticker gains an earnings_events relationship. Verified: create_all builds the tables, mappers configure, and migration 026 renders valid Postgres DDL up and down. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
from datetime import date, datetime
|
||||
|
||||
from sqlalchemy import Date, DateTime, Float, ForeignKey, Index, String, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.database import Base
|
||||
|
||||
|
||||
class EarningsEvent(Base):
|
||||
"""Earnings calendar + surprise history, sourced from the DoltHub earnings repo.
|
||||
|
||||
Forward rows (``announce_date`` > today) are the calendar; past rows are
|
||||
results. Rescheduling is handled in the importer's promotion transaction:
|
||||
this source's future-dated rows are deleted and re-inserted from the new
|
||||
snapshot so moved/cancelled dates never linger; past rows are never deleted.
|
||||
"""
|
||||
|
||||
__tablename__ = "earnings_events"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("ticker_id", "announce_date", name="uq_earnings_ticker_announce"),
|
||||
Index("ix_earnings_events_announce_date", "announce_date"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
ticker_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("tickers.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
announce_date: Mapped[date] = mapped_column(Date, nullable=False)
|
||||
# bmo | amc | unknown (source coverage is partial)
|
||||
session: Mapped[str] = mapped_column(String(10), nullable=False, default="unknown")
|
||||
period_end: Mapped[date | None] = mapped_column(Date, nullable=True)
|
||||
eps_estimate: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||||
eps_actual: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||||
source: Mapped[str] = mapped_column(String(32), nullable=False)
|
||||
import_run_id: Mapped[int | None] = mapped_column(
|
||||
ForeignKey("data_import_runs.id", ondelete="SET NULL"), nullable=True
|
||||
)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=datetime.utcnow, nullable=False
|
||||
)
|
||||
|
||||
ticker = relationship("Ticker", back_populates="earnings_events")
|
||||
Reference in New Issue
Block a user