AlgoLab Blog · 키움증권 시세 · 2026

키움 REST API 업종지수 조회 — ka20001·ka20006 시장 필터 함정 6가지

키움증권 · 지수 데이터 2026-09-29 · 알고랩 AlgoLab
한 줄 요약

키움 REST API 로 코스피·코스닥 지수 일봉은 ka20006 업종일봉조회요청(POST /api/dostk/chart, 필수 inds_cd·base_dt), 장중 현재 지수는 ka20001 업종현재가요청(POST /api/dostk/sect, 필수 mrkt_tp·inds_cd)으로 받습니다. 코스피 종합은 inds_cd 001, 코스닥 종합은 101입니다. 시장 필터(코스피 종가가 20·60일 이동평균 위일 때만 신규 매수)에서 걸리는 곳은 여섯입니다 — ⑴ 두 TR 은 경로가 다르다 ⑵ ka20006 가격은 소수점을 뗀 100배 정수, ka20001 은 부호 붙은 소수라 섞으면 100배 어긋난다 ⑶ 일봉은 최신순으로 온다 ⑷ 거래량 단위가 1000주와 1주로 다르다 ⑸ 오늘 봉은 미완성일 수 있다 ⑹ 형제 TR 명세에 오기가 있다.

이 글은 키움 REST API 자동매매 완전 가이드의 업종(지수) 편입니다. 종목 일봉 ka10081 은 키움 차트 데이터 ka10081에서 다뤘습니다. 필드명은 공식 명세 kiwoom_api_spec.json 기준(2026-09-29)입니다.

1. 업종 TR 지도 — 지수는 11개 TR 에 흩어져 있다

지수 TR 은 명세의 업종(/sect)과 차트(/chart) 메뉴에 나뉘어 있습니다. 시장 필터에 쓰는 건 ka20006·ka20001 둘입니다.

api-id이름응답 리스트
ka20001업종현재가요청inds_cur_prc_tm(시간별)
ka20002업종별주가요청inds_stkpc(구성 종목 시세)
ka20003전업종지수요청all_inds_idex
ka20009업종현재가일별요청inds_cur_prc_daly_rept
ka20004업종틱차트조회요청inds_tic_chart_qry
ka20005업종분봉조회요청inds_min_pole_qry
ka20006업종일봉조회요청inds_dt_pole_qry
ka20007업종주봉조회요청inds_stk_pole_qry
ka20008업종월봉조회요청inds_mth_pole_qry
ka20019업종년봉조회요청inds_yr_pole_qry
ka10101업종코드 리스트list(code·name)

ka20001·ka20002·ka20003·ka20009 는 /api/dostk/sect, 봉 TR 은 /api/dostk/chart, ka10101 은 /api/dostk/stkinfo 입니다. 명세의 inds_cd 값은 001 종합(KOSPI), 002 대형주, 101 종합(KOSDAQ), 201 KOSPI200, 302 KOSTAR, 701 KRX100 등이고 나머지는 ka10101 로 받습니다.

2. 요청 — 두 TR 은 경로와 필수 필드가 다르다

첫 함정은 복사·붙여넣기입니다. 경로가 다르고, ka20001 에만 mrkt_tp(0 코스피 · 1 코스닥 · 2 코스피200)가, ka20006 에만 base_dt 가 필수입니다. 공식 Postman 컬렉션 원문입니다.

// ka20006 업종일봉조회요청 — 공식 Postman 컬렉션(PRD) 원문
POST https://api.kiwoom.com/api/dostk/chart
api-id: ka20006
authorization: Bearer {ACCESS_TOKEN}
cont-yn:
next-key:
{
  "inds_cd": "001",
  "base_dt": "20260507"
}

// ka20001 업종현재가요청 — 경로가 다르고 mrkt_tp 가 하나 더 붙는다
POST https://api.kiwoom.com/api/dostk/sect
api-id: ka20001
{
  "mrkt_tp": "0",
  "inds_cd": "001"
}

짝이 어긋나면 1504(해당 URI 에서 지원하지 않는 API ID), 필수 필드가 빠지면 1511 이 옵니다. 업무 오류는 HTTP 200 과 return_code 로 오므로 raise_for_status() 만으로는 못 잡습니다(return_code 판별).

ka20001 은 mrkt_tp 와 inds_cd 짝을 맞추십시오(101 이면 1).

3. 응답 — 100배 정수와 부호 붙은 소수

가장 비싼 함정입니다. ka20006 의 cur_prc·open_pric·high_pric·low_pric 는 “소수점 제거된 100배 값”, ka20001 의 같은 이름 필드는 “부호가 포함된 숫자”("-2394.49")입니다. 이름은 같고 단위는 100배 다릅니다.

// ka20006 응답 — 공식 명세 예시값(원문 끝의 쉼표만 제거)
{
  "inds_cd": "001",
  "inds_dt_pole_qry": [
    {"cur_prc": "252127", "trde_qty": "393564", "dt": "20250210",
     "open_pric": "251064", "high_pric": "252733", "low_pric": "249918",
     "trde_prica": "10582466"},
    {"cur_prc": "252192", "trde_qty": "419872", "dt": "20250207",
     "open_pric": "253209", "high_pric": "253763", "low_pric": "251901",
     "trde_prica": "10240141"}
  ],
  "return_code": 0,
  "return_msg": "정상적으로 처리되었습니다"
}

// ka20001 응답 일부 — 공식 명세 예시값
{"cur_prc": "-2394.49", "pred_pre_sig": "5", "flu_rt": "-10.42",
 "open_pric": "-2669.53", "trde_qty": "890", "inds_cur_prc_tm": [...]}

섞으면 필터가 조용히 고장 납니다. 이동평균은 ka20006(252127 수준), 현재 지수는 ka20001(2394.49 수준)로 받아 “현재가 > 이동평균”을 비교하면 늘 거짓, 부등호를 뒤집은 차단 조건이면 늘 참입니다. ka20006 은 ÷100, ka20001 은 abs() 만. 종목 일봉 ka10081 에는 이 100배 설명이 없어, 종목용 파서를 재사용하면 여기서 틀립니다.

ka20001 부호는 방향 표시입니다. 시가 open_pric 도 "-2669.53" 으로 오므로 값은 절댓값으로 쓰고, 방향은 pred_pre_sig(2 상승 · 3 보합 · 5 하락 등)로 봅니다.

거래량도 다릅니다. trde_qty 가 ka20001 은 1000주, ka20006 은 1주 단위입니다.

장 시작 전 1회 — 지수 일봉으로 오늘 신규 매수를 열지 닫을지 정한다 ka20006 inds_cd 001 · base_dt ÷100 · 오름차순 MA20 · MA60 전일까지 종가 gate 종가 > 두 평균? YES → 신규 매수 허용 NO → 신규 매수 보류 장중 확인이 필요하면 ka20001 cur_prc "-2394.49" — abs() 만, ÷100 금지
ka20006(/chart)과 ka20001(/sect)은 경로도 단위도 다르다

4. 연속조회와 정렬 — 최신순으로 온다

명세 예시 응답은 20250210 다음에 20250207 이 오는 최신순입니다. 정렬 없이 pandas rolling() 을 돌리면 “미래 20일 평균”이 나와 미래참조가 됩니다.

한 번에 오는 봉 개수는 명세에 없습니다. cont-yn 이 Y 인 동안 next-key 를 실어 이어 받고, 필요한 개수가 모이면 멈춥니다(키움 연속조회 next-key).

import time, datetime as dt, requests, pandas as pd

BASE  = "https://api.kiwoom.com"      # 모의투자: https://mockapi.kiwoom.com
CHART = "/api/dostk/chart"            # ka20006 업종일봉
SECT  = "/api/dostk/sect"             # ka20001 업종현재가 — 경로가 다르다

def post(path, api_id, body, token, cont_yn="N", next_key=""):
    r = requests.post(BASE + path, json=body, timeout=10, headers={
        "Content-Type": "application/json;charset=UTF-8",
        "authorization": f"Bearer {token}",
        "api-id": api_id, "cont-yn": cont_yn, "next-key": next_key})
    r.raise_for_status()
    data = r.json()
    if data.get("return_code") not in (0, None):      # 업무 오류도 HTTP 200
        raise RuntimeError(f"{api_id} rc={data.get('return_code')} {data.get('return_msg')}")
    return data, r.headers.get("cont-yn", "N"), r.headers.get("next-key", "")

def num(s):
    s = (s or "").strip().replace(",", "")
    return abs(float(s)) if s not in ("", "+", "-") else float("nan")

def index_daily(token, inds_cd="001", base_dt=None, need=130, max_pages=10):
    base_dt = base_dt or dt.date.today().strftime("%Y%m%d")
    body = {"inds_cd": inds_cd, "base_dt": base_dt}
    rows, cy, nk = [], "N", ""
    for _ in range(max_pages):
        data, cy, nk = post(CHART, "ka20006", body, token, cy, nk)
        rows += data.get("inds_dt_pole_qry") or []
        if cy != "Y" or len(rows) >= need:
            break
        time.sleep(0.25)                                # 초당 5회 한도 안쪽
    df = pd.DataFrame(rows)
    if df.empty: raise RuntimeError("ka20006 빈 응답")
    df["date"] = pd.to_datetime(df["dt"], format="%Y%m%d")
    for c in ("open_pric", "high_pric", "low_pric", "cur_prc"):
        df[c] = df[c].map(num) / 100                    # 소수점 제거된 100배 → 지수
    df = (df.rename(columns={"cur_prc": "close"})
            .drop_duplicates("date")
            .sort_values("date")                        # 최신순 → 오름차순
            .set_index("date"))
    return df[["open_pric", "high_pric", "low_pric", "close"]]

5. 시장 필터 함수 — 오늘 봉은 뺀다

장중에 base_dt 를 오늘로 부르면 첫 행에 오늘 날짜가 올 수 있는데, 그 값이 확정 종가인지 현재값인지는 명세에 없습니다. 그래서 판정은 전일까지 완성된 봉으로 하고, 같은 규칙을 백테스트에도 겁니다.

def market_gate(df, fast=20, slow=60, today=None):
    today = today or pd.Timestamp.today().normalize()
    done = df[df.index < today]                 # 오늘 봉은 미완성일 수 있어 뺀다
    if len(done) < slow:
        return {"ok": False, "reason": "봉 부족"}
    c = done["close"]
    ma_f = c.rolling(fast).mean().iloc[-1]
    ma_s = c.rolling(slow).mean().iloc[-1]
    last = c.iloc[-1]
    return {"ok": bool(last > ma_f and last > ma_s), "asof": c.index[-1].date(),
            "close": round(last, 2), f"ma{fast}": round(ma_f, 2), f"ma{slow}": round(ma_s, 2)}

def live_index(token, mrkt_tp="0", inds_cd="001"):
    data, _, _ = post(SECT, "ka20001", {"mrkt_tp": mrkt_tp, "inds_cd": inds_cd}, token)
    return {"now": num(data.get("cur_prc")),            # 이미 소수 — ÷100 하지 않는다
            "sig": data.get("pred_pre_sig"),
            "chg_pct": float(data.get("flu_rt") or 0)}

# 장 시작 전 1회: gate = market_gate(index_daily(token, "001"))
# gate["ok"] 가 False 면 신규 매수만 멈춘다(손절·청산은 계속)

필터가 막는 건 신규 매수뿐이어야 합니다. 손절·청산까지 멈추면 보유 종목이 방치됩니다. 다른 필터와의 조합은 수급 필터 만들기 참고.

6. 명세 오기 — 형제 TR 을 복사할 때 조심할 곳

어느 쪽이 실제 동작인지는 단정하지 않습니다.

TR명세 원문어긋나는 점
ka20007 주봉inds_cd length 8, base_dt length 3다른 봉 TR 은 3·8 — 뒤바뀐 듯
ka20005 분봉응답 필드 정의는 inds_min_pole_qry예시 응답은 일봉 키 inds_dt_pole_qry — 첫 호출 때 실제 키를 로그로 확인
ka20006 일봉예시 요청 base_dt 20250905응답은 2025년 2월, 끝 쉼표로 JSON 파싱 불가

7. 호출 예산 — 지수는 하루 한 번이면 된다

키움증권 공지 「REST API 유량 정책 안내(2026.07.02 기준)」는 국내주식을 토큰별 조회 TR 1초당 5회로 안내합니다. 전일 종가 기준 필터라면 장 시작 전 ka20006 을 코스피·코스닥 각 1회(연속조회 포함) 부르면 끝납니다. 장중 ka20001 을 매 초 부르면 1700 에 먼저 닿습니다(키움 429 대응). 휴장일 배치는 KRX 휴장일 체크로 건너뜁니다.

붙이기 전 체크리스트

지수 필터를 봇에 넣기 전 확인할 네 줄.

자주 묻는 질문

키움 REST API 로 코스피 지수 일봉을 받으려면 어떤 TR 을 쓰나요?

업종일봉조회요청 ka20006 입니다. POST /api/dostk/chart 에 api-id 헤더 ka20006, 바디에 inds_cd(코스피 001, 코스닥 101)와 base_dt(YYYYMMDD)를 넣습니다. 둘 다 필수입니다. 봉 목록은 inds_dt_pole_qry 리스트로 오고, 더 과거는 cont-yn 이 Y 일 때 next-key 를 실어 이어 받습니다.

ka20006 의 cur_prc 가 252127 처럼 너무 크게 나옵니다.

명세대로입니다. ka20006 의 가격 필드는 소수점을 제거한 100배 값이라 252127 은 2521.27 입니다. 반면 ka20001 의 cur_prc 는 -2394.49 처럼 부호 붙은 소수입니다. 둘을 섞어 비교하면 100배 차이로 필터가 늘 한쪽으로만 판정됩니다.

코스피가 이동평균선 아래면 매수를 멈추는 필터를 쓰면 손실이 줄어드나요?

그렇다고 말할 수 없습니다. 효과는 기간·시장에 따라 다르고 과거 결과가 미래를 보장하지 않습니다. 이 글은 데이터를 정확히 받는 법만 다룹니다.

업종지수도 초당 호출 제한에 포함되나요?

키움 유량 공지(2026.07.02)는 국내주식 조회 TR 을 토큰별 초당 5회로 안내하고 업종 TR 을 따로 빼지 않습니다. 지수 일봉은 하루 한 번이면 충분합니다.

고지. 이 글은 기술 자료이며 특정 지수·종목·전략을 권유하지 않고 시장 방향을 예측하지 않습니다. 필드·코드값은 키움증권 공식 명세·Postman 컬렉션·공지를 2026-09-29 기준으로 대조했지만, 증권사 API 스펙과 유량 정책은 예고 없이 바뀌므로 실제 적용 전 키움증권 공식 문서를 다시 확인하십시오. 알고랩(퀀트웍스)은 투자자문업·투자일임업을 영위하지 않으며, 고객이 지정한 규칙을 프로그램으로 구현해 드리는 도구 제공자입니다.

시장 필터가 들어간 봇, 맡기시겠어요?

지수 필터·호출 예산·판정 로그까지 백테스트와 실매매가 같은 규칙으로 도는 구조로 만들어 드립니다.

상담 문의하기