feat: cap-tier filtering, Alpaca cost model, README cleanup
- simulate.py: --cap-tier large|mid|small|micro; yfinance market cap fetch with DB cache (ticker_meta table); argv fix for main.py dispatch - plot.py: equity curves now show cap tiers with Alpaca costs (zero commission); HP sweep uses Alpaca cost decomposition; SPY line clamped to last strategy date - db/models.py: TickerMeta table - db/db.py: get_cached_market_caps, upsert_market_caps - README: add --cap-tier to simulate docs; backfill note (~3 days for 2 years at SEC 10 req/s limit); remove duplicate setup block; remove em-dashes in prose; results table tilde estimates to be updated once cap-tier sims complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
import config
|
||||
from db.models import Base, Filing, PriceCache, Signal
|
||||
from db.models import Base, Filing, PriceCache, Signal, TickerMeta
|
||||
|
||||
|
||||
def _engine():
|
||||
@@ -219,6 +219,28 @@ def get_signals_for_backtest(min_score: float, min_cluster_size: int) -> list[di
|
||||
return [_signal_to_dict(r) for r in rows]
|
||||
|
||||
|
||||
def get_cached_market_caps(tickers: list[str]) -> dict[str, float]:
|
||||
if not tickers:
|
||||
return {}
|
||||
with _session() as session:
|
||||
rows = session.scalars(
|
||||
select(TickerMeta).where(TickerMeta.ticker.in_(tickers))
|
||||
).all()
|
||||
return {r.ticker: r.market_cap for r in rows if r.market_cap is not None}
|
||||
|
||||
|
||||
def upsert_market_caps(caps: dict[str, float]) -> None:
|
||||
with _session() as session:
|
||||
for ticker, cap in caps.items():
|
||||
existing = session.get(TickerMeta, ticker)
|
||||
if existing:
|
||||
existing.market_cap = cap
|
||||
existing.fetched_at = datetime.utcnow()
|
||||
else:
|
||||
session.add(TickerMeta(ticker=ticker, market_cap=cap))
|
||||
session.commit()
|
||||
|
||||
|
||||
def get_cached_prices(ticker: str, start_date: str, end_date: str) -> dict[str, float]:
|
||||
with _session() as session:
|
||||
rows = session.scalars(
|
||||
|
||||
@@ -66,6 +66,14 @@ class Signal(Base):
|
||||
)
|
||||
|
||||
|
||||
class TickerMeta(Base):
|
||||
__tablename__ = "ticker_meta"
|
||||
|
||||
ticker = Column(String, primary_key=True)
|
||||
market_cap = Column(Float, nullable=True)
|
||||
fetched_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
|
||||
class PriceCache(Base):
|
||||
__tablename__ = "price_cache"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user