""" PIT Ex-Dividend Calendar model — revisioned dividend announcements Stores multiple revisions of the same (ticker, ex_dividend_date) with different as_of_date values, enabling Point-in-Time backtesting without lookahead bias. """ from datetime import datetime, timezone import uuid from sqlalchemy import Column, String, Float, Index, UniqueConstraint from sqlalchemy.dialects.postgresql import UUID, TIMESTAMP from app.core.database import Base class DividendCalendar(Base): __tablename__ = "dividend_calendar" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) ticker = Column(String(10), nullable=False, index=True) ex_dividend_date = Column(TIMESTAMP(timezone=True), nullable=False) amount = Column(Float, nullable=False) declaration_date = Column(TIMESTAMP(timezone=True), nullable=True) record_date = Column(TIMESTAMP(timezone=True), nullable=True) payment_date = Column(TIMESTAMP(timezone=True), nullable=True) currency = Column(String(10), default="USD") dividend_type = Column(String(20), default="regular") # regular | special frequency = Column(String(20), nullable=True) # quarterly | semi-annual | annual | monthly | irregular as_of_date = Column(TIMESTAMP(timezone=True), nullable=False) # PIT key source = Column(String(50), nullable=False) # "yfinance", "finra_orf", etc. source_file_date = Column(TIMESTAMP(timezone=True), nullable=True) created_at = Column( TIMESTAMP(timezone=True), default=lambda: datetime.now(timezone.utc) ) updated_at = Column( TIMESTAMP(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), ) __table_args__ = ( UniqueConstraint( "ticker", "ex_dividend_date", "as_of_date", "source", name="uq_dividend_calendar", ), Index("idx_dividend_ticker_exdate", "ticker", "ex_dividend_date"), Index("idx_dividend_exdate", "ex_dividend_date"), Index("idx_dividend_as_of", "as_of_date"), # Composite index directly supports DISTINCT ON (ticker, ex_dividend_date) ORDER BY as_of_date DESC Index("idx_dividend_pit_query", "ticker", "ex_dividend_date", "as_of_date"), )