Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Kiwoom Client

БесплатноНе проверен

키움증권 REST API 파이썬 라이브러리 — 국내주식 엔드포인트 전수·실시간 WebSocket, sync+async, 토큰 자동 갱신. MCP 서버로 Claude Code 등에서 직접 호출 가능. OpenAPI+ OCX 없이 Linux·macOS 에서 동작 · Python wrappe

GitHubEmbed

Описание

키움증권 REST API 파이썬 라이브러리 — 국내주식 엔드포인트 전수·실시간 WebSocket, sync+async, 토큰 자동 갱신. MCP 서버로 Claude Code 등에서 직접 호출 가능. OpenAPI+ OCX 없이 Linux·macOS 에서 동작 · Python wrapper for Kiwoom Securities REST API — pip install kiwoom-client

README

한국어 | English

kiwoom-client — 키움증권 REST API Python 라이브러리

PyPI version Downloads Total Downloads CI License: MIT Python LinkedIn

kiwoom-client 누적 PyPI 다운로드 추이

키움증권 OpenAPI를 대체하는 Python REST API 래퍼. COM/OCX 없이 Windows · macOS · Linux 어디서나 국내주식 자동매매 · 시세조회 · 실시간 WebSocket을 사용할 수 있습니다. 토큰 자동 갱신으로 봇이 만료에 죽지 않고, sync / async 양쪽을 지원합니다. 182개 REST 엔드포인트 · 조건검색 4종 · 19종 실시간 데이터 · 모의투자/실전투자 지원. MCP(Model Context Protocol) 서버로도 제공되어, Claude Code · Cursor 등 AI 에이전트가 도구 호출로 직접 시세·계좌·주문 API를 씁니다.

pip install kiwoom-client

실제로 돌아가는 곳quant-airflow의 일일 수집 DAG 가 이 라이브러리로 시세·수급·신용·공매도를 매일 TimescaleDB 에 적재합니다. 같은 스택의 나머지는 README 하단에 있습니다.

목차

왜 이 라이브러리인가?

  • 크로스 플랫폼: REST API 기반이라 Windows, macOS, Linux 어디서나 동작합니다. COM/OCX 방식과 달리 서버 환경에서도 사용 가능합니다.
  • 자동 토큰 관리: 토큰을 알아서 발급하고, 만료 전에 갱신하고, 401이 나면 재발급 후 재시도합니다. 장시간 도는 봇이 토큰 만료로 죽지 않습니다.
  • sync / async 양쪽 지원: KiwoomAPIAsyncKiwoomAPI가 같은 API를 제공합니다.
  • 자동 페이지네이션: request_all()로 연속조회를 한 줄에 처리합니다.
  • 내장 Rate Limiter: TR(api_id)별 토큰 버킷으로 호출 제한을 자동 관리합니다.
  • 바로 쓰는 응답: to_dataframe()"+70000" 같은 문자열을 숫자로 바꿔 DataFrame으로 넘겨줍니다.
  • 완전한 커버리지: 국내주식 182개 REST 엔드포인트 + 조건검색 4종 + 19종 실시간 WebSocket 데이터를 지원합니다.
  • MCP 서버 내장: Claude Code, Cursor 등 Model Context Protocol 클라이언트에서 별도 코드 없이 이 라이브러리의 도구를 바로 호출할 수 있습니다. (자세히)

기존 키움 OpenAPI / pykiwoom 과 무엇이 다른가?

기존 키움 **OpenAPI+(OCX/COM)**나 이를 감싼 pykiwoom은 32bit Windows에 묶여 있어 서버 배포·자동화가 어렵습니다. 이 라이브러리는 키움의 신규 REST API를 사용하므로 그 제약이 없습니다.

항목 키움 OpenAPI+ (OCX) pykiwoom kiwoom-client
연동 방식 COM/OCX OCX 래퍼 REST + WebSocket
운영체제 Windows 전용 Windows 전용 Windows · macOS · Linux
Python 비트수 32bit 전용 32bit 전용 64bit 지원
서버/헤드리스 배포 어려움 (GUI 필요) 어려움 가능
실시간 데이터 이벤트 콜백 이벤트 콜백 async WebSocket
설치 별도 모듈 설치 OCX + 모듈 pip install 한 줄

이미 OCX 기반 코드를 쓰고 있다면, REST 방식으로 전환할 때 GUI 의존성과 32bit 제약을 한 번에 제거할 수 있습니다.

설치

pip install kiwoom-client

pandas 변환(to_dataframe())까지 함께 쓰려면:

pip install 'kiwoom-client[pandas]'

또는 uv 사용:

uv add kiwoom-client

소스에서 설치:

git clone https://github.com/younghwan91/kiwoom-client.git
cd kiwoom-client
pip install -e .
# 또는
uv pip install -e .

사전 준비

  1. 키움 REST API 포털에 가입합니다.
  2. API 사용신청을 통해 앱키(appkey)시크릿키(secretkey)를 발급받습니다.
  3. 환경변수 설정은 .env.example을 참고하세요.
  4. 처음에는 모의투자(is_mock=True)로 테스트한 뒤, 실전투자로 전환하세요.

빠른 시작

1단계: 연결

from kiwoom_client import KiwoomAPI

# 모의투자 서버로 연결
api = KiwoomAPI(
    app_key="발급받은_앱키",
    app_secret="발급받은_시크릿키",
    is_mock=True,  # True=모의투자, False=실전투자
)

접근토큰은 첫 호출에서 자동 발급되고 만료 전에 갱신되므로 따로 할 일이 없습니다. 키가 올바른지 즉시 확인하고 싶다면 api.login()을 호출하세요 (선택).

2단계: 종목 조회

# 삼성전자(005930) 기본 정보 조회
info = api.stock_info.basic_stock_info(stk_cd="005930")
print(info)

# 삼성전자 일봉 차트 조회
chart = api.chart.stock_daily_chart(stk_cd="005930", base_dt="20260326")

# 당일 거래량 상위 종목 조회 (파라미터 6개가 모두 필수입니다)
ranking = api.ranking.top_volume_today(
    mrkt_tp="0", stk_cnd="0", trde_qty_tp="0",
    prc_tp="0", trde_amt_tp="0", updn_tp="0",
)

3단계: 계좌 조회

# 내 계좌 평가 현황
evaluation = api.account.account_evaluation()

# 예수금 상세 조회
deposit = api.account.deposit_detail()

# 체결 잔고 조회
position = api.account.filled_position()

# 미체결 주문 조회
unfilled = api.account.unfilled_orders()

4단계: 주문

# 삼성전자 10주 지정가 매수
result = api.order.buy_order(
    dmst_stex_tp="01",   # 거래소 구분 (01: KRX)
    stk_cd="005930",     # 종목코드
    ord_qty=10,          # 주문 수량
    trde_tp="00",        # 주문 유형 (00: 지정가)
    ord_uv=70000,        # 주문 단가
)

# 매도 주문
api.order.sell_order(
    dmst_stex_tp="01",
    stk_cd="005930",
    ord_qty=10,
    trde_tp="00",
    ord_uv=75000,
)

# 주문 정정
api.order.modify_order(org_ord_no="원래주문번호", ord_qty=5, ord_uv=71000)

# 주문 취소
api.order.cancel_order(org_ord_no="원래주문번호", ord_qty=5)

5단계: 정리

api.logout()  # 토큰 폐기 (선택)
api.close()   # 연결 종료

# with 문을 쓰면 close()는 자동입니다
with KiwoomAPI(app_key="앱키", app_secret="시크릿키", is_mock=True) as api:
    info = api.stock_info.basic_stock_info(stk_cd="005930")

asyncio 사용법

AsyncKiwoomAPIKiwoomAPI와 같은 엔드포인트를 제공하며, 호출 앞에 await만 붙이면 됩니다.

import asyncio
from kiwoom_client import AsyncKiwoomAPI

async def main():
    async with AsyncKiwoomAPI(app_key="앱키", app_secret="시크릿키", is_mock=True) as api:
        # 서로 다른 TR은 동시에 나간다 — 직렬로 돌리면 3배 걸린다
        info, chart, ranking = await asyncio.gather(
            api.stock_info.basic_stock_info(stk_cd="005930"),
            api.chart.stock_daily_chart(stk_cd="005930", base_dt="20260326"),
            api.ranking.top_volume_today(
                mrkt_tp="0", stk_cnd="0", trde_qty_tp="0",
                prc_tp="0", trde_amt_tp="0", updn_tp="0",
            ),
        )
        print(info["stk_nm"])

asyncio.run(main())

Rate Limiter는 TR(api_id)별로 걸립니다. 서로 다른 TR은 서로를 막지 않고 동시에 나가며, 같은 TR을 반복 호출할 때만 초당 1건으로 조여집니다. 전체 예제는 examples/async_usage.py를 참고하세요.

응답을 숫자·DataFrame으로 받기

키움은 모든 값을 문자열로 돌려줍니다. 가격은 "+70000", 등락률은 "-1.23", 거래량은 "1,234,567" 같은 식이라 그대로는 계산에 쓸 수 없습니다.

from kiwoom_client import to_dataframe, to_number, normalize

result = api.ranking.top_volume_today(...)

# 페이로드 키를 자동으로 찾아 DataFrame으로 변환 (문자열 → 숫자 포함)
df = to_dataframe(result)
print(df["cur_prc"].mean())   # 바로 계산 가능

# dict 그대로 쓰고 싶다면
data = normalize(result)
price = to_number("+70000")   # 70000

종목코드("005930")처럼 앞자리 0이 의미를 갖는 값과, base_dt 같은 날짜·식별자 필드는 숫자로 바꾸지 않고 문자열로 남깁니다.

to_dataframe() 실행 결과 — 문자열 응답이 계산 가능한 DataFrame 이 된다

샘플 응답을 to_dataframe() 에 넣은 실제 출력입니다. 시세 값 자체는 예시입니다 — stk_cd 는 문자열로 남고 가격·거래량만 숫자가 되는 것을 보세요.

to_dataframe()에는 pandas가 필요합니다:

pip install 'kiwoom-client[pandas]'

실시간 WebSocket 데이터

실시간 체결가, 호가, 잔고 변동 등을 WebSocket으로 수신할 수 있습니다.

import asyncio
from kiwoom_client import KiwoomAPI

api = KiwoomAPI(app_key="앱키", app_secret="시크릿키")
ws = api.create_websocket()

async def main():
    # connect()가 LOGIN 핸드셰이크까지 끝냅니다. 실패하면 KiwoomWebSocketError
    await ws.connect()

    # 콜백은 REAL 프레임의 항목 하나를 받습니다:
    # {"type": "0B", "item": "005930", "values": {"10": "+70000", ...}}
    ws.on("0B", lambda d: print(f"체결 {d['item']}: {d['values'].get('10')}"))
    ws.on("0D", lambda d: print(f"호가 {d['item']}: {d['values'].get('41')}"))

    # async 콜백도 그대로 등록할 수 있습니다
    async def save(d): ...
    ws.on("0B", save)

    # 삼성전자 실시간 체결+호가 구독
    await ws.subscribe("0B", "005930")
    await ws.subscribe(["0B", "0D"], ["005930", "000660", "035420"])

    # PING 응답과 재연결(재로그인·구독 복원)은 listen()이 알아서 처리합니다
    await ws.listen()

asyncio.run(main())

values의 키는 키움 FID 번호입니다(10=현재가, 13=누적거래량, 41=매도최우선호가).

조건검색

조건검색도 같은 WebSocket을 씁니다. api.condition_search가 요청 페이로드를 만들고, ws.send()로 보낸 뒤 ws.on_trnm()으로 응답을 받습니다.

await ws.connect()
ws.on_trnm("CNSRLST", lambda d: print("조건식 목록:", d["data"]))
ws.on_trnm("CNSRREQ", lambda d: print("검색 결과:", d.get("data")))

# 조건식 목록을 먼저 조회해야 seq를 알 수 있습니다
await ws.send(api.condition_search.condition_list())

# seq로 검색 (search_type="1"이면 실시간 편입/이탈까지 수신)
await ws.send(api.condition_search.condition_search_realtime(seq="1"))
await ws.listen()

검증 상태: 실서버(api.kiwoom.com) 대상으로 LOGIN 핸드셰이크 · PING 프레임 · REG 등록 응답까지 확인했습니다. 다만 REAL 프레임의 항목 필드명(item/values)은 장 마감 중이라 아직 미확정입니다. 장중 이상 동작을 만나면 이슈로 알려주세요. 직접 확인하려면 python tests/integration_ws_smoke.py --prod 를 돌리면 됩니다.

연속 조회 (페이지네이션)

데이터가 많은 API는 한 번에 모든 데이터를 반환하지 않습니다. 응답 헤더의 cont_yn"Y"이면 다음 페이지가 있다는 뜻입니다.

# 방법 1: 수동 연속 조회
result = api.account.filled_orders()
# result에 cont_yn="Y"와 next_key가 있으면 다음 페이지 조회
next_result = api.account.filled_orders(cont_yn="Y", next_key=result["next_key"])

# 방법 2: 자동 전체 조회 (모든 페이지를 한번에)
from kiwoom_client.base import BaseClient
all_data = api._client.request_all(
    "/api/dostk/acnt", "ka10076",
    data_key="filled_list",  # 응답에서 리스트 데이터의 키 이름
)

에러 처리

from kiwoom_client.base import KiwoomAPIError

try:
    result = api.order.buy_order(stk_cd="005930", ord_qty=10, ord_uv=70000)
except KiwoomAPIError as e:
    print(f"에러 코드: {e.code}")
    print(f"에러 메시지: {e.message}")
    print(f"전체 응답: {e.response}")

요청 제한 (Rate Limit)

키움 REST API는 TR(api_id)별로 독립적인 호출 제한을 둡니다. 실측 결과는 다음과 같습니다.

항목 측정값
지속(sustained) 안전 속도 TR당 약 1 req/s (이 속도에선 거부 0)
순간 버스트(burst) 허용량 TR당 약 2건
초과 시 응답 HTTP 429 + {"return_code": 5, "return_msg": "허용된 요청 개수를 초과하였습니다"}
제한 단위 TR(api_id)별 독립 — 서로 다른 TR은 영향 없음

이에 맞춰 라이브러리는 기본적으로 TR별 토큰 버킷 Rate Limiter(1 req/s, 버스트 2) 를 적용하고, 그래도 429가 발생하면 자동으로 백오프 후 재시도합니다. 별도 설정 없이도 안전하게 동작합니다.

# 기본값: TR당 1 req/s, 버스트 2, 429 자동 재시도
api = KiwoomAPI(app_key="...", app_secret="...")

# 직접 조정 (예: TR당 2 req/s, 버스트 3, 재시도 5회)
api = KiwoomAPI(app_key="...", app_secret="...",
                rate_limit=2.0, rate_burst=3, max_retries=5)

# 클라이언트 측 스로틀 비활성화 (직접 제어할 때)
api = KiwoomAPI(app_key="...", app_secret="...", rate_limit=None)

제한이 TR별이라, 서로 다른 TR을 섞어 호출하면 합산 처리량은 더 높습니다. 반대로 같은 TR을 반복(연속조회 루프 등)할 때는 1 req/s에 수렴합니다 — 이 경우 request_all()을 쓰면 페이지네이션을 안전하게 자동 처리합니다.

아키텍처

KiwoomAPI(sync) / AsyncKiwoomAPI(async)는 같은 구조를 공유하는 파사드입니다. 15개 엔드포인트 모듈은 ModuleRegistry가 지연 생성하고, 실제 HTTP 호출·인증·재시도는 BaseClient/AsyncBaseClient 한 곳에 모여 있습니다. 실시간 데이터는 REST와 별도로 KiwoomWebSocket이 같은 토큰을 재사용해 처리합니다.

flowchart LR
    User["사용자 코드"] --> API["KiwoomAPI / AsyncKiwoomAPI\n(ModuleRegistry 파사드)"]

    API --> Modules["15개 엔드포인트 모듈\naccount · stock_info · market · chart\norder · credit_order · ranking · sector\nforeign_institution · short_selling · slb\ntheme · condition_search · elw · etf"]

    Modules --> Client["BaseClient / AsyncBaseClient\n(request / request_all)"]

    Client --> Auth["KiwoomAuth\n(토큰 발급 · 만료전 갱신 · 401 재발급)"]
    Client --> RateLimiter["PerKeyRateLimiter\n(TR별 토큰 버킷, 429 자동 재시도)"]
    Client --> Parsing["parsing\n(to_number / to_dataframe)"]

    Auth -->|"POST /oauth2/token"| REST["키움 REST API\napi.kiwoom.com / mockapi.kiwoom.com"]
    Client -->|"POST /api/dostk/..."| REST

    API --> WS["KiwoomWebSocket"]
    Auth -->|"access_token 재사용"| WS
    WS <-->|"REG/REMOVE/REAL, 조건검색"| WSS["키움 실시간 WebSocket\nwss://.../api/dostk/websocket"]

환경 설정

구분 실전투자 모의투자
is_mock False (기본값) True
REST URL https://api.kiwoom.com https://mockapi.kiwoom.com
WebSocket URL wss://api.kiwoom.com:10000 wss://mockapi.kiwoom.com:10000

MCP 서버로 사용하기

Claude Code, Cursor 등 MCP(Model Context Protocol)를 지원하는 도구에서 이 라이브러리를 직접 호출할 수 있습니다. 15개 도메인 모듈의 REST 엔드포인트 전부와 조건검색(condition_search) 4종이 MCP 도구로 노출됩니다.

pip install 'kiwoom-client[mcp]'

MCP 클라이언트 설정(예: Claude Code .mcp.json)에 추가:

{
  "mcpServers": {
    "kiwoom-client": {
      "command": "kiwoom-client-mcp",
      "env": {
        "KIWOOM_APP_KEY": "발급받은_앱키",
        "KIWOOM_APP_SECRET": "발급받은_시크릿키",
        "KIWOOM_IS_MOCK": "true"
      }
    }
  }
}
환경변수 설명 기본값
KIWOOM_APP_KEY 앱키 (필수)
KIWOOM_APP_SECRET 시크릿키 (필수)
KIWOOM_IS_MOCK 모의투자 서버 사용 여부 false
KIWOOM_MCP_ALLOW_LIVE_ORDERS 실전투자 계좌에서 주문 도구(매수/매도/정정/취소·신용주문)를 노출할지 여부 false

실주문 가드: KIWOOM_IS_MOCK=false(실전투자)이고 KIWOOM_MCP_ALLOW_LIVE_ORDERStrue가 아니면, 주문 관련 도구는 서버 시작 시점에 아예 등록되지 않습니다 — MCP 클라이언트(AI 에이전트)가 그 도구의 존재 자체를 모릅니다. 모의투자(KIWOOM_IS_MOCK=true)는 이 가드 없이 항상 사용 가능합니다. 이 가드는 MCP 서버 경로에만 적용되며, 파이썬 코드에서 KiwoomAPI/AsyncKiwoomAPI를 직접 쓰는 기존 방식에는 영향이 없습니다.

조회성 도구는 {"params": {...}} 형태로 TR 요청 필드를 그대로 전달합니다(필드 목록은 키움 REST API 가이드 참고). 예: stock_info_basic_stock_info 도구에 {"params": {"stk_cd": "005930"}}.

지원 API 목록

인증

api.login()      # 접근토큰 발급 (선택 — 첫 호출에서 자동 발급됩니다)
api.logout()     # 접근토큰 폐기

모듈별 커버리지 (182개 REST 엔드포인트)

모듈 개수 설명
api.account 33 계좌 — 예수금·잔고·손익·증거금·주문내역
api.stock_info 31 종목정보 — 기본정보·거래원·신용동향·업종코드
api.market 25 시세 — 호가·기관/외국인 매매·프로그램매매
api.ranking 23 순위정보 — 거래량·등락률·신용비율·외국인 상위
api.chart 21 차트 — 틱·분·일·주·월·년봉 (종목·업종·금현물)
api.elw 11 ELW — 민감도지표·괴리율·조건검색
api.etf 9 ETF — 수익율·시세·시간대별 체결
api.order 8 주문 — 매수·매도·정정·취소 (금현물 포함)
api.sector 6 업종 — 현재가·지수·투자자 순매수
api.credit_order 4 신용주문 — 매수·매도·정정·취소
api.foreign_institution 4 기관/외국인 매매 동향
api.slb 4 대차거래 — 추이·상위종목
api.condition_search 4 조건검색 (WebSocket, trnm 기반)
api.theme 2 테마 — 그룹·구성종목
api.short_selling 1 공매도 추이
api.create_websocket() 19종 실시간 시세 — 체결·호가·잔고·VI 등

메서드 이름과 파라미터 전체 목록은 src/kiwoom_client/domestic/ 소스나 IDE 자동완성으로 확인할 수 있습니다. API ID(ka10001 등)는 키움 공식 가이드의 TR 코드와 동일합니다.

참고

라이선스

MIT


⭐ 도움이 되셨다면

이 라이브러리가 유용했다면 우측 상단 ⭐ Star 를 눌러주세요. 검색·추천 노출이 올라가 더 많은 개발자가 찾을 수 있습니다.

  • 🐛 버그·질문 → Issues
  • 🔧 개선 → PR 환영 (CONTRIBUTING)
  • 📈 새 엔드포인트·기능 업데이트 소식을 받으려면 팔로우

관련 프로젝트 — 오픈소스 퀀트 스택

한국·미국 주식과 암호화폐를 아우르는 오픈소스 스택입니다. 각 저장소는 독립적으로 쓸 수 있습니다.

프로젝트 설명
🇰🇷 한국 주식 krx-fundamentals-client 국내 기업 펀더멘탈 Python 클라이언트 라이브러리 — 재무제표·투자지표·배당·종목 스크리닝 (DART + KRX + 네이버)
🇰🇷 한국 주식 krx-news-client 한국 주식 뉴스·공시 수집 Python 클라이언트 라이브러리 (DART + 한국경제 + 더벨 + 토스)
🇰🇷 한국 주식 fin-checkup 관심종목 위험 공시 텔레그램 알림 + DART·SEC 재무 건강검진 — 측정값과 사실만 전달한다
🇰🇷 한국 주식 quant-airflow 시세·수급·실적을 TimescaleDB 로 수집하는 Airflow 파이프라인 — 상장폐지 종목까지 담아 생존편향을 막는다
🇰🇷 한국 주식 kr-quant 코스피·코스닥 알파 리서치 — walk-forward·랜덤 음성대조·purged CV·Deflated Sharpe 를 CI 가드레일로 강제
🇺🇸 미국 주식 portfolio-research 미국주식 팩터 엔진 — point-in-time·생존편향 보정 데이터 위에서 walk-forward 를 Deflated Sharpe·PBO 로 게이팅 (+ ETF 전술배분 TAA — 9개 사전등록, 채택 0)
🇺🇸 미국 주식 automated-stock-trading-systems Bensdorp 의 7개 비상관 트레이딩 시스템 백테스터 (교육용 재구현)
₿ 암호화폐 quantbox-engine 암호화폐 선물 백테스트·실행 엔진 — 룩어헤드 0, 백테스트↔실거래 일체화

만든 사람

채영환 (Younghwan Chae) · GitHub @younghwan91 · LinkedIn

전체 오픈소스 퀀트 스택은 프로필에서 한눈에 볼 수 있습니다.

from github.com/younghwan91/kiwoom-client

Установка Kiwoom Client

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/younghwan91/kiwoom-client

FAQ

Kiwoom Client MCP бесплатный?

Да, Kiwoom Client MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Kiwoom Client?

Нет, Kiwoom Client работает без API-ключей и переменных окружения.

Kiwoom Client — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Kiwoom Client в Claude Desktop, Claude Code или Cursor?

Открой Kiwoom Client на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Kiwoom Client with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development