@ -4,10 +4,21 @@ Alpaca Market Data endpoints — standalone price data via Alpaca API
from datetime import date , datetime , timezone , timedelta
from typing import Optional
from zoneinfo import ZoneInfo
from fastapi import APIRouter , Depends , HTTPException , Query
from sqlalchemy . ext . asyncio import AsyncSession
_ET = ZoneInfo ( " America/New_York " )
_MARKET_CLOSE_HOUR = 16 # 4:00 PM ET
def _market_closed_for ( d : date ) - > bool :
""" Return True if the US equity market session for date d has ended. """
now_et = datetime . now ( _ET )
market_close_et = datetime ( d . year , d . month , d . day , _MARKET_CLOSE_HOUR , 0 , tzinfo = _ET )
return now_et > = market_close_et
from app . core . database import get_db
from app . schemas . financial import (
AlpacaMultiBarsResponse ,
@ -62,12 +73,12 @@ async def alpaca_status():
description = (
" 멀티 종목 과거 분봉 데이터를 Alpaca **SIP 피드**로 가져옵니다. "
" DB에 저장되며 재요청 시 Alpaca 미호출. \n \n "
" **⚠️ 어제(yesterday)까지만 조회 가능** — 당일 데이터는 `/intraday/today` 사용 \n \n "
" **⚠️ 장 중 당일 데이터 불가** — 장 마감(오후 4시 ET) 후에는 당일 날짜도 조회 가능 \n \n "
" | 항목 | 내용 | \n "
" |------|------| \n "
" | 피드 | **SIP** (전체 미국 거래소 통합) | \n "
" | 거래량 | **100 % ** 정확 | \n "
" | 조회 범위 | **2016년~ 어제 ** |\n "
" | 조회 범위 | **2016년~ 오늘(장 마감 후) ** |\n "
" | DB 저장 | 있음 (재요청 시 Alpaca 미사용) | \n \n "
" **권장 용도**: 백테스트, 과거 분봉 분석 \n \n "
" - `tickers`: comma-separated, e.g. `AAPL,MSFT,BF-B` \n "
@ -84,7 +95,7 @@ async def get_alpaca_intraday_multi(
force_refresh : bool = Query ( False , description = " Re-fetch from Alpaca even if DB has data " ) ,
db : AsyncSession = Depends ( get_db ) ,
) :
""" Multi-ticker historical intraday bars via Alpaca SIP (up to yesterday )."""
""" Multi-ticker historical intraday bars via Alpaca SIP (up to today after market close )."""
symbols = [ s . strip ( ) . upper ( ) for s in tickers . split ( " , " ) if s . strip ( ) ]
if not symbols :
raise HTTPException ( status_code = 400 , detail = " No tickers provided. " )
@ -95,11 +106,17 @@ async def get_alpaca_intraday_multi(
_start = start_date or yesterday
_end = end_date or yesterday
if _end > = date . today ( ) :
today = date . today ( )
if _end > today :
raise HTTPException (
status_code = 400 ,
detail = " 미래 날짜는 조회할 수 없습니다. " ,
)
if _end == today and not _market_closed_for ( today ) :
raise HTTPException (
status_code = 400 ,
detail = " 이 엔드포인트는 어제(yesterday)까지의 과거 데이터만 조회 가능합니다. "
" 당일 실시간 데이터는 GET /api/v1/alpaca/intraday/today 를 사용하세요. " ,
detail = " 장 중에는 당일 SIP 데이터를 조회할 수 없습 니다. "
" 실시간 데이터는 GET /api/v1/alpaca/intraday/today 를 사용하세요." ,
)
svc = _require_alpaca ( )