- backend/app/seed/themes.py: themes_for_code(code) 헬퍼 추가 (코드 → 소속 테마들)
- backend/app/api/themes.py: GET /api/themes/peer/{code} 신규
· 종목이 속한 모든 테마의 코드 합집합을 peer 풀로
· 단일 SQL (ROW_NUMBER OVER PARTITION BY code) 로 21영업일 누적수익률 일괄 계산
· 본인 / peer 평균 / 상·하위 5종목 반환
- web/lib/api.ts: PeerCompare 타입 + api.peerCompare()
- web/components/PeerComparePanel.tsx: 테마 태그 + 3-칸 요약 (본인/평균/격차) + 상·하위 5
- [code]/page.tsx 에 PeriodReturns 아래 부착. 테마 무소속 종목은 패널 자동 숨김.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
배경: 토요일/봇차단 등으로 KRX 가 LOGOUT/JSONDecodeError 를 주면
pykrx 가 빈 리스트만 돌려줘서 SEED 10 종목 외엔 검색이 안 되는
회귀가 있었다 (기아/네이버/엔비디아 같은 비-seed 검색 실패).
해결: 시총/거래대금 상위 + 친숙도 기준으로 KOSPI 104 / KOSDAQ 52
= 156 개를 정적 스냅샷 (app/seed/krx_static.py) 으로 묶었다.
seed_symbols() 가 KRX 라이브 fetch 결과가 0건이면 자동으로 이
스냅샷에서 upsert. KRX 가 정상 돌아오면 다음 호출이 라이브 데이터로
자연 덮어쓰여진다. 응답에 static_fallback_used 필드 노출.
수록 항목은 KRX 공시 종목코드 + 현재 등록명 (공개 사실).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
10종목 시드 + pykrx OHLCV / 외인·기관 거래대금, KIS read-only EOD, OpenDART
공시, 네이버 금융 뉴스 스크레이퍼, 구글 뉴스 RSS, yfinance 거시(KOSPI/KOSDAQ/
USDKRW/US10Y) fetcher 를 추가하고 refresh_one / daily_batch / backfill /
APScheduler(16:00 KST) 파이프라인으로 묶음.
- backend/app/seed: 10종목 시드 (대형/고변동/테마/플랫폼/방어)
- backend/app/fetch: pykrx, kis, dart, news, macro, symbols_seed
- backend/app/pipelines: refresh_one, daily_batch, backfill(CLI), scheduler
- backend/app/api/refresh.py: POST /api/refresh/{code}?lookback_days=N
- backend/app/main.py: lifespan 으로 스케줄러 기동/종료, /health/keys 추가
- README: .env 복사 안내 보강
스모크 테스트 (실제 키 사용) 결과:
KIS token : ok (token 346자 발급)
KIS daily : 005930 11rows
DART list : 005930 30일 10건
Naver news : 005930 12건
Google RSS : "삼성전자" 92건
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>