Cloudwiki

KIS 해외주식 시세 확장 검토 (FMP 대체)

제목: CloudStock/KIS 해외주식 시세 확장 검토

> [[CloudStock]] 미국 종목 EOD 시세를 FMP 대신 **한국투자증권(KIS) 해외주식 시세 API** 로 조달할 수 있는지 검토. 결론: **EOD 용도에 한해 가능**. 실행은 다음 작업으로 보류(2026-06-02, KR 파이프라인 마무리 우선).
> 관련: [[CloudStock/FMP Starter 전환 계획]](무료티어 coverage 고통) · [[CloudStock/한국투자증권KIS OpenAPI]](국내 시세 스펙) · [[CloudStock/KR파이프라인]].

[목차]

## 배경 — 왜 검토하나

[[CloudStock/FMP Starter 전환 계획]] 에 정리된 대로 FMP 무료 Basic 은 종목 universe 가 제한적이라 mid/large-cap 일부가 per-ticker `402 Payment Required` 로 시세를 안 준다(38종목 중 23종목 실패 측정). 현재는 시세가 돌아오는 20종목으로 축소해 운영 중이고, 전체 커버리지는 FMP Starter($22/월) 결제가 전제다.

이미 KR 파이프라인용으로 KIS 토큰/시세 인프라(`worker/batch/kis.ts`)가 있으므로, **같은 KIS 키로 미국 주식 시세까지 조달**하면 ① FMP coverage 고통·유료압박 해소 ② 플랫폼 단일화가 가능한지 확인한다.

## KIS 해외주식 시세 엔드포인트 (확인)

공식 GitHub 샘플(`koreainvestment/open-trading-api`)·MCP config 로 교차 확인. 인증(OAuth 토큰·`appkey`/`appsecret` 헤더·`tr_id`)은 **국내 시세와 동일** → 기존 `getKISToken`/`authHeaders` 그대로 재사용.

| 항목 | 기본 현재가 | 현재가 상세 |
|------|-------------|-------------|
| 엔드포인트 | `GET /uapi/overseas-price/v1/quotations/price` | `GET /uapi/overseas-price/v1/quotations/price-detail` |
| TR ID | `HHDFS00000300` | `HHDFS76200200` |
| 파라미터 | `AUTH`(빈문자열), `EXCD`, `SYMB` | `AUTH`, `EXCD`, `SYMB` |
| 주요 output | `last`(현재가)·`base`(전일종가)·`sign`·`diff`(대비)·`rate`(등락률%)·`tvol`(거래량)·`tamt`(거래대금)·`pvol` | 위 + `curr`(통화)·`perx`(PER)·`pbrx`(PBR)·`epsx`·`bpsx`·`shar`(상장주수)·**`mcap`(시가총액)**·`h52p`/`l52p`(52주 고저) |

- `EXCD` 거래소 코드: **`NAS`(나스닥)·`NYS`(뉴욕)·`AMS`(아멕스)**. NYSE/NASDAQ/AMEX 지원.
- 응답은 수치를 문자열로 반환(국내와 동일) → 기존 `toNum` 파서 재사용.

## FMP 필드 매핑

현재 `worker/batch/fmp.ts` 의 `Quote`(`ticker·name·price·change·changePct·marketCap·volume`)를 KIS 로 매핑:

| FMP(Quote) | KIS | 비고 |
|------------|-----|------|
| `price` | `last` | ✅ |
| `changePct` | `rate` | ✅ |
| `change` | `diff`(+`sign`) | ✅ |
| `volume` | `tvol` | ✅ |
| `marketCap` | `mcap` | ⚠️ **기본 `price` 엔드포인트엔 없음 → `price-detail`(HHDFS76200200) 사용 필요**. 단위(천/백만 등) 실측 필요 |
| `name` | (응답에 없음) | KR 처럼 **시드 종목명** 사용 — US universe 20종목이라 부담 없음 |

`pickMovers`(등락률)·`pickCapTop`(시총) 둘 다 충족하려면 **`price-detail` 한 엔드포인트로 통일**.

## 결정적 포인트 — 왜 EOD 면 가능한가

KIS 해외주식 무료시세는 **약 15분 지연**("실시간 지연 체결가")이라 인트라데이엔 부적합하다. 그러나 본 프로젝트 US 파이프라인은 `0 22 * * MON-FRI`(UTC 22:00 = 미 장마감 1~2시간 후) **1일 1회 EOD 배치**다. 발화 시점엔 미장이 이미 마감돼 `last` 가 종가로 확정 → **15분 지연이 무의미**. 즉 KIS 의 유일한 약점이 EOD 용도에서 자연 무력화된다.

(미 장마감: EDT 20:00 UTC / EST 21:00 UTC. cron 22:00 UTC 는 항상 마감 후.)

## 이점

- **FMP coverage 고통 소멸** — KIS 는 상장 미국주식 전체 커버. [[CloudStock/FMP Starter 전환 계획]] 의 20/20 covered/uncovered 분류와 Starter $22/월 압박이 사라진다.
- **인프라 재사용** — 토큰 캐시(`token_cache`)·`authHeaders`·self-throttle 전부 `kis.ts` 에 존재. US 20종목 순차 호출은 KR `fetchKRQuotes` 와 동일 패턴(67ms gap, 20req/s 한도 내).
- **플랫폼 단일화** — KIS 하나로 KR+US 시세 통합. (뉴스는 Finnhub 유지)
- **시간대 무충돌** — KR cron(UTC 00–07)과 US cron(UTC 22) 분리 → 토큰/레이트리밋 경합 없음.
- **비용** — KIS 무료. FMP Starter 결제 회피.

## 추가 작업 / 리스크

1. **EXCD 매핑(최대 추가 작업)** — FMP 는 raw 심볼만 받았지만 KIS 는 종목별 거래소 코드 필수. `tickers`/universe 정의에 `exchange`(NAS/NYS/AMS) 컬럼 시드 필요. KIS 해외종목 마스터파일(`overseas_stock_code`)로 일괄 확인 가능.
2. **종목명 시드** — KIS 시세 응답에 회사명 없음 → DB 시드(`tickers.name_en` 활용).
3. **`mcap` 단위 실측** — capTop 정렬은 상대값이라 무방하나 화면 표기 시 단위 확인. KR 업종코드처럼 **실 시크릿 end-to-end 1회 검증** 권장.
4. **실시간 시세 별도 유료신청** 대상이나 EOD 용도엔 불필요.

## 구현 스케치 (다음 작업)

- `worker/batch/kisOverseas.ts`(또는 `kis.ts` 확장)에 `fetchUSQuotesKIS(env, token, [{ticker,excd}])` 추가 — `price-detail` 순차 호출, `FetchQuotesResult`(quotes/failed) 형태로 FMP 와 동일 계약 반환.
- `worker/batch/stockRadar.ts` 의 `fmp` step 을 KIS 호출로 교체(부분 실패 placeholder 정책 그대로). `FMP_API_KEY` 의존 제거.
- universe 시드에 `exchange` 추가(`migrations/000X_us_exchange.sql`), 종목명 시드 확인.
- [[CloudStock/API 키 발급 목록]] FMP 섹션 → "KIS 로 대체" 로 갱신, [[CloudStock#s-1.12]] 비용표에서 FMP 라인 제거.

## 한 줄 요약

EOD 한정으로 `price-detail`(HHDFS76200200) + EXCD/종목명 시드만 추가하면 FMP→KIS 대체 가능. `kis.ts` 재사용으로 난이도 낮음. 실행은 KR 파이프라인 라이브 검증 이후 진행.