키움 ka10052 거래원순간거래량 — qty_tp 3·5는 공란
ka10052(거래원순간거래량요청)는 "회원사 1곳"이 낸 순간 대량 체결을 HHmmss 시각 행으로 주는 TR입니다. 경로는 /api/dostk/stkinfo, 필수 body는 mmcm_cd·mrkt_tp·qty_tp·pric_tp·stex_tp 5개이고 종목코드 stk_cd는 선택입니다. 걸리는 곳은 네 군데입니다. 수량구분 qty_tp의 3과 5는 명세 설명이 비어 있고("3:, 5:"), 응답에 날짜가 없으며, 현재가는 "+57700"인데 전일대비는 부호 없이 "400"으로 옵니다. 응답 예시를 시간순으로 놓으면 이전 누적순매수 + 이번 순간거래량 = 이번 누적순매수가 3행 모두 정확히 맞습니다(실측). (공식 명세 kiwoom_api_spec.json·예제, main 953e5db 2026-09-15 기준, 2026-10-22 확인)
목차
- ka10052는 무엇을 주나 — 거래원 TR 지도
- 요청·응답 실물
- 함정 6가지
- 최소 호출 코드
- 자주 묻는 질문
1. ka10052는 무엇을 주나 — 거래원 TR 지도
"거래원"은 주문이 거쳐 간 증권사 창구입니다. 거래원 계열 TR은 대부분 하루·기간 합계를 주지만, ka10052는 특정 회원사 창구에서 한 번에 큰 수량이 체결된 순간을 시각·종목·수량 행으로 하나씩 돌려줍니다.
같은 회원사코드(mmcm_cd)를 받는 형제 TR과 비교하면 위치가 분명해집니다. 기간 합계는 ka10043 거래원매물대분석과 ka10078 증권사별종목매매동향, 순위는 ka10039 증권사별매매상위가 맡습니다.
| 항목 | ka10052 거래원순간거래량 | ka10043 거래원매물대분석 | ka10039 증권사별매매상위 |
|---|---|---|---|
| 경로 | /api/dostk/stkinfo | /api/dostk/stkinfo | /api/dostk/rkinfo |
| 고정하는 것 | 회원사 (종목은 선택) | 회원사 + 종목 | 회원사 |
| 시간 축 | 당일 시각 tm (HHmmss) | 일자 dt | 기간 dt |
| 필수 body | 5개 (stk_cd만 N) | 9개 전부 Y | 5개 |
예시 mmcm_cd | "888" | "36" | "001" |
| 목록 키 | trde_ori_mont_trde_qty | trde_ori_prps_anly | sec_trde_upper |
명세 전체 337개 API를 훑으면 qty_tp·mont_trde_qty(순간거래량)·acc_netprps(누적순매수)·trde_ori_nm(거래원명) 네 필드는 ka10052에만 있습니다. 장중 상위 5개 창구를 실시간으로 받고 싶다면 TR이 아니라 WebSocket 타입 0F(주식당일거래원)가 따로 있습니다(키움 실시간 WebSocket 글).
2. 요청·응답 실물
명세의 request_example 원문입니다. 공식 예제 examples/국내주식/종목정보/get_domestic_broker_instant_volume.py의 __main__도 같은 값입니다.
POST https://api.kiwoom.com/api/dostk/stkinfo
api-id: ka10052
authorization: Bearer {접근토큰}
{
"mmcm_cd": "888",
"stk_cd": "",
"mrkt_tp": "0",
"qty_tp": "0",
"pric_tp": "0",
"stex_tp": "3"
}
요청 파라미터 설명 원문입니다. qty_tp의 3과 5, stex_tp의 "3.통합"(쉼표 대신 마침표)까지 명세에 적힌 그대로 옮겼습니다.
| element | 필수 | 명세 설명 |
|---|---|---|
mmcm_cd | Y | 회원사 코드는 ka10102 조회 (길이 3) |
stk_cd | N | 거래소별 종목코드 (KRX:039490, NXT:039490_NX, SOR:039490_AL) |
mrkt_tp | Y | 0:전체, 1:코스피, 2:코스닥, 3:종목 |
qty_tp | Y | 0:전체, 1:1000주, 2:2000주, 3:, 5:, 10:10000주, 30: 30000주, 50: 50000주, 100: 100000주 |
pric_tp | Y | 0:전체, 1:1천원 미만, 8:1천원 이상, 2:1천원 ~ 2천원, 3:2천원 ~ 5천원, 4:5천원 ~ 1만원, 5:1만원 이상 |
stex_tp | Y | 1:KRX, 2:NXT 3.통합 |
응답 response_example 원문(3행 중 2행)입니다. 행은 최신 시각이 먼저(161437 → 161423 → 161417) 옵니다.
{
"trde_ori_mont_trde_qty": [
{
"tm": "161437",
"stk_cd": "005930",
"stk_nm": "삼성전자",
"trde_ori_nm": "다이와",
"tp": "-매도",
"mont_trde_qty": "-399928",
"acc_netprps": "-1073004",
"cur_prc": "+57700",
"pred_pre_sig": "2",
"pred_pre": "400",
"flu_rt": "+0.70"
},
{
"tm": "161423",
...
"mont_trde_qty": "-100000",
"acc_netprps": "-673076",
...
}
],
"return_code": 0,
"return_msg": "정상적으로 처리되었습니다"
}
| element | 한글명 | 명세 설명 |
|---|---|---|
tm | 시간 | HHmmss |
trde_ori_nm · tp | 거래원명 · 구분 | (공란) — 예시는 "다이와" · "-매도" |
mont_trde_qty | 순간거래량 | 단위: 1주 |
acc_netprps | 누적순매수 | 단위: 1주 |
cur_prc | 현재가 | 단위: 원, 부호가 포함된 숫자 |
pred_pre_sig · pred_pre | 전일대비기호 · 전일대비 | 1: 상한가, 2:상승, 3:보합, 4:하한가, 5:하락 · 단위: 원 |
flu_rt | 등락율 | 단위: %, 부호 포함 소수점 둘째 자리까지 |
가격 쪽은 앞뒤가 맞습니다. 57,700 − 400 = 57,300원이 전일 종가이고, 400 ÷ 57,300 = 0.698%라 flu_rt "+0.70"과 일치합니다(실측 계산).
3. 함정 6가지
① 수량구분 3·5의 설명이 비어 있다
qty_tp 설명에서 1·2·10·30·50·100은 "1000주"처럼 수량이 붙어 있는데 3과 5만 "3:, 5:"로 비어 있습니다. 규칙상 3000주·5000주로 읽히지만 명세에는 없습니다. 공식 예제의 docstring도 같은 문구를 그대로 복사했고 __main__은 "0"(전체)만 씁니다. "5000주 이상만 보는 봇"을 만들 계획이면 qty_tp "0"으로 받아 mont_trde_qty로 직접 거르는 편이 확실합니다. 3·5를 쓰려면 같은 시각대에 "0"과 결과를 비교해 경계를 확인하거나 키움 공식 문서로 확인하십시오.
② pric_tp 번호가 ka10030과 다르다
같은 이름의 가격구분이 ka10023(거래량급증)·ka10030(당일거래량상위)에도 있지만 번호 체계가 다릅니다. ka10052의 "2"는 "1천원 ~ 2천원"인데 ka10030의 "2"는 "1천원이상"이고, ka10052의 "8"은 "1천원 이상"인데 ka10030의 "8"은 "5만원이상"입니다. 순위 TR용 상수를 그대로 가져오면 오류 없이 전혀 다른 가격대가 걸러집니다. TR마다 상수표를 따로 두십시오.
③ 응답에 날짜가 없다
tm은 HHmmss 6자리뿐이고 요청에도 날짜 파라미터가 없습니다. 저장할 때 호출한 날짜를 직접 붙여야 합니다. 예시 시각 161437은 KRX 정규장 마감(15:30) 뒤인데, 요청이 stex_tp "3"(통합)이라 NXT 애프터마켓 체결로 보입니다. 다만 명세에 설명이 없으니 단정은 못 합니다. KRX만 원하면 stex_tp "1"로 받으십시오. 거래소 구분은 NXT·KRX 주문 라우팅 글에 정리했습니다.
④ 누적순매수는 행마다 이어진다 — 빠진 행 검사에 쓴다
예시 3행을 시간순으로 뒤집어 계산해 보면(Python 3.10.4 · pandas 2.2.3, 실측) 관계가 정확히 맞습니다.
161423: -573076 + -100000 = -673076 vs -673076
161437: -673076 + -399928 = -1073004 vs -1073004
first row acc-mont = -473076
즉 acc_netprps는 그 창구의 그 종목 당일 누적이고, 각 행은 누적이 한 번 움직인 순간입니다. 첫 행 앞에는 −473,076주가 이미 쌓여 있었다는 뜻이라, 예시는 당일의 일부 구간입니다. 연속조회 페이지 사이에서 행이 빠지면 이 등식이 깨지니 수집 검증에 그대로 쓸 수 있습니다. 단, 순간거래량 기준(qty_tp)보다 작은 체결도 누적에는 들어가는지는 명세에 없습니다. 0으로 받았을 때 맞는지부터 확인하십시오.
⑤ 부호가 필드마다 다르다
cur_prc "+57700"·flu_rt "+0.70"은 부호가 붙는데, 같은 행의 pred_pre는 상승(pred_pre_sig "2")인데도 "400"으로 부호가 없습니다. ka10043 예시가 "+1700"·"--1100"으로 오는 것과도 다릅니다. 하락일에 "-400"이 올지 "400"이 올지 예시로는 알 수 없으므로, 방향은 pred_pre_sig에서 읽고 크기만 pred_pre에서 읽는 쪽이 안전합니다. 구분 tp도 "-매도"처럼 문자열 앞에 마이너스가 붙어 오고, 매도 행은 mont_trde_qty 자체가 음수입니다. 이번 예시는 이중 부호가 없어 pd.to_numeric이 정상 변환됩니다(실측).
공식 예제의 화면 표시 함수 _format_display_value에 예시 값을 넣어 본 결과입니다(실측).
fmt('-399928') -> '-399,928'
fmt('+57700') -> '+57700' # '+'는 처리 안 해 쉼표가 안 붙는다
fmt('+0.70') -> '+0.70'
예제의 NUMERIC_COLUMNS는 등락율·순간거래량·현재가 3개뿐이라 누적순매수와 전일대비는 목록에 없습니다. 이 함수는 표시용이니 계산용 변환은 따로 해야 합니다. 연속조회 상한은 MAX_PAGES = 10·REQUEST_DELAY_SECONDS = 0.2로 형제 예제와 같습니다.
⑥ 응답에 회원사코드가 없고, 예시 "888"은 확인되지 않는다
응답 행에는 trde_ori_nm(이름)만 있고 코드 필드가 없습니다. 여러 회원사를 돌며 모으면 요청에 쓴 mmcm_cd를 행에 직접 붙여야 나중에 구분됩니다. 이름으로 맞추려 해도 ka10102 예시 이름은 "교 보"·"대 신"처럼 가운데 공백이 두 칸이라 공백을 지우고 비교해야 합니다. 예시 요청의 "888"은 ka10102 응답 예시("001"~"012" 10개)에 없어 어느 회원사인지 확인되지 않습니다. 응답 거래원명은 "다이와"입니다. 회원사 코드 형식("36" vs "036") 문제는 ka10040·회원사 코드 글에서 다뤘습니다.
명세가 비워 둔 것 — qty_tp 3·5의 수량, mrkt_tp "3"(종목)일 때 stk_cd가 사실상 필수인지, 하루 중 몇 시부터 몇 시까지의 행을 주는지, 한 번에 오는 최대 행 수, 매수 행의 tp 문자열("+매수"인지)은 명세에 없습니다. 첫 운영 호출에서 직접 확인하십시오.
4. 최소 호출 코드
토큰은 환경변수에서 읽고 ①~⑥을 코드에서 막습니다. cont-yn·next-key 처리는 연속조회 글과 같고, 오류 응답의 return_code는 키움 return_code 글에서 해석합니다.
import os, time, datetime, requests
import pandas as pd
BASE = "https://api.kiwoom.com" # 모의: https://mockapi.kiwoom.com
TOKEN = os.environ["KIWOOM_TOKEN"]
PATH = "/api/dostk/stkinfo" # ka10052·ka10043·ka10102 공통
NUM = ["mont_trde_qty", "acc_netprps", "cur_prc", "pred_pre", "flu_rt"]
SIGN = {"1": 1, "2": 1, "3": 0, "4": -1, "5": -1} # pred_pre_sig
def signed(s): # "+57700"·"-399928" 공통 처리
s = str(s).strip()
if s in ("", "None"):
return float("nan")
neg = s.startswith("-")
v = float(s.lstrip("+-") or 0)
return -v if neg else v
def post(api_id, body, cont_yn=None, next_key=None):
h = {"Content-Type": "application/json;charset=UTF-8",
"authorization": f"Bearer {TOKEN}", "api-id": api_id}
if cont_yn == "Y":
h.update({"cont-yn": "Y", "next-key": next_key})
r = requests.post(BASE + PATH, headers=h, json=body, timeout=10)
j = r.json()
if j.get("return_code") not in (None, 0):
raise RuntimeError(f"{api_id} {j.get('return_code')}: {j.get('return_msg')}")
return j, r.headers.get("cont-yn"), r.headers.get("next-key")
def to_frame(rows, trade_date, mmcm_cd):
df = pd.DataFrame(rows)
if df.empty:
return df
for c in NUM:
df[c] = df[c].map(signed)
df["cur_prc"] = df["cur_prc"].abs()
df["pred_pre"] = df["pred_pre"].abs() * df["pred_pre_sig"].map(SIGN) # ⑤
df["side"] = df["tp"].str.lstrip("+-")
df["trde_ori_key"] = df["trde_ori_nm"].str.replace(" ", "") # ⑥
df["mmcm_cd"] = mmcm_cd # ⑥
df["ts"] = pd.to_datetime(trade_date + df["tm"], format="%Y%m%d%H%M%S") # ③
return df.sort_values("ts").reset_index(drop=True)
def check_running(df): # ④ 빠진 행 검사
prev = df["acc_netprps"].shift(1)
ok = (prev + df["mont_trde_qty"] == df["acc_netprps"])
return ok.iloc[1:].all()
def ka10052(mmcm_cd, code6="", stex_tp="1", max_pages=10):
body = {"mmcm_cd": mmcm_cd, "stk_cd": code6,
"mrkt_tp": "3" if code6 else "0",
"qty_tp": "0", # ① 3·5 대신 받은 뒤 직접 거른다
"pric_tp": "0", "stex_tp": stex_tp}
today = datetime.date.today().strftime("%Y%m%d")
rows, cy, nk = [], None, None
for _ in range(max_pages):
j, cy, nk = post("ka10052", body, cy, nk)
rows += j.get("trde_ori_mont_trde_qty", [])
if cy != "Y":
break
time.sleep(0.2)
return to_frame(rows, today, mmcm_cd)
네트워크 없이 to_frame·check_running에 명세 응답 예시 3행을 넣고 날짜를 "20261022"로 붙인 결과입니다(실측).
ts trde_ori_key side mont_trde_qty acc_netprps cur_prc pred_pre flu_rt
0 2026-10-22 16:14:17 다이와 매도 -100000.0 -573076.0 57700.0 400.0 0.7
1 2026-10-22 16:14:23 다이와 매도 -100000.0 -673076.0 57700.0 400.0 0.7
2 2026-10-22 16:14:37 다이와 매도 -399928.0 -1073004.0 57700.0 400.0 0.7
running ok: True
회원사 여러 곳을 장중에 짧은 간격으로 돌리면 호출이 곱으로 늘어 키움 429 호출 제한에 닿기 쉽습니다. 장중 실시간이 꼭 필요하면 WebSocket 0F를, 마감 뒤 기록이면 ka10052를 하루 한두 번 받는 식으로 나누는 편이 무난합니다.
창구 데이터는 그 증권사 고객 전체의 합이라 누가 주문했는지 알려 주지 않으므로 이 데이터만으로 매매 근거를 삼을 수는 없으며, 이 글은 특정 종목이나 전략을 권하지 않습니다. 명세는 바뀔 수 있으니 키움 REST API 공식 문서로 현재 값을 확인하십시오.
5. 자주 묻는 질문
ka10052와 ka10043은 무엇이 다른가요?
둘 다 /api/dostk/stkinfo 경로에 회원사코드(mmcm_cd)를 받지만, ka10043은 회원사 1곳 × 종목 1개의 일별 매수·매도 수량을 기간으로 주고, ka10052는 회원사 1곳의 순간 대량 체결을 HHmmss 시각 행으로 줍니다. ka10052에는 날짜 파라미터가 없고 종목코드(stk_cd)는 선택이며, 수량구분(qty_tp)·가격구분(pric_tp)으로 걸러 받습니다.
ka10052 qty_tp 3과 5는 몇 주인가요?
공식 명세의 qty_tp 설명은 '0:전체, 1:1000주, 2:2000주, 3:, 5:, 10:10000주, 30: 30000주, 50: 50000주, 100: 100000주'로 3과 5의 수량이 비어 있습니다. 앞뒤 규칙상 3000주·5000주로 보이지만 명세에 적혀 있지 않으므로, 쓰기 전에 0(전체)으로 받은 결과와 비교해 확인하거나 키움 공식 문서로 확인하십시오.
ka10052 응답에 날짜가 없는데 어떻게 저장하나요?
응답 시간 tm은 'HHmmss' 6자리뿐이고 날짜 필드가 없습니다. 호출한 날짜를 직접 붙여 타임스탬프를 만들어 저장해야 하며, 자정을 넘겨 실행하거나 전날 데이터를 다음 날 받는 구성이면 날짜가 틀어질 수 있습니다.
ka10052 mmcm_cd '888'은 어느 증권사인가요?
명세 예시 요청과 공식 예제가 모두 '888'을 쓰지만, ka10102 회원사 리스트 예시에는 001~012의 10개만 있어 888이 무엇인지 확인되지 않습니다. 응답 예시의 거래원명은 '다이와'입니다. ka10102를 실제로 호출해 받은 코드를 쓰십시오.
창구별 대량 체결을 기록하는 키움 봇, 만들어 드립니다
보고 싶은 회원사와 종목만 알려 주시면 TR 경로·부호 정리·날짜 붙이기·빠진 행 검사까지 맞춰 드립니다. 24시간 빠른 답변 가능합니다.
무료 상담 시작하기