한국투자증권 API 파이썬 예제 — 공식 깃허브 실행
koreainvestment/open-trading-api에 있고,
처음 안 돌아가는 이유는 거의 항상 코드가 아니라 설정 파일 위치입니다.
저장소 루트의 kis_devlp.yaml을 ~/KIS/config/로 복사한 뒤 값을 채워야 합니다.
인증 모듈 kis_auth.py가 설정을 저장소가 아니라 홈 폴더에서 찾도록
config_root에 박아 두었기 때문입니다.
그다음은 세 줄입니다 — import kis_auth as ka → ka.auth() → ka.getTREnv().
실전은 svr="prod", 모의투자는 svr="vps"이며
계좌번호는 앞 8자리(my_acct_stock)와 뒤 2자리(my_prod)를 나눠 적습니다.
1. 저장소에는 무엇이 들어 있나
KIS Developers에서 앱키를 받은 다음 대부분 “그래서 코드는 어디서 구하나”에서 멈춥니다. 한국투자증권은 공식 예제를 깃허브에 공개해 두었습니다. 2026-08-22 기준 루트 구성은 이렇습니다.
koreainvestment/open-trading-api
├── kis_devlp.yaml ← 개인 설정 (앱키·계좌·도메인)
├── examples_user/ ← 분야별 통합 예제 (실매매용)
├── examples_llm/ ← API 1개 = 폴더 1개 (기능 확인용)
├── strategy_builder/ ← 전략 작성
├── backtester/ ← 백테스트
├── MCP/
├── stocks_info/
├── legacy/ ← 구버전 보관
├── docs/
├── llms.txt
├── requirements.txt
└── pyproject.toml ← uv 기반 의존성
눈여겨볼 것은 예제가 두 벌이라는 점입니다. 목적이 다릅니다.
| 구분 | examples_user | examples_llm |
|---|---|---|
| 묶는 기준 | 분야별 — domestic_stock, overseas_stock, domestic_bond, domestic_futureoption, overseas_futureoption, elw, etfetn |
API 1개당 폴더 1개 |
| 파일 구성 | domestic_stock_functions.pydomestic_stock_examples.py..._functions_ws.py(웹소켓)..._examples_ws.py |
[기능].py + chk_[기능].py |
| 언제 쓰나 | 실제 봇을 만들 때. 함수만 import해 쓰면 된다 |
“이 API가 뭘 돌려주지?” 한 개만 찍어 볼 때 |
처음이면 examples_llm으로 하나만 찍어 보고, 봇을 만들 때 examples_user로 넘어가십시오.
두 디렉터리 각각에 kis_auth.py가 따로 있습니다.
한쪽에서 인증이 됐다고 다른 쪽이 자동으로 되는 게 아니라, 실행하는 디렉터리 기준으로 import됩니다.
경로 문제로 헤매는 분들이 여기서 많이 막힙니다.
2. kis_devlp.yaml — 이 파일이 전부다
저장소 루트의 kis_devlp.yaml 실제 내용입니다(값은 채우기 전 상태).
#실전투자
my_app: "앱키"
my_sec: "앱키 시크릿"
#모의투자
paper_app: "모의투자 앱키"
paper_sec: "모의투자 앱키 시크릿"
# HTS ID
my_htsid: "사용자 HTS ID"
#계좌번호 앞 8자리
my_acct_stock: "증권계좌 8자리"
my_acct_future: "선물옵션계좌 8자리"
my_paper_stock: "모의투자 증권계좌 8자리"
my_paper_future: "모의투자 선물옵션계좌 8자리"
#계좌번호 뒤 2자리
my_prod: "01" # 종합계좌
# my_prod: "03" # 국내선물옵션계좌
# my_prod: "08" # 해외선물옵션 계좌
# my_prod: "22" # 개인연금
# my_prod: "29" # 퇴직연금
#domain infos
prod: "https://openapi.koreainvestment.com:9443" # 서비스
ops: "ws://ops.koreainvestment.com:21000" # 웹소켓
vps: "https://openapivts.koreainvestment.com:29443" # 모의투자 서비스
vops: "ws://ops.koreainvestment.com:31000" # 모의투자 웹소켓
my_token: ""
my_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
여기서 실무상 반드시 짚어야 할 네 가지가 있습니다.
① 계좌번호는 8자리 + 2자리로 쪼갠다
HTS에서 보던 10자리를 통째로 넣으면 안 됩니다.
앞 8자리는 my_acct_stock, 뒤 2자리는 my_prod입니다.
API 요청에서는 각각 CANO와 ACNT_PRDT_CD로 들어갑니다
(자세한 건 KIS 계좌번호 CANO·ACNT_PRDT_CD 정리).
② 앱키는 실전·모의가 서로 다르다
my_app/my_sec은 실전, paper_app/paper_sec은 모의투자용입니다.
같은 키를 양쪽에 넣으면 인증이 실패합니다.
발급 절차 자체는 KIS API 발급부터 첫 주문까지 30분 가이드에 화면 기준으로 정리해 두었습니다.
③ my_htsid를 비워 두면 실시간 시세가 끊긴다
REST 조회만 할 때는 티가 안 나다가, WebSocket 실시간 시세에서 문제가 드러납니다.
저장소 안내에 따르면 No close frame received 오류가 날 때
가장 먼저 볼 곳이 kis_devlp.yaml의 HTS ID입니다.
실시간 체결가 구독 구조는 KIS WebSocket 실시간 시세에 있습니다.
④ 도메인 4개가 이미 들어 있다
실전 openapi.koreainvestment.com:9443, 모의 openapivts.koreainvestment.com:29443,
그리고 웹소켓 ops·vops가 설정에 상수로 들어 있습니다.
직접 짜는 코드에서도 도메인을 소스에 박지 말고 이렇게 설정으로 빼 두는 편이 안전합니다.
3. 파일을 어디에 둬야 하는가 — 가장 많이 막히는 곳
저장소 폴더에 그대로 두면 안 됩니다.
인증 모듈 examples_user/kis_auth.py는 설정 파일을 홈 디렉터리에서 찾습니다.
코드에 이렇게 박혀 있습니다.
# examples_user/kis_auth.py
config_root = os.path.join(os.path.expanduser("~"), "KIS", "config")
token_tmp = os.path.join(
config_root, f"KIS{datetime.today().strftime('%Y%m%d')}"
)
with open(os.path.join(config_root, "kis_devlp.yaml"), encoding="UTF-8") as f:
...
즉 실제로 읽는 경로는 다음과 같습니다.
| OS | 설정 파일이 있어야 하는 위치 |
|---|---|
| Windows | C:\Users\<계정>\KIS\config\kis_devlp.yaml |
| macOS · Linux | ~/KIS/config/kis_devlp.yaml |
# Windows (PowerShell)
mkdir "$HOME\KIS\config" -Force
copy .\kis_devlp.yaml "$HOME\KIS\config\"
# macOS / Linux
mkdir -p ~/KIS/config && cp kis_devlp.yaml ~/KIS/config/
이건 단순한 경로 문제가 아니라 보안 설계입니다.
설정 파일을 저장소 안에 두고 앱키를 채우면,
나중에 그 폴더를 깃허브에 올리는 순간 앱키와 앱시크릿이 그대로 공개됩니다.
홈 폴더로 분리하면 실수해도 저장소에 딸려 가지 않습니다.
키가 노출됐다면 즉시 KIS Developers에서 재발급하십시오.
알고랩은 어떤 경우에도 고객의 appkey·appsecret 값을 요구하지 않습니다.
4. 첫 실행 — 실제로는 세 줄
설정만 제자리에 있으면 인증은 짧습니다. Python은 3.11 이상이 필요합니다.
git clone https://github.com/koreainvestment/open-trading-api
cd open-trading-api
uv sync # 또는: pip install -r requirements.txt
import kis_auth as ka
ka.auth(svr="prod", product="01") # 실전. 모의투자는 svr="vps"
trenv = ka.getTREnv()
print(trenv.my_acct) # 계좌 앞 8자리
print(trenv.my_prod) # 계좌 뒤 2자리
그다음 분야별 함수 파일을 import해서 부르면 됩니다.
examples_user/domestic_stock에는
domestic_stock_functions.py와 domestic_stock_examples.py,
웹소켓용 domestic_stock_functions_ws.py·domestic_stock_examples_ws.py가 들어 있습니다.
import kis_auth as ka
from domestic_stock_functions import *
ka.auth()
result = inquire_price(env_dv="real", fid_input_iscd="005930")
print(result)
여기까지 오면 “API가 되는지”는 끝난 것입니다. 이 뒤로는 주문·잔고·체결 조회를 붙이는 일이고, 주문 시 hashkey가 필수인가처럼 TR 하나하나의 문제로 넘어갑니다.
5. 토큰은 어디에 저장되나
auth()는 무턱대고 토큰을 새로 받지 않습니다.
저장된 토큰이 있으면 그것부터 씁니다.
저장 위치는 앞서 본 token_tmp, 즉 ~/KIS/config/KIS20260822처럼
날짜가 붙은 파일입니다.
재인증 함수도 조건부입니다. 마지막 인증 시각으로부터
86400초(= 1일)가 지났을 때만 다시 발급합니다.
def reAuth(svr="prod", product=_cfg["my_prod"]):
n2 = datetime.now()
if (n2 - _last_auth_time).seconds >= 86400: # 유효시간 1일
auth(svr, product)
여기를 “매번 새로 받게” 고치는 것이 흔한 사고입니다. 토큰 발급은 1분에 한 번으로 제한됩니다. 개발 중 프로그램을 자주 껐다 켜면서 실행할 때마다 발급을 강제하면 발급 자체가 막혀 아무것도 못 하게 됩니다. 저장된 토큰을 먼저 읽는 기본 동작을 그대로 두십시오. 만료·갱신 처리는 KIS 접근토큰 만료·재발급에 정리해 두었습니다.
6. 실전과 모의는 대기 시간부터 다르다
svr 값 하나로 앱키·도메인이 갈리는 것은 앞에서 봤습니다.
그런데 공식 코드에는 대부분 모르는 차이가 하나 더 들어 있습니다.
호출 사이 대기 시간을 실전과 모의에 다르게 잡아 둡니다.
# kis_auth.py — changeTREnv() 내부
if svr == "prod": # 실전투자
_smartSleep = 0.05 # 초당 20회 수준
elif svr == "vps": # 모의투자
_smartSleep = 0.5 # 초당 2회 수준
모의투자 쪽이 10배 깁니다.
이게 왜 중요하냐면, 모의에서 잘 돌던 반복 조회 루프가 실전에서 그대로 통한다고 착각하게 만들기 때문입니다.
반대로 모의에서 초당 호출 제한(EGW00201)을 만나면
코드가 잘못된 게 아니라 모의 환경이 원래 더 좁은 것일 수 있습니다.
| 항목 | svr="prod" (실전) | svr="vps" (모의) |
|---|---|---|
| 앱키 필드 | my_app / my_sec | paper_app / paper_sec |
| REST 도메인 | openapi...:9443 | openapivts...:29443 |
| 웹소켓 | ops...:21000 | vops...:31000 |
| 호출 간 대기 | 0.05초 | 0.5초 |
| 계좌 | my_acct_stock | my_paper_stock |
실전 전환 시 실제로 무엇이 바뀌는지는 KIS 모의투자에서 실전으로 넘어갈 때에 별도로 정리해 두었습니다. 모의투자를 지원하지 않는 API가 있다는 점도 함께 확인하십시오.
7. 처음 돌릴 때 걸리는 5가지
| 증상 | 실제 원인 | 조치 |
|---|---|---|
| 설정 파일을 못 찾는다 | kis_devlp.yaml이 저장소 안에 있다 |
~/KIS/config/로 복사 |
EGW00201 |
초당 호출 제한 초과. 모의는 한도가 더 좁다 | 호출 간 간격 확보 · 에러코드 정리 |
| 토큰 발급이 막힌다 | 재시작마다 강제 발급 (1분 1회 제한) | 저장 토큰 재사용 동작 복원 |
웹소켓 No close frame received |
my_htsid가 비었거나 틀림 |
HTS ID 확인 후 재시도 |
| 계좌 관련 오류 | 10자리 계좌번호를 통으로 입력 | 8자리 + 2자리로 분리 |
다섯 중 넷이 “코드 문제가 아니라 설정 문제”입니다.
예제가 안 돌아간다고 코드를 뜯어고치기 전에
~/KIS/config/kis_devlp.yaml부터 확인하는 편이 훨씬 빠릅니다.
키움 쪽과 비교해 어느 증권사가 맞는지 고민 중이라면
키움 vs KIS API 비교를 먼저 보시면 됩니다.
자주 묻는 질문
공식 파이썬 예제는 어디에 있나요?
깃허브 koreainvestment/open-trading-api입니다.
실매매용 examples_user와 기능 확인용 examples_llm이 나뉘어 있고,
2026-08 기준으로 strategy_builder·backtester·MCP·llms.txt도 함께 들어 있습니다.
설정 파일을 못 찾는다고 나옵니다.
kis_devlp.yaml을 저장소에 그대로 뒀기 때문입니다.
kis_auth.py의 config_root가 홈 폴더의 KIS/config로 지정돼 있으므로
그 경로로 복사한 뒤 값을 채우십시오. 앱키 유출 위험도 함께 줄어듭니다.
실전과 모의투자는 어떻게 전환하나요?
ka.auth(svr="prod") ↔ ka.auth(svr="vps")입니다.
앱키·REST 도메인·웹소켓 주소가 함께 바뀌고, 호출 간 대기 시간도 0.05초 대 0.5초로 다릅니다.
모의투자를 지원하지 않는 API가 있다는 점도 확인하십시오.
토큰은 매번 새로 받아야 하나요?
아닙니다. 공식 코드는 ~/KIS/config/에 날짜가 붙은 파일로 토큰을 저장해 재사용하고,
reAuth()는 86400초가 지났을 때만 재발급합니다.
발급은 1분 1회 제한이므로 재시작마다 강제 발급하도록 고치지 마십시오.
이 내용을 그대로 믿어도 되나요?
이 글의 디렉터리 구조·설정 필드·함수 동작은
2026-08-22 시점 koreainvestment/open-trading-api 저장소의 main 브랜치
(README.md, kis_devlp.yaml, examples_user/kis_auth.py)를 직접 확인한 것입니다.
저장소와 API 명세는 예고 없이 바뀌므로 실제 작업 시점의 저장소와 KIS Developers 개발자 포털 명세로 대조하십시오.
이 글은 개발 실무 안내이며 투자 권유나 수익 보장이 아닙니다.