Spaces:
Sleeping
Sleeping
File size: 4,751 Bytes
9d29748 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | """
Quantitative Models: Features, Factors, and Signals.
Stores computed quantitative data — technical features,
factor exposures, and generated trading signals.
"""
from __future__ import annotations
from datetime import date, datetime
from sqlalchemy import Date, DateTime, Float, ForeignKey, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database import Base
class FeatureData(Base):
"""Computed technical features for an asset (SMA, RSI, MACD, etc.)."""
__tablename__ = "feature_data"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
asset_id: Mapped[int] = mapped_column(
Integer, ForeignKey("assets.id"), nullable=False, index=True
)
date: Mapped[date] = mapped_column(Date, nullable=False, index=True)
feature_name: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
feature_value: Mapped[float] = mapped_column(Float, nullable=True)
parameters_json: Mapped[str] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
asset = relationship("Asset", back_populates="features")
def __repr__(self) -> str:
return f"<FeatureData({self.feature_name}={self.feature_value}, date={self.date})>"
class Factor(Base):
"""Quantitative factor definition (momentum, value, size, etc.)."""
__tablename__ = "factors"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False, index=True)
display_name: Mapped[str] = mapped_column(String(200), nullable=True)
description: Mapped[str] = mapped_column(Text, nullable=True)
category: Mapped[str] = mapped_column(
String(50), nullable=False
) # style, macro, sector, custom
calculation_method: Mapped[str] = mapped_column(Text, nullable=True)
is_active: Mapped[bool] = mapped_column(default=True, nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
exposures = relationship("FactorExposure", back_populates="factor", lazy="noload")
def __repr__(self) -> str:
return f"<Factor(name='{self.name}', category='{self.category}')>"
class FactorExposure(Base):
"""Factor exposure (loading) for an asset on a given date."""
__tablename__ = "factor_exposures"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
asset_id: Mapped[int] = mapped_column(
Integer, ForeignKey("assets.id"), nullable=False, index=True
)
factor_id: Mapped[int] = mapped_column(
Integer, ForeignKey("factors.id"), nullable=False, index=True
)
date: Mapped[date] = mapped_column(Date, nullable=False, index=True)
exposure_value: Mapped[float] = mapped_column(Float, nullable=False)
z_score: Mapped[float] = mapped_column(Float, nullable=True)
percentile_rank: Mapped[float] = mapped_column(Float, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
asset = relationship("Asset", back_populates="factor_exposures")
factor = relationship("Factor", back_populates="exposures")
def __repr__(self) -> str:
return f"<FactorExposure(asset={self.asset_id}, factor={self.factor_id}, value={self.exposure_value})>"
class Signal(Base):
"""Generated quantitative trading signal."""
__tablename__ = "signals"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(200), nullable=False, index=True)
signal_type: Mapped[str] = mapped_column(
String(50), nullable=False
) # momentum, mean_reversion, sentiment, volatility, factor
asset_id: Mapped[int] = mapped_column(
Integer, ForeignKey("assets.id"), nullable=True, index=True
)
date: Mapped[date] = mapped_column(Date, nullable=False, index=True)
value: Mapped[float] = mapped_column(Float, nullable=False)
strength: Mapped[float] = mapped_column(Float, nullable=True) # 0-1 confidence
direction: Mapped[str] = mapped_column(
String(10), nullable=True
) # long, short, neutral
metadata_json: Mapped[str] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)
asset = relationship("Asset", back_populates="signals")
def __repr__(self) -> str:
return f"<Signal(name='{self.name}', type='{self.signal_type}', direction='{self.direction}')>"
|