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.
115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
"""
|
|
Attention subsystem models — event-centric attention data for backtest-friendly queries.
|
|
|
|
Completely separate from the overlay subsystem (which is real-time monitoring).
|
|
This subsystem is designed for fithia2 backtester to query attention data
|
|
relative to events (earnings, etc.).
|
|
"""
|
|
|
|
from sqlalchemy import Column, String, Float, Boolean, Integer, Text, Date, Index, UniqueConstraint, JSON
|
|
from sqlalchemy.dialects.postgresql import UUID, TIMESTAMP
|
|
from datetime import datetime, timezone
|
|
import uuid
|
|
|
|
from app.core.database import Base
|
|
|
|
|
|
class CompanyEntityMap(Base):
|
|
"""Ticker → canonical company entity mapping with Wikipedia and GDELT resolution."""
|
|
|
|
__tablename__ = "company_entity_map"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
ticker = Column(String(10), unique=True, nullable=False, index=True)
|
|
canonical_name = Column(String(500), nullable=False)
|
|
wiki_title = Column(String(500), nullable=True)
|
|
gdelt_query = Column(String(1000), nullable=True)
|
|
aliases_json = Column(JSON, default=list)
|
|
resolver_confidence = Column(Float, default=0.0)
|
|
is_manual_override = Column(Boolean, default=False)
|
|
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__ = (
|
|
Index("idx_company_entity_map_ticker", "ticker"),
|
|
)
|
|
|
|
|
|
class WikiPageviewsDaily(Base):
|
|
"""Daily Wikipedia pageview counts per article title."""
|
|
|
|
__tablename__ = "wiki_pageviews_daily"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
wiki_title = Column(String(500), nullable=False)
|
|
date = Column(Date, nullable=False)
|
|
views = Column(Integer, nullable=False)
|
|
created_at = Column(
|
|
TIMESTAMP(timezone=True), default=lambda: datetime.now(timezone.utc)
|
|
)
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("wiki_title", "date", name="uq_wiki_pageviews_daily"),
|
|
Index("idx_wiki_pageviews_daily_title_date", "wiki_title", "date"),
|
|
)
|
|
|
|
|
|
class GdeltArticleRaw(Base):
|
|
"""Raw GDELT article records matched to a ticker."""
|
|
|
|
__tablename__ = "gdelt_article_raw"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
url = Column(String(2000), unique=True, nullable=False)
|
|
title = Column(Text, nullable=True)
|
|
domain = Column(String(255), nullable=True)
|
|
published_at = Column(TIMESTAMP(timezone=True), nullable=True)
|
|
sourcecountry = Column(String(10), nullable=True)
|
|
matched_ticker = Column(String(10), nullable=False, index=True)
|
|
match_method = Column(String(50), nullable=True)
|
|
match_confidence = Column(Float, default=1.0)
|
|
created_at = Column(
|
|
TIMESTAMP(timezone=True), default=lambda: datetime.now(timezone.utc)
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index("idx_gdelt_article_raw_ticker", "matched_ticker"),
|
|
Index("idx_gdelt_article_raw_published_at", "published_at"),
|
|
)
|
|
|
|
|
|
class AttentionFeaturesDaily(Base):
|
|
"""Derived daily attention features per ticker — materialized from wiki + gdelt raw data."""
|
|
|
|
__tablename__ = "attention_features_daily"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
ticker = Column(String(10), nullable=False)
|
|
date = Column(Date, nullable=False)
|
|
|
|
# Wikipedia features
|
|
wiki_views = Column(Integer, nullable=True)
|
|
wiki_spike_10d = Column(Float, nullable=True)
|
|
wiki_zscore_20d = Column(Float, nullable=True)
|
|
|
|
# GDELT / news features
|
|
gdelt_article_count_1d = Column(Integer, default=0)
|
|
gdelt_article_count_3d = Column(Integer, default=0)
|
|
gdelt_unique_domains_3d = Column(Integer, default=0)
|
|
gdelt_us_article_count_3d = Column(Integer, default=0)
|
|
|
|
created_at = Column(
|
|
TIMESTAMP(timezone=True), default=lambda: datetime.now(timezone.utc)
|
|
)
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("ticker", "date", name="uq_attention_features_daily"),
|
|
Index("idx_attention_features_daily_ticker_date", "ticker", "date"),
|
|
)
|