docs: Alpaca 엔드포인트 전체 IEX/SIP 피드 정보 명시

- /bars/{ticker}, /data/{ticker}: interval별 자동 피드 선택 표 추가
- /intraday/{ticker}: IEX 피드, 5분 캐시, DB 없음 명시
- /snapshot, /snapshot/{ticker}: IEX 강제 (무료 플랜 제한) 명시
- openapi.json 업데이트 (95 endpoints)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
I Luk Kim 4 months ago
parent 9882592ac1
commit 75b3a356d0

@ -74,8 +74,15 @@ async def alpaca_status():
summary="Get Alpaca bars (raw, no DB)", summary="Get Alpaca bars (raw, no DB)",
description=( description=(
"Fetch historical bars directly from Alpaca without storing in DB.\n\n" "Fetch historical bars directly from Alpaca without storing in DB.\n\n"
"**주의**: 이 엔드포인트는 DB에 저장하지 않음. 저장이 필요하면 `/alpaca/data/{ticker}` 사용.\n\n" "**데이터 소스 (피드 자동 선택)**\n\n"
"**이론적 범위**: Alpaca API 제공 범위 (~20년). `ALPACA_API_KEY` / `ALPACA_SECRET_KEY` 필수." "| interval | 피드 | 특성 |\n"
"|----------|------|------|\n"
"| `1m` `5m` `15m` `30m` `1h` | **IEX** | 실시간, 거래량 2~5%, 무료 |\n"
"| `1d` `1w` `1mo` | **SIP** | 전체 거래소 통합, 정확, 무료 |\n\n"
"- DB에 저장하지 않음 — 저장이 필요하면 `/alpaca/data/{ticker}` 사용\n"
"- 조회 범위: 2016년~ (Alpaca 무료 플랜 기준)\n"
"- Redis 24시간 캐시 적용 (`force_refresh=true`로 우회)\n"
"- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`"
), ),
) )
@with_cache(namespace="alpaca:bars", ttl=86400, key_params=["ticker", "interval", "start_date", "end_date", "limit"]) @with_cache(namespace="alpaca:bars", ttl=86400, key_params=["ticker", "interval", "start_date", "end_date", "limit"])
@ -126,11 +133,15 @@ async def get_alpaca_bars(
description=( description=(
"Fetch OHLCV price data from Alpaca, store in AlpacaPriceData table, and return " "Fetch OHLCV price data from Alpaca, store in AlpacaPriceData table, and return "
"in PriceDataResponse format. Includes vwap and trade_count in metadata.\n\n" "in PriceDataResponse format. Includes vwap and trade_count in metadata.\n\n"
"**데이터 소스 (피드 자동 선택)**\n\n"
"| interval | 피드 | 특성 |\n"
"|----------|------|------|\n"
"| `1m` `5m` `15m` `30m` `1h` | **IEX** | 실시간, 거래량 2~5%, 무료 |\n"
"| `1d` `1w` `1mo` | **SIP** | 전체 거래소 통합, 정확, 무료 |\n\n"
"- DB 저장 후 재요청 시 Alpaca 미사용 (DB-first)\n"
"- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`\n" "- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`\n"
"- Uses `data_source = \"ALPACA\"` to distinguish from Yahoo data\n" "- `data_source = \"ALPACA\"`로 Yahoo Finance 데이터와 구분\n"
"- Supports: 1m, 5m, 15m, 1h, 1d, 1w, 1mo intervals\n\n" "- 조회 범위: 2016년~ (Alpaca 무료 플랜 기준)"
"**현재 DB 보유**: 현재 테스트 데이터만 존재 (AAPL 27일치). "
"백필은 이 엔드포인트를 원하는 날짜 범위로 호출하면 자동으로 DB에 누적됨."
), ),
) )
@with_cache(namespace="alpaca:data", ttl=86400, key_params=["ticker", "interval", "start_date", "end_date"]) @with_cache(namespace="alpaca:data", ttl=86400, key_params=["ticker", "interval", "start_date", "end_date"])
@ -402,8 +413,21 @@ async def get_alpaca_intraday_today(
@router.get( @router.get(
"/intraday/{ticker}", "/intraday/{ticker}",
response_model=AlpacaIntradayResponse, response_model=AlpacaIntradayResponse,
summary="Get intraday candles from Alpaca", summary="Get intraday candles from Alpaca (single ticker, IEX feed)",
description="Fetch intraday bars (1m, 5m, 15m, 1h) directly from Alpaca. Not stored in DB.", description=(
"단일 종목의 분봉 데이터를 Alpaca **IEX 피드**로 직접 가져옵니다.\n\n"
"**데이터 소스: IEX 피드**\n\n"
"| 항목 | 내용 |\n"
"|------|------|\n"
"| 피드 | **IEX** (IEX 거래소 단일) |\n"
"| 지연 | **실시간** (지연 없음) |\n"
"| 거래량 커버리지 | 미국 전체 시장의 약 **2~5%** |\n"
"| DB 저장 | **없음** — 매 요청 Alpaca 직접 호출 |\n"
"| 캐시 | Redis **5분 TTL** |\n\n"
"멀티 종목이 필요하면 → `GET /api/v1/alpaca/intraday/today` (오늘) 또는 "
"`GET /api/v1/alpaca/intraday` (과거, SIP)\n\n"
"- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`"
),
) )
@with_cache(namespace="alpaca:intraday", ttl=300, key_params=["ticker", "interval", "start_date", "end_date"]) @with_cache(namespace="alpaca:intraday", ttl=300, key_params=["ticker", "interval", "start_date", "end_date"])
async def get_alpaca_intraday( async def get_alpaca_intraday(
@ -482,11 +506,18 @@ def _parse_snapshot(ticker: str, raw: dict) -> AlpacaSnapshotResponse:
@router.get( @router.get(
"/snapshot/{ticker}", "/snapshot/{ticker}",
response_model=AlpacaSnapshotResponse, response_model=AlpacaSnapshotResponse,
summary="Real-time snapshot for a single ticker", summary="Real-time snapshot for a single ticker (IEX feed)",
description=( description=(
"Returns the latest trade price, bid/ask, today's OHLCV, and change vs previous close " "단일 종목의 실시간 스냅샷을 반환합니다. 최신 체결가, bid/ask, 당일 OHLCV, 전일 대비 변동률 포함.\n\n"
"using Alpaca's `/v2/stocks/{symbol}/snapshot` endpoint.\n\n" "**데이터 소스: IEX 피드 (무료 플랜 강제)**\n\n"
"**캐시 없음** — 매 요청마다 Alpaca API를 직접 호출." "| 항목 | 내용 |\n"
"|------|------|\n"
"| 피드 | **IEX** — 무료 플랜에서 snapshot은 SIP 불가 |\n"
"| 지연 | **실시간** (지연 없음) |\n"
"| 거래량 | IEX 기준 (실제의 2~5%) |\n"
"| High/Low | IEX 기준 (실제보다 range 좁을 수 있음) |\n"
"| 캐시 | **없음** — 매 요청마다 Alpaca 직접 호출 |\n\n"
"- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`"
), ),
) )
async def get_snapshot(ticker: str): async def get_snapshot(ticker: str):
@ -505,11 +536,18 @@ async def get_snapshot(ticker: str):
@router.get( @router.get(
"/snapshot", "/snapshot",
response_model=AlpacaMultiSnapshotResponse, response_model=AlpacaMultiSnapshotResponse,
summary="Real-time snapshots for multiple tickers", summary="Real-time snapshots for multiple tickers (IEX feed)",
description=( description=(
"Returns snapshots for up to 100 tickers in a single request.\n\n" "멀티 종목의 실시간 스냅샷을 한 번의 요청으로 반환합니다.\n\n"
"**데이터 소스: IEX 피드 (무료 플랜 강제)**\n\n"
"| 항목 | 내용 |\n"
"|------|------|\n"
"| 피드 | **IEX** — 무료 플랜에서 snapshot은 SIP 불가 |\n"
"| 지연 | **실시간** (지연 없음) |\n"
"| 거래량 | IEX 기준 (실제의 2~5%) |\n"
"| 캐시 | **없음** — 매 요청마다 Alpaca 직접 호출 |\n\n"
"**Usage**: `?tickers=AAPL,MSFT,NVDA`\n\n" "**Usage**: `?tickers=AAPL,MSFT,NVDA`\n\n"
"**캐시 없음** — 매 요청마다 Alpaca API를 직접 호출." "- Requires `ALPACA_API_KEY` / `ALPACA_SECRET_KEY`"
), ),
) )
async def get_snapshots( async def get_snapshots(

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save