KIS 해외주식 일봉 HHDFS76240000 — MODP 함정
HHDFS76240000 하나로 받되, 세 가지를 직접 정해야 합니다.
거래소를 EXCD로(나스닥 NAS, 주간거래는 BAQ),
수정주가를 MODP로(0 미반영 / 1 반영),
그리고 한 번에 다 오지 않으므로 마지막 날짜를 BYMD에 다시 넣어
과거로 굴리는 연속조회를 직접 짜야 합니다. 국내 일봉 FHKST03010100과는
파라미터 이름도 응답 필드명도 전부 다릅니다.
국내 일봉을 붙여 본 사람이 해외주식으로 넘어오면 같은 자리에서 막힙니다.
fid_input_date_1·fid_input_date_2처럼 기간을 주는 방식이 아니라,
기준일 하나를 주고 그 이전으로 거슬러 올라가는 방식이기 때문입니다.
이 글은 한국투자증권 공식 GitHub 저장소(koreainvestment/open-trading-api)의
파이썬 예제와, 같은 저장소에 들어 있는 공식 백테스터의 KIS 데이터 프로바이더 구현을
2026년 9월 21일 기준으로 읽어 정리한 것입니다.
목차
1. 엔드포인트와 요청 파라미터 6개
해외주식 기간별시세는 하나의 엔드포인트에 tr_id를 붙여 호출합니다.
국내와 달리 실전과 모의투자의 tr_id가 같습니다.
공식 예제 examples_llm/overseas_stock/dailyprice/dailyprice.py는
env_dv가 real이든 demo든 같은 값을 쓰고,
그 외의 값이 들어오면 ValueError를 던지도록 되어 있습니다.
| 항목 | 값 |
|---|---|
| 엔드포인트 | /uapi/overseas-price/v1/quotations/dailyprice |
tr_id | HHDFS76240000 (실전·모의 공통) |
AUTH | 사용자권한정보 — 예제에서는 빈 문자열로 둡니다(사용 안 함) |
EXCD | 거래소코드 (필수) — NAS·NYS·AMS 등 |
SYMB | 종목코드 (필수) — TSLA·AAPL 같은 티커 |
GUBN | 일/주/월 구분 (필수) — 0 일 · 1 주 · 2 월 |
BYMD | 조회기준일자 YYYYMMDD — 공란이면 오늘 |
MODP | 수정주가 반영 (필수) — 0 미반영 · 1 반영 |
KEYB | NEXT KEY BUFF — 예제 주석상 사용 안 함으로 표기 |
필수 검증이 걸려 있는 파라미터는 EXCD·SYMB·GUBN·MODP 넷입니다.
공식 예제는 이 중 하나라도 비면 로그를 찍고 ValueError로 끊습니다.
BYMD는 비어도 통과하고 그때는 오늘 날짜가 기준이 됩니다.
params = {
"AUTH": "", # (사용 안 함)
"EXCD": "NAS", # 나스닥
"SYMB": "TSLA", # 종목 티커
"GUBN": "0", # 0:일 1:주 2:월
"BYMD": "20230101", # 기준일 — 이 날짜 '이전'으로 내려간다
"MODP": "1", # 0:수정주가 미반영 1:반영
"KEYB": "",
}
res = kis._url_fetch("/uapi/overseas-price/v1/quotations/dailyprice",
"HHDFS76240000", tr_cont, params)
기간을 주는 게 아니라 기준일을 준다.
국내 일봉 FHKST03010100은 시작일·종료일을 같이 넣지만,
HHDFS76240000은 BYMD 한 개만 받고 거기서부터 과거로 내려갑니다.
"2020-01-01부터 2024-12-31까지"를 한 번에 요청하는 형태가 아예 없으므로,
시작일에 도달할 때까지 호출을 반복하는 루프는 내가 짜야 합니다.
2. EXCD — 거래소 코드 14개와 주간거래
공식 예제 주석에 적힌 거래소 코드는 다음과 같습니다. 아래 표의 마지막 세 줄, 미국 주간거래(데이마켓) 전용 코드를 놓치는 경우가 많습니다.
| EXCD | 거래소 | EXCD | 거래소 |
|---|---|---|---|
NAS | 나스닥 | SHS | 상해 |
NYS | 뉴욕 | SZS | 심천 |
AMS | 아멕스 | SHI | 상해지수 |
HKS | 홍콩 | SZI | 심천지수 |
TSE | 도쿄 | HSX | 호치민 |
HNX | 하노이 | ||
BAQ | 나스닥(주간) | BAY | 뉴욕(주간) |
BAA | 아멕스(주간) |
같은 저장소의 백테스터 쪽에는 이 매핑이 파이썬 딕셔너리로 들어 있습니다. 거래소 이름을 받아 세 글자 코드로 바꾸고, 표에 없으면 앞 세 글자를 대문자로 잘라 쓰는 방식입니다.
EXCHANGE_TO_KIS = {
"nasdaq": "NAS",
"nyse": "NYS",
"amex": "AMS",
"hkex": "HKS",
"shse": "SHS",
"szse": "SZS",
"tse": "TSE",
}
# 표에 없으면: exchange.upper()[:3]
주간거래를 섞어 쓰는 봇이라면 EXCD를 세션별로 나눠야 합니다.
정규장 나스닥은 NAS, 미국주식 주간거래 세션은 BAQ로 코드가 갈립니다.
같은 AAPL이라도 어느 세션의 캔들을 보느냐에 따라 요청이 달라지므로,
세션 판별과 EXCD 선택을 한 함수에 묶어 두는 편이 안전합니다.
주간거래 주문 쪽 이야기는 미국주식 주간거래 API 편에 정리해 두었습니다.
3. MODP — 수정주가 스위치를 기본값에 맡기지 말 것
MODP는 수정주가 반영 여부입니다. 0이면 미반영,
1이면 반영입니다. 한 글자짜리 파라미터지만 백테스트 결과를 바꿉니다.
MODP=0(미반영) — 당시 실제로 찍혔던 가격 그대로. 액면분할일에 가격이 통째로 점프한 흔적이 남습니다.MODP=1(반영) — 분할·배당을 소급해 과거 가격을 조정. 연속된 시계열이 되지만, 과거 행의 값이 지금 다시 받으면 또 달라질 수 있습니다.
한국투자증권 공식 저장소의 백테스터는 해외주식 일봉을 받을 때
MODP를 "1"로 하드코딩해 두고 있습니다.
백테스트 용도라면 이쪽이 기본값이라고 읽어도 무방합니다.
params = {
"AUTH": "",
"EXCD": kis_excd,
"SYMB": symbol,
"GUBN": "0", # 일봉
"BYMD": current_bymd,
"MODP": "1", # 수정주가 ← 백테스터는 이 값으로 고정
}
어느 쪽이든 "코드에 적어 두는 것"이 요점입니다.
MODP를 빼먹으면 예제 기준으로는 아예 ValueError가 나므로 조용히 틀리지는 않습니다.
문제는 한 번은 0, 한 번은 1로 받아 캐시에 섞어 두는 경우입니다.
같은 종목의 같은 날짜가 두 값으로 존재하면 그 뒤의 어떤 검증도 의미가 없어집니다.
캐시 파일 이름이나 컬럼에 modp를 남겨 두십시오.
4. 연속조회 — BYMD를 굴리는 방식
한 번 호출로 몇 건이 오는지는 종목과 기준일에 따라 다르지만,
10년치가 한 번에 오지는 않습니다.
공식 백테스터는 이 호출을 최대 10회 반복하는 루프로 감싸고,
응답에서 마지막 행의 xymd를 꺼내 다음 요청의 BYMD에 넣습니다.
all_data, tr_cont, current_bymd = [], "", end_str
for _ in range(10):
params = {"AUTH": "", "EXCD": kis_excd, "SYMB": symbol,
"GUBN": "0", "BYMD": current_bymd, "MODP": "1"}
resp = self._auth.get(ApiPath.OVERSEAS_DAILY, params,
TrId.OVERSEAS_DAILY, tr_cont=tr_cont)
if not resp.is_ok():
break
data = resp.get_output2()
if not data:
break
all_data.extend(data)
current_bymd = data[-1].get("xymd", "") # 마지막 날짜로 되감기
tr_cont = getattr(resp.header, 'tr_cont', '')
if tr_cont not in ["M", "F"]: # 더 없으면 종료
break
tr_cont = "N"
self._auth.smart_sleep() # 레이트리밋 대응
여기서 눈여겨볼 곳이 셋입니다.
tr_cont가M또는F일 때만 다음 장이 있습니다. 다음 요청을 보낼 때는 헤더에N을 실어 보냅니다.- 루프에 상한(
range(10))이 걸려 있습니다. 끝날 때까지 도는while True가 아닙니다. 요청한 시작일까지 못 내려갔는데 10바퀴를 다 돌면 조용히 짧은 데이터를 반환합니다 — 받은 첫 행의 날짜를 항상 확인하십시오. - 매 바퀴마다 슬립이 들어갑니다. 같은 저장소의 국내 일봉 쪽 코드에는
EGW00201레이트리밋을 만나면 최대 3회 자동 재시도하는 분기까지 들어 있습니다. 호출 제한 이야기는 EGW00201 편에 따로 정리했습니다.
5. output2 필드명 — 국내 파서가 그대로 안 돈다
응답은 output1과 output2로 나뉩니다.
output1은 종목 요약(단일 객체), output2가 날짜별 캔들 배열입니다.
공식 예제는 output1이 리스트가 아니면 리스트로 한 번 감싸 DataFrame을 만들고,
output2는 그대로 DataFrame으로 만들어 누적합니다.
| output2 필드 | 의미 | 국내 일봉의 대응 필드 |
|---|---|---|
xymd | 일자 YYYYMMDD | stck_bsop_date |
clos | 종가 | stck_clpr |
open | 시가 | stck_oprc |
high | 고가 | stck_hgpr |
low | 저가 | stck_lwpr |
tvol | 거래량 | acml_vol |
sign | 대비기호 | prdy_vrss_sign |
diff | 대비 | prdy_vrss |
rate | 등락율 | prdy_ctrt |
pbid | 매수호가 | — |
즉 국내 일봉용 파서를 그대로 돌리면 KeyError가 납니다.
공식 백테스터도 국내와 해외를 서로 다른 메서드로 분리해 두고,
해외 쪽에서는 xymd·open·high·low·clos·tvol만 꺼내
공통 Bar 객체로 정규화합니다. 파싱 실패는 try/except로 삼키고
경고만 남긴 뒤 그 행을 버리는 구조입니다.
for row in all_data:
try:
bars.append(Bar(
time = datetime.strptime(row.get("xymd", ""), "%Y%m%d"),
open = float(row.get("open", 0)),
high = float(row.get("high", 0)),
low = float(row.get("low", 0)),
close = float(row.get("clos", 0)), # 'close' 아님
volume = int(row.get("tvol", 0)),
))
except (ValueError, TypeError) as e:
logger.warning(f"해외주식 파싱 오류: {e}")
continue
bars.sort(key=lambda b: b.time)
행을 조용히 버리는 구조를 그대로 쓰면 구멍이 생깁니다.
위 코드는 파싱이 실패한 행을 continue로 넘깁니다.
받은 건수와 Bar 개수가 다르면 중간에 빠진 날이 있다는 뜻인데,
정렬까지 끝나고 나면 눈에 띄지 않습니다. 운영에 쓸 때는
len(all_data)와 len(bars)를 비교해 로그로 남기십시오.
데이터가 조용히 비는 문제는 백테스트와 실매매의 괴리에서
가장 흔한 원인 중 하나입니다.
6. FHKST03030100과 헷갈리지 말 것
해외 시세에는 비슷한 이름의 API가 하나 더 있습니다.
해외주식 종목·지수·환율 기간별시세 FHKST03030100
(/uapi/overseas-price/v1/quotations/inquire-daily-chartprice)입니다.
이름만 보면 상위 호환처럼 읽히는데, 미국주식에 한해 종목 범위가 좁습니다.
공식 저장소 예제 주석에 이렇게 적혀 있습니다 — 해당 API로 미국주식을 조회할 경우 다우30·나스닥100·S&P500 종목만 조회 가능하며, 더 많은 미국주식 시세가 필요하면 해외주식 기간별시세 API를 사용하라는 안내입니다. 또한 해외지수 당일 시세는 지연시세 또는 종가시세로 제공된다고 명시되어 있습니다.
| 구분 | HHDFS76240000 | FHKST03030100 |
|---|---|---|
| 이름 | 해외주식 기간별시세 | 해외주식 종목·지수·환율 기간별시세 |
| 경로 | .../quotations/dailyprice | .../quotations/inquire-daily-chartprice |
| 미국주식 범위 | 제한 없음 | 다우30·나스닥100·S&P500 |
| 기간 지정 | BYMD 기준일 되감기 | inqr_strt_dt·inqr_end_dt 구간 |
| 주기 | GUBN 0/1/2 (일·주·월) | period D/W/M/Y |
| 지수·환율 | 지수 EXCD(SHI·SZI) 경유 | 지원 |
정리하면 지수·환율이나 대형주 몇 개만 보면 FHKST03030100이 편하고,
유니버스를 넓게 훑는 스크리너·백테스트라면 HHDFS76240000이 기본입니다.
둘을 섞어 쓸 때는 필드명이 또 달라지므로 소스별 정규화 레이어를 하나 두는 편이 낫습니다.
어떤 데이터 소스를 고를지 자체가 고민이라면
미국주식 백테스트 데이터 비교 편을 먼저 보십시오.
거래량이 없는 날의 종목
같은 예제 주석에 조건검색과의 차이도 적혀 있습니다 —
그날 거래량이나 시세가 형성되지 않은 종목은 HHDFS76240000에서는 조회되지만
해외주식 조건검색 HHDFS76410000에서는 조회되지 않습니다.
조건검색 결과로 유니버스를 만들고 일봉을 채우는 파이프라인이라면,
거래가 없던 날 종목이 통째로 유니버스에서 빠지는 현상이 여기서 나옵니다.
(조건검색 결과 자체도 현재 최대 100개까지만 조회 가능하다고 안내되어 있습니다.)
7. 시세 품질에 대한 공식 고지
미국주식 시세는 무료와 유료가 같은 숫자가 아닙니다. 공식 저장소 예제에 인용된 한국투자증권 안내를 그대로 옮기면 이렇습니다.
- 무료 실시간 시세는 나스닥 마켓센터에서 거래되는 호가·호가잔량 기준(매수·매도 각 1호가)이고, 유료는 미국 전체 거래소들의 통합 주문체결 및 최우선 호가입니다.
- 무료 서비스는 유료 대비 평균 50% 수준에 해당하는 정보이므로 현재가·호가·순간체결량·차트에서 일시적·부분적 차이가 있을 수 있습니다.
- 무료의 시가·저가·고가·종가는 유료와 다를 수 있으며, 종목별 과거 데이터는 장 종료 후(오후 12시경) 유료와 동일하게 업데이트됩니다.
그래서 일봉을 언제 받느냐가 데이터 품질을 바꿉니다. 장 종료 직후에 받은 전일 캔들과, 그 뒤에 다시 받은 같은 날짜의 캔들이 다를 수 있다는 뜻입니다. 배치를 돌린다면 업데이트가 끝난 뒤로 시각을 잡고, 이미 받아 둔 과거 구간을 덮어쓸 때 값이 바뀌는지 한 번은 대조해 보십시오. 같은 성격의 검증 절차를 실전 투입 전 3단계 검증에 정리해 두었습니다.
정리 — 체크리스트 5줄
EXCD를 세션까지 포함해 정했는가 (정규장NAS/ 주간BAQ)MODP를 코드에 명시하고, 캐시에 그 값을 남겼는가- 연속조회 루프의 상한에 걸려 짧은 데이터가 반환되지 않았는지 첫 행 날짜로 확인하는가
output2필드명(xymd·clos·tvol)으로 파싱하는가 — 국내 필드명이 섞이지 않았는가- 받은 행 수와 정규화된 캔들 수가 같은지 로그로 남기는가
해외주식은 국내와 같은 계좌·같은 앱키로 호출하지만 스펙은 다른 세계에 가깝습니다.
현재가는 HHDFS00000300, 일봉은 HHDFS76240000, 주문과 잔고는 또 다른 TR로 갈립니다.
하나씩 붙여 보는 것 말고 지름길은 없고, 이 글이 그중 일봉 한 칸입니다.
미국주식까지 도는 봇을 맡기려면
해외 시세는 필드명부터 세션까지 국내와 따로 놉니다. 어떤 TR을 어디에 붙일지,
데이터는 어디서 받아 어떻게 캐시할지부터 같이 정리해 드립니다. 24시간 빠른 답변 가능합니다.
koreainvestment/open-trading-api)의
examples_llm/overseas_stock/dailyprice/, legacy/Sample01/kis_ovrseastk.py,
그리고 같은 저장소 backtester/kis_backtest/providers/kis/의 구현을
2026년 9월 21일 기준으로 읽어 정리했습니다.
본문의 TR ID·엔드포인트 경로·요청 파라미터·응답 필드명·거래소 코드는 전부 그 시점의 공식 표기이며,
실계좌 호출 결과로 검증한 것이 아닙니다. 코드 예시는 구조를 보이기 위한 골격으로 그대로 실행되는 완제품이 아닙니다.
한 번에 반환되는 건수, 연속조회 동작, 무료·유료 실시간 시세의 범위와 요금은
공지에 따라 변경될 수 있으므로 반드시 한국투자증권 개발자 포털의 현재 명세로 대조하십시오.
이 글은 특정 종목·상품이나 매매 시점에 대한 권유를 담고 있지 않으며,
수익률이나 시장 방향에 대한 어떠한 전망도 하지 않습니다.
알고랩(퀀트웍스)은 투자자문업·투자일임업을 영위하지 않으며, 고객이 정한 규칙을 코드로 구현하는 도구 제작 서비스를 제공합니다.
투자 판단과 그 결과의 책임은 전적으로 투자자 본인에게 있습니다.