feat: add Polygon grouped daily endpoint for broad market data
Two tiers of market data: 1. Per-ticker prev bars (existing 50 sources, 15-min cadence) for watchlist detail — trading decisions, stop-loss, position sizing 2. Grouped daily (new single source, once per day) for broad market context — correlation analysis, sector rotation, competitive intel Changes: - Add grouped_daily endpoint to PolygonMarketAdapter with auto date calculation (previous trading day, skip weekends) - Add fetch_global_market_sources() to scheduler for sources without company_id, scheduled once daily (86400s cadence) - Update _persist_market_items to use item-level ticker from T field and look up company_id dynamically for grouped daily bars - Migration 020: make company_id nullable on sources and market_snapshots tables, add grouped daily source row - Fix backtest replay to query market_snapshots data->>'c' for prices
This commit is contained in:
@@ -43,6 +43,7 @@ class PolygonMarketAdapter(MarketDataAdapter):
|
||||
|
||||
PREV_BARS = "/v2/aggs/ticker/{ticker}/prev"
|
||||
RANGE_BARS = "/v2/aggs/ticker/{ticker}/range/{multiplier}/{timespan}/{from_date}/{to_date}"
|
||||
GROUPED_DAILY = "/v2/aggs/grouped/locale/us/market/stocks/{date}"
|
||||
TICKER_DETAILS = "/v3/reference/tickers/{ticker}"
|
||||
|
||||
def __init__(self, api_key: str, base_url: str = "https://api.polygon.io") -> None:
|
||||
@@ -132,6 +133,20 @@ class PolygonMarketAdapter(MarketDataAdapter):
|
||||
params["sort"] = config["sort"]
|
||||
if config.get("limit"):
|
||||
params["limit"] = str(config["limit"])
|
||||
elif endpoint_key == "grouped_daily":
|
||||
# Grouped daily: returns bars for ALL tickers for a given date
|
||||
target_date = config.get("date", "")
|
||||
if not target_date:
|
||||
# Default to previous trading day
|
||||
from datetime import date, timedelta
|
||||
today = date.today()
|
||||
prev = today - timedelta(days=1)
|
||||
# Skip weekends
|
||||
while prev.weekday() > 4:
|
||||
prev -= timedelta(days=1)
|
||||
target_date = prev.isoformat()
|
||||
path = self.GROUPED_DAILY.format(date=target_date)
|
||||
params["adjusted"] = str(config.get("adjusted", True)).lower()
|
||||
elif endpoint_key == "ticker_details":
|
||||
path = self.TICKER_DETAILS.format(ticker=ticker)
|
||||
else:
|
||||
@@ -149,6 +164,7 @@ class PolygonMarketAdapter(MarketDataAdapter):
|
||||
return [results] if isinstance(results, dict) and results else []
|
||||
|
||||
# Aggregate endpoints return results as a list
|
||||
# For grouped_daily, each item has a "T" field with the ticker
|
||||
results = data.get("results", [])
|
||||
if isinstance(results, list):
|
||||
return results
|
||||
|
||||
Reference in New Issue
Block a user