날짜만 보내면(2026-04-15) Alpaca가 ET 자정(23:59 ET = 03:59 UTC)으로 해석해
당일 장 마감 후에도 "미래 end" 로 판정 → SIP 403 에러 발생.
RFC-3339 datetime 형식(2026-04-15T23:59:59Z)으로 변경하면
Alpaca가 UTC 기준으로 정확히 해석해 15분 규칙을 통과함.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BaseHTTPMiddleware는 요청당 2개 asyncio task를 생성한다.
--limit-concurrency 100은 여전히 200개 task가 event loop를 포화시켜
health check 포함 모든 요청이 block됐다.
변경 사항:
- docker-compose.yml: --limit-concurrency 100 → 20
(세마포어 10개 처리 + 10개 대기, 나머지 20초과 시 503으로 즉시 반환)
- alpaca_price_service.py: upsert 루프 청크 사이 + Phase 4 ORM 일괄 생성 후
await asyncio.sleep(0) 추가 — 동기 CPU 블로킹 중 event loop yield 보장
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
서비스 메서드가 db: AsyncSession을 인자로 받아 외부 API 호출(yfinance 30-60s,
Alpaca HTTP) 중에도 DB 커넥션을 잡고 있던 구조를 제거.
변경 패턴 (Session-per-phase):
Before: Endpoint(db) → Service(db) → DB check → API call(30s 세션 유지) → DB store
After: Endpoint() → Service() → DB check(세션1) → API call(세션 없음) → DB store(세션2)
변경 파일:
- alpaca_price_service.py: fetch_and_store_bars, get_or_fetch_multi_bars에서 db 제거
- price_data_service.py: get_or_update_price_data, get_multiple_tickers_data_optimized에서
db 제거; _fetch_price_data(새), _bulk_fetch_price_data(새, lambda 클로저 버그 수정);
_fetch_and_store_price_data, _bulk_fetch_and_store_price_data, get_multiple_tickers_data 제거
- alpaca.py, price.py: Depends(get_db) 제거 (GET /latest 제외)
- financial_service.py, real_sec_financial_service.py: 호출 인자 정리
결과: "idle in transaction" 커넥션 0개, 풀 고갈 원인 근본 해결
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- interval 누락으로 uq_alpaca_price_data constraint 위반 방지
- 단일 INSERT → CHUNK=2300 분할 (14 params/row, asyncpg 한도 대비)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- AlpacaPriceService.get_or_fetch_multi_bars(): checks DB max_date per
ticker, only fetches missing ranges from Alpaca, upserts with chunking
(3000 rows/chunk, asyncpg 32767-param limit) then reads back from DB
- GET /price/data endpoint: now uses service + Depends(get_db); subsequent
calls for same date range skip Alpaca entirely
- force_refresh=true bypasses DB check and re-fetches all from Alpaca
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Separate Alpaca price data into dedicated AlpacaPriceData table to avoid
UniqueConstraint('ticker', 'date') conflicts with Yahoo Finance PriceData.
Add Redis caching (build_cache_key/get_cached_response/set_cached_response)
to 3 Alpaca endpoints and 2 FINRA query endpoints with appropriate TTLs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>