키움 ka10044 일별기관매매종목 — 100주·백만원 단위다
ka10044(일별기관매매종목요청)는 strt_dt~end_dt 동안 기관이 많이 순매수(또는 순매도)한 종목을 순위 목록으로 주는 TR이고, 수량 netprps_qty는 100주, 금액 netprps_amt는 백만원 단위입니다. 공식 명세 337개 TR 중 수량을 100주로 적은 필드는 이것 하나뿐이라, 쌍둥이 TR인 ka10058 투자자별일별매매종목(수량 1주)과 합치면 100배가 어긋납니다. 100주 미만 순매도는 "-0"으로 와서 파이썬에서 -0.0이 되고, 명세의 응답 필드는 4개인데 예시에는 prsm_avg_pric·cur_prc·avg_pric_pre·pre_rt 4개가 더 있습니다. 투자자 구분이 없어 기관 하위 분류(투신·연기금)는 고를 수 없고, trde_tp는 "2"가 순매수입니다. (키움 공식 명세 kiwoom_api_spec.json·공식 GitHub 예제 기준, 2026-10-30 확인)
목차
- ka10044는 무엇을 주나 — ka10058·ka10045와 나누기
- 요청·응답 실물
- 함정 5가지
- 받아서 저장하는 코드
- 자주 묻는 질문
1. ka10044는 무엇을 주나 — ka10058·ka10045와 나누기
메뉴 위치는 국내주식 > 시세, URL은 POST /api/dostk/mrkcond입니다. 이름의 "일별"과 달리 응답에 날짜 필드가 없고, 요청한 기간을 합친 결과가 종목당 한 줄씩 옵니다. 어제 정리한 ka10058과 요청 필드 다섯 개(strt_dt·end_dt·trde_tp·mrkt_tp·stex_tp)가 같고, ka10058에만 invsr_tp가 하나 더 있습니다. 같은 기관 데이터를 주는 TR이 셋이라 용도를 먼저 나눠 두면 덜 헤맵니다.
| TR | URL | 결과 모양 | 투자자 선택 | 수량 단위 | 금액 단위 |
|---|---|---|---|---|---|
| ka10044 일별기관매매종목 | mrkcond | 기간 합계 · 종목 순위 | 없음(기관) | 100주 | 백만원 |
| ka10058 투자자별일별매매종목 | stkinfo | 기간 합계 · 종목 순위 | invsr_tp 12종 | 1주 | 원(예시 검산은 만원) |
| ka10045 종목별기관매매추이 | mrkcond | 종목 1개 · 날짜별(dt) | 기관·외인 열 고정 | 1주 | — |
정리하면, "오늘 기관이 많이 산 종목 30개"는 ka10044, "오늘 연기금이 많이 산 종목"은 ka10058(invsr_tp=6000), "삼성전자의 지난 20일 기관 순매수 흐름"은 ka10045입니다. ka10045는 stk_cd를 넣고 응답에 dt·orgn_daly_nettrde_qty(기관일별순매매수량, 1주)가 날짜별로 옵니다. 연속 순매수 일수 같은 조건은 ka10131 기관외국인연속매매가 따로 있습니다.
2. 요청·응답 실물
헤더는 다른 키움 REST TR과 같습니다 — api-id: ka10044, authorization: Bearer ..., 다음 페이지가 있으면 응답 헤더의 cont-yn·next-key를 그대로 다시 보냅니다. body 다섯 개는 모두 필수입니다. 명세의 요청 예시 그대로입니다.
POST https://api.kiwoom.com/api/dostk/mrkcond
api-id: ka10044
Content-Type: application/json;charset=UTF-8
{
"strt_dt": "20241106",
"end_dt": "20241107",
"trde_tp": "1",
"mrkt_tp": "001",
"stex_tp": "3"
}
| 필드 | 한글명 | 값 (명세 원문) |
|---|---|---|
strt_dt · end_dt | 시작일자 · 종료일자 | YYYYMMDD (최대 기간은 명세에 없음) |
trde_tp | 매매구분 | "1:순매도, 2:순매수" → 2가 순매수 |
mrkt_tp | 시장구분 | 001 코스피 · 101 코스닥 (000 전체 없음) |
stex_tp | 거래소구분 | 1 KRX · 2 NXT · 3 통합 (원문 "3.통합") |
명세의 응답 예시입니다(리스트 키 daly_orgn_trde_stk).
{
"daly_orgn_trde_stk": [
{"stk_cd": "005930", "stk_nm": "삼성전자",
"netprps_qty": "-0", "netprps_amt": "-1", "prsm_avg_pric": "140000",
"cur_prc": "-95100", "avg_pric_pre": "--44900", "pre_rt": "-32.07"},
{"stk_cd": "005930", "stk_nm": "삼성전자",
"netprps_qty": "-0", "netprps_amt": "-0", "prsm_avg_pric": "12000",
"cur_prc": "9920", "avg_pric_pre": "--2080", "pre_rt": "-17.33"}
],
"return_code": 0,
"return_msg": "정상적으로 처리되었습니다"
}
같은 종목코드가 두 번 나오고 삼성전자 현재가가 9,920원인 것으로 보아 테스트값입니다. 숫자 자체보다 형식(부호·단위·필드 구성)을 읽는 용도로 봐야 합니다.
3. 함정 5가지
① 수량 100주 · 금액 백만원 — 337개 중 유일한 단위
명세의 netprps_qty 설명은 "단위: 100주", netprps_amt는 "단위: 백만원"입니다. 337개 TR의 응답 필드 설명 전체를 훑어 "100주"가 나오는 곳은 ka10044의 netprps_qty 한 군데뿐입니다. 같은 이름 netprps_qty를 쓰는 ka10034·ka10043·ka10063·ka10078은 모두 1주 단위이고, netprps_amt도 ka10063은 백만원이지만 ka10039는 천원입니다. 필드 이름이 같다고 같은 파서를 쓰면 ka10044만 100배 작게 들어갑니다. ka10058과 합칠 때는 ka10044 수량에 100, 금액에 1,000,000을 곱해 원·주로 맞춘 뒤 저장하세요.
② 100주 미만 순매도는 "-0"이다
예시 첫 행은 수량 "-0", 금액 "-1"입니다. 1백만원 ÷ 추정평균가 140,000원 = 약 7.1주로, 100주 단위로 줄이면 0이 되는 크기입니다. 부호만 남은 이 값을 파이썬에서 바꾸면 이렇게 됩니다.
>>> int("-0"), float("-0")
(0, -0.0)
>>> float("-0") < 0
False
float로 바꾼 -0.0은 0과 같다고 판정되므로 df[df.netprps_qty < 0]로 순매도 종목을 고르면 이 행이 빠집니다. 그런데 금액은 −1백만원이라 실제로는 팔았습니다. 소액 종목이나 짧은 기간(하루)일수록 수량이 0으로 뭉개지는 행이 많아지니, 방향 판정과 정렬은 금액(netprps_amt)으로 하고 수량은 참고값으로 두는 편이 안전합니다. 둘째 행처럼 수량·금액이 모두 "-0"인 행은 백만원 미만 순매도라 크기를 알 수 없습니다.
③ 명세의 응답 필드는 4개, 예시는 8개
명세 응답 표에는 stk_cd·stk_nm·netprps_qty·netprps_amt 네 개만 있습니다. 예시에는 prsm_avg_pric(추정평균가)·cur_prc(현재가)·avg_pric_pre(평균가대비)·pre_rt(대비율)가 더 있습니다. 337개 TR의 응답 예시 키와 명세 필드를 전수 대조하면 이렇게 명세에 없는 키가 예시에 섞인 TR이 41개이고, ka10044가 그중 하나입니다. 공식 예제 get_domestic_daily_institution_stock_trade.py도 COLUMNS에 네 개만 정의해서, rename(columns=COLUMNS)를 하면 컬럼이 이렇게 섞입니다.
['종목코드', '종목명', '순매수수량', '순매수금액', 'prsm_avg_pric', 'cur_prc', 'avg_pric_pre', 'pre_rt']
실서버가 8개를 줄지 4개를 줄지는 명세로 확정할 수 없습니다. 파서는 네 개 필드만 필수로 보고 나머지는 "있으면 쓰는" 구조로 만들어 두면, 어느 쪽이 와도 KeyError로 멈추지 않습니다(4장 코드).
④ 이중 부호 "--44900" — 공식 예제도 못 읽는다
avg_pric_pre가 "--44900"처럼 마이너스가 두 번 붙어 옵니다. 검산하면 |cur_prc| 95,100 − prsm_avg_pric 140,000 = −44,900이 정확히 맞고, pre_rt는 −44,900 ÷ 140,000 = −32.071% → -32.07, 둘째 행도 −2,080 ÷ 12,000 = −17.333% → -17.33입니다. 즉 pre_rt는 전일 대비 등락률이 아니라 기관 추정평균가 대비 현재가이고, 이 구조는 ka10058과 같습니다. 문제는 숫자 변환입니다. 공식 예제의 표시 함수 _format_display_value에 넣어 본 결과입니다.
'-0' -> '-0'
'--44900' -> '--44900'
'140000' -> '140,000'
'-95100' -> '-95100'
이중 부호는 숫자로 인식하지 못해 문자열 그대로 남고, int("--44900")은 ValueError: invalid literal for int() with base 10로 멈춥니다. 또 cur_prc의 "-95100"은 가격이 음수라는 뜻이 아니라 전일 대비 하락이라는 부호이므로 절댓값으로 써야 합니다.
⑤ 기관을 고를 수 없고, 필드 이름은 이번엔 맞다
요청에 투자자 구분이 없습니다. 명세는 이 "기관"이 어떤 하위 분류의 합인지 적지 않으므로, 기관계로 쓰려면 같은 날 ka10058에 invsr_tp="9999"(기관계)를 넣은 결과와 상위 종목을 한 번 대조해 보는 것이 좋습니다. 필드 이름은 ka10058보다 정직합니다. ka10058은 순매수 요청에도 필드명이 netslmt_*(순매도)였지만, ka10044는 netprps_*(순매수)이고 순매도 요청(trde_tp="1") 예시의 값이 음수입니다 — 이름 그대로 "순매수, 부호 포함"으로 읽으면 됩니다. 다만 trde_tp 순매수 값이 TR마다 "0"(ka10059·ka10066)·"1"(ka10065)·"2"(ka10044·ka10058)로 갈리니 상수는 TR별로 둡니다. mrkt_tp에 000이 없어 코스피·코스닥을 따로 불러야 하는 것도 ka10058과 같습니다.
4. 받아서 저장하는 코드
단위 환산, 이중 부호, -0, 명세 밖 필드의 유무까지 처리합니다. 토큰 발급·호출부는 생략했고, 연속조회는 next-key 처리대로 페이지를 이어 붙인 rows를 넘긴다고 가정합니다.
import pandas as pd
TRDE_TP = {"순매도": "1", "순매수": "2"} # ka10044 전용 (ka10066은 "0"이 순매수)
REQUIRED = ["stk_cd", "stk_nm", "netprps_qty", "netprps_amt"] # 명세 필드
OPTIONAL = ["prsm_avg_pric", "cur_prc", "avg_pric_pre", "pre_rt"] # 예시에만 있는 필드
def to_num(v):
s = str(v).strip().replace(",", "")
neg = s.startswith("-")
s = s.lstrip("+-") # "--44900" 이중 부호
x = float(s or 0)
return -x if (neg and x) else x # "-0" → 0.0 (부호는 버린다)
def parse_ka10044(rows, strt_dt, end_dt, trde_tp, mrkt_tp):
df = pd.DataFrame(rows)
if df.empty:
return df
missing = [c for c in REQUIRED if c not in df.columns]
if missing:
raise ValueError(f"ka10044 응답에 필수 필드 없음: {missing}")
df["qty_sh"] = df["netprps_qty"].map(to_num) * 100 # 100주 → 주
df["amt_won"] = df["netprps_amt"].map(to_num) * 1_000_000 # 백만원 → 원
for c in OPTIONAL:
df[c] = df[c].map(to_num) if c in df.columns else None
if df["cur_prc"].notna().all():
df["cur_prc"] = df["cur_prc"].abs() # 부호 = 전일 대비 방향
df.insert(0, "strt_dt", strt_dt) # 응답에 날짜가 없다
df.insert(1, "end_dt", end_dt)
df.insert(2, "side", {v: k for k, v in TRDE_TP.items()}[trde_tp])
df.insert(3, "mrkt_tp", mrkt_tp)
return df.drop(columns=["netprps_qty", "netprps_amt"])
명세 응답 예시 2행을 parse_ka10044(rows, "20241106", "20241107", "1", "001")에 넣은 출력입니다.
strt_dt end_dt side mrkt_tp stk_cd prsm_avg_pric cur_prc avg_pric_pre pre_rt qty_sh amt_won
0 20241106 20241107 순매도 001 005930 140000.0 95100.0 -44900.0 -32.07 0.0 -1000000.0
1 20241106 20241107 순매도 001 005930 12000.0 9920.0 -2080.0 -17.33 0.0 0.0
(stk_nm 열은 지면상 뺐습니다.) 명세 필드 4개만 오는 경우를 가정해 예시에서 추가 필드를 지우고 넣으면, prsm_avg_pric 등 네 열이 None으로 채워질 뿐 같은 qty_sh·amt_won이 나옵니다.
첫 행의 수량은 0이지만 금액이 −1,000,000원으로 남아 순매도임을 알 수 있습니다. 실계좌에서는 장 마감 뒤 strt_dt=end_dt=오늘, 코스피·코스닥 × 순매수·순매도 4번을 부르면 하루치가 됩니다. 페이지가 이어지면 호출이 늘어나니 429 호출 제한 간격을 지키세요(공식 예제는 MAX_PAGES = 10, REQUEST_DELAY_SECONDS = 0.2). 저장 키는 (strt_dt, end_dt, side, mrkt_tp, stk_cd)입니다.
- ka10058과 같이 쌓을 때 — 이 코드처럼 주·원으로 환산한 컬럼(
qty_sh·amt_won)만 저장하면 투자자 구분 하나("기관")를 더한 같은 표에 넣을 수 있습니다. ka10058의 금액 단위는 명세("원")와 예시 검산(만원)이 달라 허브 글의check_units로 먼저 확정하세요. - 매매 필터로 쓸 때 — 기관 순매수 상위와 외국인 순매수 상위의 교집합 같은 수급 필터는 수급 데이터로 봇 필터 만들기에 정리했습니다. 수급은 후보를 좁히는 도구이지 수익을 보장하지 않으며, 과거 수급 패턴이 앞으로 반복된다는 근거도 없습니다.
키움 REST 전체 구조(토큰·도메인·TR 분류)는 키움 REST API 자동매매 가이드에서 먼저 보시면 이 TR이 어디에 놓이는지 잡힙니다.
5. 자주 묻는 질문
ka10044의 netprps_qty는 몇 주 단위인가요?
공식 명세상 100주 단위입니다. 값 15는 1,500주라는 뜻이고, 금액 netprps_amt는 백만원 단위입니다. 공식 명세 337개 TR 가운데 수량을 100주 단위로 적은 필드는 ka10044의 netprps_qty 하나뿐이라 다른 TR과 합칠 때 반드시 환산해야 합니다.
ka10044 응답에 -0이 오는 것은 무엇인가요?
100주 단위로 줄이면서 0이 된 순매도입니다. 명세 예시에서 수량은 -0인데 금액은 -1(백만원)이고 추정평균가가 140,000원이라 약 7주에 해당합니다. 파이썬 float로 바꾸면 -0.0이 되어 qty < 0 조건에서 빠지므로, 매도 여부는 금액으로 판정하는 편이 안전합니다.
ka10044에서 기관 종류를 고를 수 있나요?
고를 수 없습니다. 요청 필드는 strt_dt, end_dt, trde_tp, mrkt_tp, stex_tp 다섯 개뿐이고 투자자 구분이 없습니다. 투신·연기금처럼 기관 하위 분류가 필요하면 invsr_tp를 받는 ka10058을 써야 합니다.
ka10044와 ka10045는 무엇이 다른가요?
ka10044는 기간 동안 기관이 많이 순매수하거나 순매도한 종목의 순위 목록이고, ka10045(종목별기관매매추이요청)는 종목 하나를 넣어 날짜별 기관·외국인 순매매 수량을 받는 시계열입니다. ka10045의 수량은 1주 단위입니다.
기관·외국인 수급을 쌓는 봇, 만들어 드립니다
ka10044·ka10058·ka10045로 기관·투자자별 순매매를 매일 받아 단위를 맞춰 저장하고, 매매 필터로 쓰는 키움 REST 봇을 맞춤 제작합니다. 24시간 빠른 답변 가능합니다.
무료 상담 시작하기