# Data Coverage & Backfill Guide 각 API 엔드포인트의 **실제 DB 보유 데이터 범위**와 **과거 데이터 백필 방법**을 정리한 문서입니다. > 마지막 업데이트: 2026-03-29 > DB 실측 기준 --- ## 요약 테이블 | 엔드포인트 | 데이터 소스 | DB 저장 | 현재 보유 범위 | 이론적 최대 범위 | 백필 필요 | |---|---|---|---|---|---| | `/price` | Yahoo Finance | ✅ | 2018-04-24 ~ 현재 (1682 티커) | 20년+ | 요청 기반 자동 누적 | | `/alpaca/intraday` (SIP, 과거) | Alpaca SIP | ✅ | 요청 기반 자동 누적 | 2016년~어제 | 요청 기반 자동 누적 | | `/alpaca/intraday/today` (IEX, 당일) | Alpaca IEX | ✅ | 당일만 | 오늘 장 중 | 해당 없음 | | `/alpaca/snapshot` | Alpaca IEX | ❌ | 실시간만 | 없음 | 해당 없음 | | `/finra/short-volume` | FINRA CDN | ✅ | **2026-02-10 ~ 현재 (28거래일)** | 수년치 | **⚠️ 백필 권장** | | `/etf/holdings` | SEC EDGAR (NPORT) | ✅ (스냅샷) | 요청 기반 자동 누적 | 2019년~ | 요청 기반 자동 누적 | | `/filings/search` | SEC EDGAR | ✅ | 1994-01-05 ~ 현재 (1598 티커) | 1994년~ | 요청 기반 자동 누적 | | `/stocks/most-active` | Yahoo 실시간 스크래핑 | ❌ | 실시간만 | 없음 | 해당 없음 | | `/stocks/52-week-gainers` | Yahoo 실시간 스크래핑 | ❌ | 실시간만 | 없음 | 해당 없음 | | `/stocks/trending` | Yahoo 실시간 스크래핑 | ❌ | 실시간만 | 없음 | 해당 없음 | | `/overlay/{symbol}` | Yahoo/YouTube/Wikipedia/FINRA | ✅ | 2026-03-17 ~ 현재 (50 심볼) | 서비스 시작 이후 | 과거 백필 불가 | | `/overlay/{symbol}/headlines` | Yahoo Finance RSS | ✅ | 2026-02-24 ~ 현재 | 서비스 시작 이후 | 과거 백필 불가 | | `/overlay/{symbol}/wiki` | Wikipedia Pageviews API | ✅ | 2015-12-26 ~ 현재 | 2015년~ | 자동 수집됨 | | `/insider/transactions` | SEC EDGAR Form 4 | ✅ | 요청 기반 자동 누적 | 2004년~ | 요청 기반 자동 누적 | | `/earnings/surprise` | yfinance-plus earnings_dates | ✅ | 요청 기반 자동 누적 | ~25분기 (6년+) | 요청 기반 자동 누적 | | `/universe/screen` | SEC EDGAR + yfinance 월별 스냅샷 | ✅ (사전 빌드 필요) | admin 빌드 후 사용 가능 | 2010년~ | **⚠️ 사전 빌드 필요** | --- ## 엔드포인트별 상세 --- ### `/api/v1/price` — 주가 (Yahoo Finance) **현재 DB 보유**: 2018-04-24 ~ 현재, 1682 티커, 약 190만 행 **조회 파라미터**: - `period`: `1d` `7d` `30d` `1m` `3m` `6m` `1y` `2y` `5y` `max` - `start_date` + `end_date`: 특정 날짜 범위 (YYYY-MM-DD) - `quarters`: `["2024Q1", "2024Q2"]` 형식 **동작 방식**: DB 캐시 우선 → 누락 구간만 Yahoo Finance에서 실시간 페치 → 자동 저장 **백필**: 별도 작업 불필요. 처음 조회 시 자동으로 인제스트됨. ```bash # 특정 티커 과거 데이터 미리 채우기 (선택 사항) curl -X POST "http://localhost:18001/api/v1/price/data" \ -H "Content-Type: application/json" \ -d '{"ticker": "AAPL", "start_date": "2020-01-01", "end_date": "2024-12-31"}' ``` --- ### `/api/v1/alpaca` — 분봉 (Alpaca API) **엔드포인트 구성**: | 엔드포인트 | 피드 | 용도 | DB 저장 | |---|---|---|---| | `GET /alpaca/intraday` | **SIP** | 과거 분봉 (2016년~어제) | ✅ | | `GET /alpaca/intraday/today` | **IEX** | 당일 실시간 분봉 | ✅ | | `GET /alpaca/snapshot` | **IEX** | 현재가 스냅샷 | ❌ | | `GET /alpaca/status` | — | API 키 유효성 확인 | ❌ | **피드 차이**: - **SIP**: 전체 미국 거래소 통합 데이터. 거래량 100% 정확. 과거 데이터(어제까지) 무료 접근. - **IEX**: IEX 거래소 단일. 실시간이지만 거래량은 실제의 2~5%. 당일 데이터 전용. **필수 조건**: `ALPACA_API_KEY`, `ALPACA_SECRET_KEY` 환경 변수 설정 필요. **이론적 범위**: 2016년~ (Alpaca 무료 플랜 기준) ```bash # 과거 5분봉 조회 (SIP, DB 저장) curl "http://localhost:18001/api/v1/alpaca/intraday?tickers=AAPL,MSFT&interval=5m&start_date=2025-01-01&end_date=2025-01-31" # 당일 실시간 분봉 (IEX) curl "http://localhost:18001/api/v1/alpaca/intraday/today?tickers=AAPL,MSFT&interval=5m" # 현재가 스냅샷 curl "http://localhost:18001/api/v1/alpaca/snapshot?tickers=AAPL,MSFT,SPY" ``` --- ### `/api/v1/finra` — FINRA 공매도 (RegSHO) **현재 DB 보유**: 2026-02-10 ~ 2026-03-20, 28거래일 (서비스 가동 시점부터) > 데이터 소스인 FINRA CDN은 수년치 과거 파일을 보유하고 있으나, 현재 DB에는 최근 28일치만 있음. **조회 파라미터**: - `days`: 최근 N일 (기본 30, 최대 365) - `limit`: 반환 최대 건수 (기본 100, 최대 1000) **⚠️ 백필 방법**: ```bash # 단일 날짜 백필 POST /api/v1/finra/admin/ingest?date=2025-01-02&force=false # 날짜 범위 백필 (권장) POST /api/v1/finra/admin/ingest?start_date=2024-01-01&end_date=2026-02-09&force=false ``` curl 예시: ```bash # 2024년 전체 백필 (~252 거래일 × ~11,000 심볼 = ~280만 행) curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2024-01-01&end_date=2024-12-31" # 2025년 전체 백필 curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2025-01-01&end_date=2025-12-31" # 운영 공백 구간 채우기 (2026-01-01 ~ 2026-02-09) curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2026-01-01&end_date=2026-02-09" ``` > 주의: 1년치 백필 시 ~3000 HTTP 요청 + DB write. 수십 분 소요될 수 있음. FINRA CDN은 API 키 없이 사용 가능하나 과부하를 피하기 위해 범위를 분할해서 실행 권장. --- ### `/api/v1/etf` — ETF 보유 종목 (SEC EDGAR) **현재 DB 보유**: 요청된 ETF 스냅샷만 (요청 기반 자동 누적) **이론적 범위**: 2019년~ (NPORT-P 도입 이후). 일부 ETF는 더 이전 N-Q 파일링 존재. **조회 파라미터**: - `as_of_date`: 기준 날짜 (YYYY-MM-DD). 가장 가까운 파일링 자동 선택. - 생략 시: 가장 최신 파일링 반환. **동작 방식**: 첫 조회 시 SEC EDGAR에서 자동 페치 → 스냅샷 DB 저장. 재조회 시 캐시. ```bash # 특정 날짜 기준 ETF 보유 종목 조회 (자동 캐시) curl "http://localhost:18001/api/v1/etf/holdings/QQQ?as_of_date=2023-12-31" curl "http://localhost:18001/api/v1/etf/holdings/SPY?as_of_date=2022-06-30" ``` > ETF 출시 이전 날짜 요청 시 `availability` 필드에 가능한 날짜 범위 반환됨. --- ### `/api/v1/filings` — SEC 공시 (EDGAR) **현재 DB 보유**: 1994-01-05 ~ 현재, 1598 티커, 약 8000일치 **지원 양식**: `8-K`, `6-K`, `20-F`, `40-F` **조회 파라미터**: - `form_type`: 쉼표 구분 (예: `8-K,6-K`) - `start_date` + `end_date`: 공시 날짜 범위 - `limit` / `offset`: 페이지네이션 (최대 100) **동작 방식**: 첫 조회 시 SEC EDGAR 자동 인덱싱 → DB 저장. 이후 DB 캐시. 1시간 Redis 캐시. **백필**: 별도 작업 불필요. `GET /filings/search/{ticker}` 최초 호출 시 자동 인덱싱됨. ```bash # 특정 티커 전체 8-K 조회 (자동 인덱싱) curl "http://localhost:18001/api/v1/filings/search/AAPL?form_type=8-K&start_date=2020-01-01" # 여러 티커 일괄 인덱싱 curl -X POST "http://localhost:18001/api/v1/filings/search/bulk" \ -H "Content-Type: application/json" \ -d '{"tickers": ["AAPL","MSFT","NVDA","TSLA"], "form_type": "8-K", "limit_per_ticker": 100}' ``` --- ### `/api/v1/stocks` — 시장 현황 (Yahoo Finance 실시간) **현재 DB 보유**: **없음**. 실시간 스크래핑 전용. | 엔드포인트 | 데이터 | 캐시 TTL | |---|---|---| | `/stocks/most-active` | 실시간 상위 ~170 종목 | 1시간 | | `/stocks/52-week-gainers` | 실시간 상위 ~1350 종목 | 1시간 | | `/stocks/trending` | most-active + gainers 결합 | 30분 | > 과거 데이터 조회 불가. 시계열 추적이 필요하면 주기적으로 `/price` 엔드포인트를 통해 개별 종목 가격을 저장하는 별도 배치 작업 필요. --- ### `/api/v1/overlay` — Attention Overlay **현재 DB 보유**: | 데이터 | 보유 범위 | |---|---| | Overlay score (feature records) | 2026-03-17 ~ 현재, 50 심볼 | | 뉴스 헤드라인 | 2026-02-24 ~ 현재 | | Wikipedia 페이지뷰 | 2015-12-26 ~ 현재 (풍부) | | YouTube 멘션 | 서비스 시작 이후 | | Google Trends | 서비스 시작 이후 | **조회 파라미터**: - `/{symbol}`: 최신 composite score - `/{symbol}/history?days=N`: 스코어 시계열 (최대 365일) - `/{symbol}/headlines?hours=N`: 뉴스 (최대 168시간) - `/{symbol}/wiki?days=N`: Wikipedia 페이지뷰 (최대 90일) - `/{symbol}/crowding`: FINRA 기반 crowding 지표 **지원 심볼**: 기본 50개 (`TOP_50_SYMBOLS`). 그 외 심볼은 파이프라인 트리거 필요. **과거 데이터 백필**: Overlay score는 실시간 수집 기반으로 **과거 소급 생성 불가**. Wikipedia 페이지뷰 (`/wiki`)는 2015년부터 조회 가능. ```bash # 파이프라인 수동 트리거 (신규 심볼 추가 시) POST /api/v1/overlay/admin/trigger-pipeline # 특정 심볼의 헬스 상태 확인 GET /api/v1/overlay/admin/health ``` --- ### `/api/v1/insider` — 내부자 거래 (SEC Form 4) **현재 DB 보유**: 요청 기반 자동 누적 (첫 조회 시 자동 인덱싱) **이론적 범위**: 2004년~ (EDGAR 전자 파일링 이후). 실제 커버리지는 기업마다 다름. **조회 파라미터**: - `GET /insider/transactions/{symbol}?days=90&transaction_type=P-Purchase` - `GET /insider/summary/{symbol}?period=90d`: 집계 요약 (매수/매도 금액, 순매수) **지원 거래 유형**: `P-Purchase`, `S-Sale`, `A-Award`, `D-Return`, `F-TaxWithholding`, `G-Gift`, `M-OptionExercise` **동작 방식**: 첫 조회 시 SEC EDGAR Form 4 XML 자동 파싱 → DB 저장. 이후 캐시. ```bash # 최근 90일 내부자 거래 조회 (자동 인덱싱) curl "http://localhost:18001/api/v1/insider/transactions/NVDA?days=90" # 내부자 매매 요약 (순매수/매도 금액) curl "http://localhost:18001/api/v1/insider/summary/AAPL?period=90d" ``` --- ### `/api/v1/earnings` — 어닝 서프라이즈 (yfinance-plus) **현재 DB 보유**: 요청 기반 자동 누적 (첫 조회 시 자동 인덱싱) **이론적 범위**: 약 25분기 (6년+). yfinance `earnings_dates` 데이터 기준. **조회 파라미터**: - `GET /earnings/surprise/{symbol}?limit=20`: 분기별 EPS surprise 이력 **반환 필드**: `reported_eps`, `estimated_eps`, `surprise`, `surprise_percentage`, `streak` - `surprise` = reported_eps − estimated_eps - `surprise_percentage` = (surprise / estimated) × 100 - `streak`: 연속 beat(+) 또는 miss(−) 횟수 **동작 방식**: 첫 조회 시 yfinance `earnings_dates` 자동 인제스트 → DB 저장. 이후 1시간 Redis 캐시. ```bash # 어닝 서프라이즈 이력 조회 (자동 인덱싱) curl "http://localhost:18001/api/v1/earnings/surprise/AAPL?limit=20" ``` --- ### `/api/v1/universe` — 과거 주식 유니버스 (백테스팅) **현재 DB 보유**: admin 엔드포인트로 사전 빌드 필요 (초기에는 빈 상태) **이론적 범위**: 2010년~ (SEC EDGAR 데이터 + yfinance 가격 데이터 가용 범위) **데이터 소스**: SEC EDGAR `companyfacts` (shares_outstanding) × yfinance 월별 종가 → 월별 시총 계산 > **Survivorship bias 주의**: 현재 상장된 종목만 포함. 상폐 종목 미포함. > **정확도**: 시총 오차 ±10~20% (buyback 반영 지연, SEC 분기별 업데이트 때문). #### 워크플로우 ``` 1단계: 유니버스 등록 (1~5분) POST /universe/admin/discover?market_cap_min=100000000 → yfinance screener로 ~3000~5000 종목 발견 → universe_ticker_registry 테이블에 저장 2단계: 스냅샷 빌드 (30~60분, 백그라운드) POST /universe/admin/build-snapshots → SEC EDGAR shares_outstanding × yfinance 월별 종가 = 월별 시총 → universe_snapshot 테이블에 ~480K 행 저장 (4000 × 120개월) 3단계: 과거 스크리닝 GET /universe/screen?date=2018-01-01&market_cap_min=2e9&market_cap_max=20e9 → 2018년 초 기준 시총 $2B~$20B 종목 목록 반환 ``` #### 엔드포인트 상세 **`GET /universe/screen`** — 과거 시점 기준 종목 스크리닝 | 파라미터 | 필수 | 설명 | |---|---|---| | `date` | ✅ | 기준 날짜 YYYY-MM-DD (월초로 자동 반올림) | | `market_cap_min` | - | 최소 시총 (USD), 예: `2e9` = $2B | | `market_cap_max` | - | 최대 시총 (USD), 예: `20e9` = $20B | | `sector` | - | 섹터 필터 (예: `Technology`, `Healthcare`) | | `exchange` | - | 거래소 필터 (`NYSE`, `NASDAQ`, `AMEX`) | | `page` / `page_size` | - | 페이지네이션 (기본 100, 최대 500) | | `sort_by` | - | 정렬 기준 (`market_cap` 또는 `ticker`) | ```bash # 2018년 초 시총 $2B~$20B 종목 (Small/Mid Cap) curl "http://localhost:18001/api/v1/universe/screen?date=2018-01-01&market_cap_min=2000000000&market_cap_max=20000000000" # 2020년 기준 Technology 섹터 Large Cap ($10B+) curl "http://localhost:18001/api/v1/universe/screen?date=2020-01-01&market_cap_min=10000000000§or=Technology" # 2023년 기준 Top 100 시총 순위 curl "http://localhost:18001/api/v1/universe/screen?date=2023-01-01&sort_by=market_cap&sort_ascending=false&page_size=100" ``` **`GET /universe/registry`** — 등록된 종목 목록 조회 ```bash # 등록된 전체 종목 조회 curl "http://localhost:18001/api/v1/universe/registry?page_size=200" # NASDAQ 기술주 필터 curl "http://localhost:18001/api/v1/universe/registry?exchange=NASDAQ§or=Technology" ``` **`POST /universe/admin/discover`** — 종목 발견 및 등록 ```bash # $100M 이상 ~3000~5000 종목 등록 (1~5분 소요) curl -X POST "http://localhost:18001/api/v1/universe/admin/discover?market_cap_min=100000000" # 소규모 테스트 ($1T 이상, ~50 종목) curl -X POST "http://localhost:18001/api/v1/universe/admin/discover?market_cap_min=1000000000000" ``` **`POST /universe/admin/build-snapshots`** — 월별 시총 스냅샷 빌드 ```bash # 소규모 테스트 (3 종목 × 2년, 즉시 반환) curl -X POST "http://localhost:18001/api/v1/universe/admin/build-snapshots" \ -H "Content-Type: application/json" \ -d '{"tickers":["AAPL","MSFT","NVDA"],"start_date":"2023-01-01","end_date":"2024-12-01"}' # 전체 유니버스 × 10년 빌드 (백그라운드, 30~60분) curl -X POST "http://localhost:18001/api/v1/universe/admin/build-snapshots" \ -H "Content-Type: application/json" \ -d '{"start_date":"2015-01-01","end_date":"2025-12-01","force_rebuild":false}' ``` > `tickers` 생략 시 registry 전체 대상. 20개 이하면 동기 실행(즉시 결과), 21개 이상이면 백그라운드 실행. #### 초기 세팅 권장 순서 ```bash # 1. 유니버스 등록 ($100M+ → ~4000 종목) curl -X POST "http://localhost:18001/api/v1/universe/admin/discover?market_cap_min=100000000" # 2. 전체 스냅샷 빌드 (백그라운드 시작) curl -X POST "http://localhost:18001/api/v1/universe/admin/build-snapshots" \ -H "Content-Type: application/json" \ -d '{"start_date":"2015-01-01","end_date":"2025-12-01"}' # 3. 빌드 완료 후 스크리닝 테스트 curl "http://localhost:18001/api/v1/universe/screen?date=2020-01-01&market_cap_min=10000000000" ``` --- ## 백필 우선순위 권장 사항 | 우선순위 | 대상 | 이유 | 예상 소요 시간 | |---|---|---|---| | 🔴 높음 | FINRA 1년치 (2025년) | z-score 계산 윈도우(30일)가 너무 짧아 신호 품질 저하 | 20-40분 | | 🔴 높음 | Universe 스냅샷 빌드 | 백테스팅 유니버스 기능 사용 전 필수 1회 실행 | 30-60분 (4000 종목 × 10년) | | 🟡 중간 | FINRA 2년치 (2024년) | 더 긴 추세 분석 가능 | 1-2시간 | | 🟢 낮음 | Alpaca 데이터 | Yahoo Finance와 중복, API 키 필요 | 필요시 | ### FINRA 권장 백필 스크립트 ```bash # 1단계: 2025년 (가장 중요) curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2025-01-02&end_date=2025-12-31" # 2단계: 2026년 공백 구간 curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2026-01-02&end_date=2026-02-09" # 3단계 (선택): 2024년 curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2024-01-02&end_date=2024-12-31" ``` --- ## 현재 DB 상태 확인 쿼리 ```sql -- 각 테이블 데이터 범위 확인 SELECT 'price_data' AS tbl, MIN(date)::date, MAX(date)::date, COUNT(DISTINCT date::date) AS days, COUNT(DISTINCT ticker) AS tickers FROM price_data UNION ALL SELECT 'finra_short_volume', MIN(date)::date, MAX(date)::date, COUNT(DISTINCT date::date), NULL FROM finra_short_volume UNION ALL SELECT 'sec_filings', MIN(filing_date)::date, MAX(filing_date)::date, COUNT(DISTINCT filing_date::date), COUNT(DISTINCT ticker) FROM sec_filings UNION ALL SELECT 'overlay_feature_records', MIN(as_of_ts)::date, MAX(as_of_ts)::date, COUNT(DISTINCT as_of_ts::date), COUNT(DISTINCT symbol) FROM overlay_feature_records UNION ALL SELECT 'insider_transactions', MIN(transaction_date)::date, MAX(transaction_date)::date, COUNT(DISTINCT transaction_date::date), COUNT(DISTINCT ticker) FROM insider_transactions UNION ALL SELECT 'earnings_surprise', MIN(earnings_date)::date, MAX(earnings_date)::date, COUNT(DISTINCT earnings_date::date), COUNT(DISTINCT ticker) FROM earnings_surprise ORDER BY tbl; -- Universe 스냅샷 상태 확인 SELECT COUNT(DISTINCT ticker) AS tickers, COUNT(*) AS snapshots, MIN(snapshot_date)::date AS earliest, MAX(snapshot_date)::date AS latest FROM universe_snapshot; -- Universe 등록 종목 수 SELECT COUNT(*) AS registered, COUNT(*) FILTER (WHERE is_active) AS active FROM universe_ticker_registry; ```