- Replace db/schema.sql + raw sqlite3 with SQLAlchemy ORM (db/models.py) - Filing, Signal, PriceCache models with proper indexes - db/db.py uses SQLAlchemy sessions throughout; no raw SQL strings - Add PriceCache table: stores daily close prices per ticker - backtest._fetch_prices checks DB first; skips yfinance for completed ranges - New data persisted via upsert_prices() - get_cached_prices() / upsert_prices() added to db.py - EDGAR poller incremental fetch: get_latest_filed_date() returns newest filed_date in DB; fetch_and_store_new_filings skips entries older than that cutoff before even checking accession_exists - Add get_signals_for_backtest() to db.py; backtest no longer opens its own sqlite3 connection - requirements.txt: add sqlalchemy>=2.0.0 Co-authored-by: dodox <dodox@users.noreply.local>
82 lines
2.2 KiB
Python
82 lines
2.2 KiB
Python
from datetime import datetime
|
|
|
|
from sqlalchemy import (
|
|
Boolean,
|
|
Column,
|
|
DateTime,
|
|
Float,
|
|
Index,
|
|
Integer,
|
|
String,
|
|
Text,
|
|
UniqueConstraint,
|
|
)
|
|
from sqlalchemy.orm import DeclarativeBase
|
|
|
|
|
|
class Base(DeclarativeBase):
|
|
pass
|
|
|
|
|
|
class Filing(Base):
|
|
__tablename__ = "filings"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
accession_number = Column(String, unique=True, nullable=False)
|
|
ticker = Column(String)
|
|
cik = Column(String)
|
|
insider_name = Column(String)
|
|
role = Column(String)
|
|
transaction_date = Column(String)
|
|
filed_date = Column(String)
|
|
shares = Column(Float)
|
|
price = Column(Float)
|
|
total_value = Column(Float)
|
|
flag = Column(String)
|
|
is_10b51 = Column(Boolean, default=False)
|
|
post_tx_shares = Column(Float)
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
__table_args__ = (
|
|
Index("idx_filings_ticker", "ticker"),
|
|
Index("idx_filings_transaction_date", "transaction_date"),
|
|
Index("idx_filings_filed_date", "filed_date"),
|
|
)
|
|
|
|
|
|
class Signal(Base):
|
|
__tablename__ = "signals"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
ticker = Column(String)
|
|
trigger_date = Column(String)
|
|
cluster_size = Column(Integer)
|
|
total_cluster_value = Column(Float)
|
|
score = Column(Float)
|
|
alerted = Column(Boolean, default=False)
|
|
executed = Column(Boolean, default=False)
|
|
executed_at = Column(DateTime)
|
|
closed = Column(Boolean, default=False)
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
__table_args__ = (
|
|
Index("idx_signals_ticker", "ticker"),
|
|
Index("idx_signals_alerted", "alerted"),
|
|
Index("idx_signals_executed", "executed"),
|
|
)
|
|
|
|
|
|
class PriceCache(Base):
|
|
__tablename__ = "price_cache"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
ticker = Column(String, nullable=False)
|
|
date = Column(String, nullable=False)
|
|
close = Column(Float, nullable=False)
|
|
fetched_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("ticker", "date", name="uq_price_cache_ticker_date"),
|
|
Index("idx_price_cache_ticker_date", "ticker", "date"),
|
|
)
|