"""TimescaleDB hypertable models: MarketData, PortfolioSnapshot, StrategyMetric.""" import uuid from datetime import datetime from sqlalchemy import DateTime, Float, ForeignKey, Integer, String from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from shared.models.base import Base class MarketData(Base): """OHLCV bars — intended as a TimescaleDB hypertable partitioned by timestamp.""" __tablename__ = "market_data" timestamp: Mapped[datetime] = mapped_column( DateTime(timezone=True), primary_key=True ) ticker: Mapped[str] = mapped_column(String(20), primary_key=True) open: Mapped[float] = mapped_column(Float, nullable=False) high: Mapped[float] = mapped_column(Float, nullable=False) low: Mapped[float] = mapped_column(Float, nullable=False) close: Mapped[float] = mapped_column(Float, nullable=False) volume: Mapped[float] = mapped_column(Float, nullable=False) class PortfolioSnapshot(Base): """Periodic portfolio value snapshots — TimescaleDB hypertable.""" __tablename__ = "portfolio_snapshots" timestamp: Mapped[datetime] = mapped_column( DateTime(timezone=True), primary_key=True ) total_value: Mapped[float] = mapped_column(Float, nullable=False) cash: Mapped[float] = mapped_column(Float, nullable=False) positions_value: Mapped[float] = mapped_column(Float, nullable=False) daily_pnl: Mapped[float] = mapped_column(Float, nullable=False) class StrategyMetric(Base): """Per-strategy performance over time — TimescaleDB hypertable.""" __tablename__ = "strategy_metrics" timestamp: Mapped[datetime] = mapped_column( DateTime(timezone=True), primary_key=True ) strategy_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("strategies.id"), primary_key=True ) win_rate: Mapped[float] = mapped_column(Float, nullable=False) total_pnl: Mapped[float] = mapped_column(Float, nullable=False) trade_count: Mapped[int] = mapped_column(Integer, nullable=False) sharpe_ratio: Mapped[float | None] = mapped_column(Float, nullable=True)