@ -2,6 +2,7 @@
Alpaca Market Data endpoints — standalone price data via Alpaca API
"""
import asyncio
from datetime import date , datetime , timezone , timedelta
from typing import Optional
from zoneinfo import ZoneInfo
@ -11,6 +12,11 @@ from fastapi import APIRouter, HTTPException, Query
_ET = ZoneInfo ( " America/New_York " )
_MARKET_CLOSE_HOUR = 16 # 4:00 PM ET
# Limit concurrent Alpaca intraday processing to prevent event-loop saturation
# under bulk backfill workloads. Callers beyond this limit wait on the semaphore
# (cheap asyncio wait) rather than flooding httpx connections and DB sessions.
_INTRADAY_SEMAPHORE = asyncio . Semaphore ( 10 )
def _market_closed_for ( d : date ) - > bool :
""" Return True if the US equity market session for date d has ended. """
@ -120,6 +126,7 @@ async def get_alpaca_intraday_multi(
start_dt = datetime . combine ( _start , datetime . min . time ( ) ) . replace ( tzinfo = timezone . utc )
end_dt = datetime . combine ( _end , datetime . max . time ( ) ) . replace ( tzinfo = timezone . utc )
async with _INTRADAY_SEMAPHORE :
try :
data = await svc . get_or_fetch_multi_bars (
symbols , start_dt , end_dt , interval , force_refresh , feed = " sip "
@ -193,6 +200,7 @@ async def get_alpaca_intraday_today(
start_dt = datetime . combine ( today , datetime . min . time ( ) ) . replace ( tzinfo = timezone . utc )
end_dt = datetime . combine ( today , datetime . max . time ( ) ) . replace ( tzinfo = timezone . utc )
async with _INTRADAY_SEMAPHORE :
try :
data = await svc . get_or_fetch_multi_bars (
symbols , start_dt , end_dt , interval , force_refresh = True , feed = " iex "