키움 REST API 클라이언트 재구현 인수인계서¶
작성: 2026-05-15 (Cowork 세션)
수행 주체: PM 머신의 Claude Code (키움 API 네트워크 도달 가능 환경)
사유: Cowork 샌드박스는 mockapi.kiwoom.com/api.kiwoom.com이 허용목록 차단(HTTP 403 blocked-by-allowlist)이라 토큰 발급·API 호출 검증 불가. 작성은 가능하나 검증 루프를 돌릴 수 없어 머신 측으로 이관.
1. 배경¶
- 원본
scripts/kiwoom_rest_api.py풀 클라이언트(~30 메서드 + 토큰 발급)와claude_trader패키지,api_keys.txt가 이전 세션에서 소실됨. - 2026-05-13 11:12, 원본이 pykrx 기반 33줄 stub으로 덮어쓰여짐 (현재 상태). stub은
get_daily_chart/get_minute_chart만 구현. - 백업 압축본 6개 전수 확인 — 원본 클라이언트 없음. 재구현 외 경로 없음.
api_keys.txt는 PM이 프로젝트 루트에 복원 완료.
2. 목표 / 성공조건¶
키움 REST API를 실제로 호출하는 KiwoomRestAPI 클라이언트를 재구현하여 의존 스크립트 9개를 복구한다.
| 검증 항목 | 성공 기준 |
|---|---|
| 토큰 발급 | mock 서버에서 OAuth2 토큰 정상 발급 |
fetch_market_top.py 실행 |
등락률 상위/거래량 상위 정상 수집, JSON 저장 |
| 의존 스크립트 8개 | import 및 핵심 메서드 호출 스모크 테스트 통과 |
3. 자격증명¶
api_keys.txt (프로젝트 루트), 형식 — 키 이름과 값 사이 : (공백 포함) 구분:
secret : <secretkey>
api : <appkey>
: 구분자와 앞뒤 공백 strip 처리 주의.
4. 엔드포인트 / 설정¶
근거: knowledge_base/system/TOOL_REFERENCE.md §1, docs/work_logs/2026-01-16_rest_api_setup.md, _archive/config_inactive_20260512.zip > production_config.yaml.
| 항목 | 값 |
|---|---|
| mock base URL | https://mockapi.kiwoom.com |
| real base URL | https://api.kiwoom.com |
| 토큰 엔드포인트 | /oauth2/token |
| 차트 | /api/dostk/chart |
| 시세/정보 | /api/dostk/stkinfo |
| 호가/시장 | /api/dostk/mrkcond |
| 주문 | /api/dostk/ordr |
| rate limit | 데이터 요청 간 1.0s, max 5 req/s |
토큰 gotcha (TOOL_REFERENCE.md §1):
- 응답 토큰 키 = token (NOT access_token)
- 만료 키 = expires_dt (YYYYMMDDHHmmss 형식, NOT expires_in)
5. 구현 범위 — 메서드 표면¶
의존 스크립트 9개를 grep하여 확정한 실제 호출 메서드만. 원본의 ~30개 전부가 아니라 아래만 구현하면 9개 스크립트가 복구됨. (주문/계좌 메서드는 이번 범위 아님 — 호출하는 스크립트 없음.)
Foundation¶
__init__(is_mock=...)—KiwoomRestAPI(is_mock=True)와 bareKiwoomRestAPI()둘 다 호출됨.is_mock기본값 필요. 참고:docs/work_logs/2026-02-19_session148_live_mode_activation.md에 따르면 원본은is_mock을config.api.is_mock에서 읽었음 — 기본값 처리 방식 결정 필요._request(api_id, params, cont_yn='N', next_key='')— 내부 요청 헬퍼. 반환:(result_dict, next_key)튜플.result_dict에는return_code(int, 0=성공),return_msg, 그리고 API별 데이터 키가 포함됨 — 호출처는result.get("return_code") != 0로 성공 여부 판정(근거:collect_ka90010_full.py:26).collect_ka90010_full.py가api._request("ka90010", params, cont_yn, next_key)로 직접 호출하므로 public 시그니처로 노출 필요. ka90010 params 예시:{date, amt_qty_tp, mrkt_tp, min_tic_tp, stex_tp}, 데이터 키prm_trde_trnsn.
시세/시장 메서드¶
| 메서드 | API ID | 호출 시그니처 (실제 사용) | 반환 형태 | 호출처 |
|---|---|---|---|---|
get_top_change_rate |
ka10027 | (market='000', sort_type='1'\|'3', stex_tp='2') |
dict, 키 pred_pre_flu_rt_upper (list). item: stk_cd,stk_nm,flu_rt,cur_prc |
fetch_market_top, fetch_limit_up, fetch_nxt_market |
get_top_volume_today |
ka10030 | (market='000', sort_tp='3', mang_stk_incls='14', stex_tp='2', cont_yn='Y', next_key=...) |
튜플 (dict, next_key). dict 키 tdy_trde_qty_upper (list) |
fetch_market_top, fetch_nxt_market |
get_current_price |
ka10001 | (code) |
flat dict, 키 cur_prc. 장마감 후 exp_cntr_pric=0 주의. 모의투자 cur_prc=0 빈번 |
fetch_nxt_market |
get_expected_price |
(미확정) | (code) |
예상체결가. ka10001의 exp_cntr_pric 필드 래핑인지 별도 호출인지 라이브 확인 필요 |
fetch_nxt_market |
get_inst_trading_trend |
ka10045 (확정) | (code, start_date=, end_date=) |
dict, 키 stk_orgn_trde_trnsn (list). item: dt,for_daly_nettrde_qty,orgn_daly_nettrde_qty,close_pric,for_dt_acc,orgn_dt_acc. 근거: collect_stock_flow_series.py:40,45 + candidate_from_theme.py:307-308 |
candidate_from_theme, collect_stock_flow_series |
get_program_trading_daily_all |
ka90013 (확정) | (code, base_date=None, max_pages=N, delay=N) — base_date 생략 호출 있음 |
dict (bare list 아님), 키 stk_daly_prm_trde_trnsn (list). 페이지네이션 집계 래퍼. item: dt/date,prm_buy_qty,prm_sell_qty,prm_netprps_qty. 근거: collect_program_trading.py:49,51 + collect_stock_flow_series.py:64,66 |
collect_program_trading, collect_stock_flow_series |
get_daily_chart |
ka10081 | (code) |
dict, 키 stk_dt_pole_chart_qry (list). item: dt,cur_prc,open_pric,high_pric,low_pric,trde_qty. 부호 +/- prefix |
check_wait_conditions, mtf_chart_profiler, fetch_market_top(간접) |
get_minute_chart |
ka10080 (확정) | (code, minute_type='5') |
dict, 키 stk_min_pole_chart_qry (list, daily와 키 다름). item: cntr_tm,open_pric,high_pric,low_pric. 근거: mtf_chart_profiler.py:248-249 |
mtf_chart_profiler |
API ID 주의: config/data_sources.yaml 14-16줄은 top_change_rate/top_volume_today/top_volume_prev를 모두 ka10030으로 주석 달았으나, 이는 data_sources.yaml의 복붙 오류로 보임. TOOL_REFERENCE.md §1은 ka10027(등락률 상위)·ka10030(당일 거래량)으로 구분하고, 아카이브에 test_ka10027_fields.py·test_ka10030_fields.py가 별도 존재 → ka10027/ka10030은 별개 API. 위 표 기준(get_top_change_rate=ka10027) 채택. 라이브에서 최종 확인 권장.
참고: 현재 stub의 get_daily_chart/get_minute_chart는 pykrx 기반. config/data_sources.yaml fallback_rules는 daily_ohlcv의 fallback으로 FDR를 허용하므로, ka10081 재구현 + pykrx/FDR fallback 구조로 가도 됨. PM 아키텍처 방침: 정확도 우선 데이터는 키움, 과거 추세는 FDR.
6. 스펙 출처¶
knowledge_base/system/TOOL_REFERENCE.md§1 — API ID, 엔드포인트, 응답키, 토큰 gotcha, ka10063 부호 파싱(--282=-282) 등config/data_sources.yaml9-27줄 — kiwoom_rest_api 엔드포인트 매핑, fallback_rules, cross_validation_rulesdocs/work_logs/2026-01-16_rest_api_setup.md— 초기 셋업 (토큰 발급/ka10081/ka10059 연동 성공 기록)
7. 미검증 영역 (라이브에서 확인하며 채울 부분)¶
TOOL_REFERENCE.md에 없는 것 — 학습데이터로 지어내지 말고 mock 서버 에러 메시지로 확인 (원 개발자도 "파라미터명은 에러 메시지로 확인"이라 기록함, 2026-01-16_rest_api_setup.md):
- 토큰 요청 본문의 정확한 필드명 (
grant_type,appkey,secretkey/appsecret등) - API 호출 시 헤더 구성 —
authorization: Bearer {token},api-id: {ka#####},cont-yn,next-key등의 정확한 헤더명 - 각 ka#####의 정확한 요청 파라미터명 (시그니처의
market/sort_type등이 REST 파라미터로 어떻게 매핑되는지) get_expected_price의 정확한 API ID와 반환 형태 (ka10001exp_cntr_pric필드 래핑인지 별도 호출인지). —get_inst_trading_trend·get_program_trading_daily_all·get_minute_chart는 §5에서 소스로 API ID·반환키 확정됨, 미검증 영역 아님.
8. 검증 루프¶
api_keys.txt파싱 → mock 서버 토큰 발급. 실패 시 토큰 요청 본문/헤더 조정.- 메서드별 단건 호출 테스트 —
get_top_change_rate부터. 에러 메시지로 파라미터명 확정. fetch_market_top.py실행 → 등락률/거래량 상위 + JSON 저장 확인.- 나머지 8개 스크립트 import + 핵심 메서드 스모크 테스트:
candidate_from_theme.py,check_wait_conditions.py,collect_ka90010_full.py,collect_program_trading.py,collect_stock_flow_series.py,fetch_limit_up.py,fetch_nxt_market.py,mtf_chart_profiler.py - 통과 후
docs/topics/_index.md에 복원 완료 기록.
9. 제약 (CLAUDE.md 준수)¶
scripts/kiwoom_rest_api.py1개 파일만 교체. 의존 스크립트 9개는 건드리지 않음 — 메서드 시그니처를 위 §5에 맞추면 수정 불필요. 만약 시그니처 불일치가 불가피하면 PM 보고 후 진행.- 검증 없이 "동작함" 단정 금지. 각 메서드는 실제 호출 결과로만 검증.
- 미확정 부분(§7)은 추측으로 채우지 말고 에러 기반으로 확인.