AlgoLab Blog · KIS API 실무 · 2026

KIS 예상체결가 추이 FHPST01810000 — 30건 함정

KIS API · 시세분석 2026-10-11 · 약 8분 읽기 · 알고랩 AlgoLab
한 줄 요약

한국투자증권 KIS API에서 종목 1개의 예상체결가 흐름은 GET /uapi/domestic-stock/v1/quotations/exp-price-trend에 tr_id FHPST01810000으로 받고, 필수 파라미터는 FID_COND_MRKT_DIV_CODE=J·FID_INPUT_ISCD·FID_MKOP_CLS_CODE(0:전체, 4:체결량 0 제외) 세 개입니다. 공식 설명대로 최대 30건까지만 오고 다음 조회가 안 되며, 장전·장마감을 고르는 코드가 없습니다. 같은 이름의 FID_MKOP_CLS_CODE가 형제 API에서는 "1:장시작전, 2:장마감"이라 그대로 옮기면 틀립니다. 공식 저장소 기준 모의투자 칸은 비어 있어 실전 앱키 전용입니다.

목차

  1. 스펙 한 장
  2. 요청·응답 실물
  3. 함정 5가지
  4. 봇에서 쓰는 법 — 장전 갭 점검
  5. 자주 묻는 질문

지금 이 순간의 예상체결가 하나는 허브 글 KIS API 호가 조회 FHKST01010200의 output2.antc_cnpr로 받습니다. 이 글은 그 흐름 — 장전 동시호가 동안 예상체결가가 어떻게 움직였는지 — 를 받는 API 하나만 떼어 냅니다. 출처는 한국투자증권 공식 GitHub 저장소 koreainvestment/open-trading-api의 examples_llm/domestic_stock/exp_price_trend/(exp_price_trend.py·chk_exp_price_trend.py), examples_user/domestic_stock/domestic_stock_functions.py, MCP/KIS Code Assistant MCP/data.csv, legacy/README.md·legacy/postman/README.md, 실전계좌_POSTMAN_샘플코드_v2.6.json입니다(2026-10-11 zipball 기준).

1. 스펙 한 장

항목값
API명[국내주식] 시세분석 > 국내주식 예상체결가 추이 [국내주식-118]
HTS 화면eFriend Plus [0184] — 설명문 표기는 "예상체결지수 추이"
메서드 · URLGET /uapi/domestic-stock/v1/quotations/exp-price-trend
tr_idFHPST01810000 (Postman 설명 "[실전투자]")
헤더authorization(Bearer access_token) · appkey · appsecret · tr_id · custtype=P
모의투자legacy/README.md 제공 칸 공란 · legacy/postman/README.md 실전 ⭕
건수"최대 30건 확인 가능하며, 다음 조회가 불가합니다"(공식 설명 원문)
응답output1(객체 1개) + output2(배열)

'예상체결' 이름이 붙은 KIS API가 많아 섞이기 쉽습니다. 종목·지수, 단건·흐름으로 나누면 이렇습니다.

용도tr_id
종목 1개 · 지금 예상체결가FHKST01010200 (호가/예상체결)
종목 1개 · 예상체결가 흐름 (이 글)FHPST01810000
예상체결 기준 등락률 순위FHPST01820000
지수 · 예상체결지수 추이FHPST01840000
지수 · 예상체결 전체지수FHKUP11750000
장마감 상·하한가 예상 목록FHKST117300C0
실시간 푸시H0STANC0 (국내주식 실시간예상체결)

설명문의 HTS 화면 이름 "예상체결지수 추이"는 지수 API FHPST01840000의 이름과 똑같습니다. 종목 API에 지수 화면명이 붙어 있는 셈이라, HTS 화면으로 동작을 확인할 때 [0184]가 종목 흐름을 보여 주는지 먼저 보십시오. 모의 서버에서 막히는 API 전체 목록은 KIS 모의투자 한계에 있습니다.

2. 요청·응답 실물

Postman v2.6 샘플의 원본 요청 줄입니다(저장소 원문 그대로).

{{PROD}}/uapi/domestic-stock/v1/quotations/exp-price-trend?fid_cond_mrkt_div_code=J&fid_input_iscd=005930&fid_mkop_cls_code=0

공식 함수의 핵심부입니다. output1은 객체 하나라 [ ]로 감싸 DataFrame을 만들고, output2는 배열 그대로 씁니다.

tr_id = "FHPST01810000"
params = {
    "FID_COND_MRKT_DIV_CODE": fid_cond_mrkt_div_code,
    "FID_INPUT_ISCD": fid_input_iscd,
    "FID_MKOP_CLS_CODE": fid_mkop_cls_code,
}
res = ka._url_fetch(API_URL, tr_id, "", params)
if res.isOK():
    output1_data = pd.DataFrame([res.getBody().output1])
    output2_data = pd.DataFrame(res.getBody().output2)

응답 필드는 chk_exp_price_trend.py의 COLUMN_MAPPING 14개가 전부입니다. 그대로 옮깁니다.

COLUMN_MAPPING = {
    'rprs_mrkt_kor_name': '대표 시장 한글 명',
    'antc_cnpr': '예상 체결가',
    'antc_cntg_vrss_sign': '예상 체결 대비 부호',
    'antc_cntg_vrss': '예상 체결 대비',
    'antc_cntg_prdy_ctrt': '예상 체결 전일 대비율',
    'antc_vol': '예상 거래량',
    'antc_tr_pbmn': '예상 거래대금',
    'stck_bsop_date': '주식 영업 일자',
    'stck_cntg_hour': '주식 체결 시간',
    'stck_prpr': '주식 현재가',
    'prdy_vrss_sign': '전일 대비 부호',
    'prdy_vrss': '전일 대비',
    'prdy_ctrt': '전일 대비율',
    'acml_vol': '누적 거래량'
}
NUMERIC_COLUMNS = []

공식 함수를 거치지 않고 requests로 직접 부르는 코드입니다. 앱키·토큰은 환경변수에서 읽고 코드에 쓰지 않습니다.

import os, requests, pandas as pd
from datetime import datetime
from zoneinfo import ZoneInfo

URL = "https://openapi.koreainvestment.com:9443/uapi/domestic-stock/v1/quotations/exp-price-trend"
headers = {
    "content-type": "application/json; charset=utf-8",
    "authorization": f"Bearer {os.environ['KIS_TOKEN']}",
    "appkey": os.environ["KIS_APPKEY"],
    "appsecret": os.environ["KIS_APPSECRET"],
    "tr_id": "FHPST01810000",
    "custtype": "P",
}

def exp_trend(code, mkop="0"):                  # 0 전체, 4 체결량 0 제외
    r = requests.get(URL, headers=headers, timeout=5, params={
        "FID_COND_MRKT_DIV_CODE": "J",
        "FID_INPUT_ISCD": code,
        "FID_MKOP_CLS_CODE": mkop})
    body = r.json()
    if body.get("rt_cd") != "0":
        raise RuntimeError(f"{body.get('msg_cd')} {body.get('msg1')}")
    head = body.get("output1") or {}
    rows = pd.DataFrame(body.get("output2") or [])
    rows["fetched_at"] = datetime.now(ZoneInfo("Asia/Seoul"))
    return head, rows, r.headers.get("tr_cont")

rt_cd가 "0"이 아닐 때 msg_cd 해석은 KIS API 에러코드를, 장 시작 직전에 종목을 여럿 돌리다 EGW00201(초당 거래건수 초과)이 나면 EGW00201 해결을 보십시오.

3. 함정 5가지

① 최대 30건, 다음 조회 불가 — 흐름 전체가 아니다

공식 설명이 직접 "최대 30건 확인 가능하며, 다음 조회가 불가합니다"라고 적고, 함수도 ka._url_fetch(API_URL, tr_id, "", params)로 tr_cont를 빈 값 고정해 한 번만 부릅니다. 장전 동시호가 30분 전체가 오는지, 최근 30개 시점만 오는지는 행 간격에 달렸는데 행 간격이 명세에 없습니다. 지수 쪽 FHPST01840000은 FID_INPUT_HOUR_1(10초·30초·1분·10분)로 간격을 고르지만 이 API에는 그 파라미터가 없습니다. 처음 붙일 때 아래처럼 간격부터 재십시오.

head, rows, tr_cont = exp_trend("005930")
t = pd.to_datetime(rows["stck_bsop_date"] + rows["stck_cntg_hour"], format="%Y%m%d%H%M%S")
print(len(rows), t.min(), t.max(), t.diff().abs().value_counts().head())
print("tr_cont:", tr_cont)                     # 뒤에 더 있다는 신호가 오는지 기록

30건으로 모자라면 방법은 둘입니다. 주기적으로 불러 stck_cntg_hour 기준으로 중복을 지우며 직접 쌓거나, KIS 웹소켓 실시간 시세에서 H0STANC0(실시간예상체결)를 구독해 저장합니다.

② 장전·장마감을 고르는 코드가 없다

FID_MKOP_CLS_CODE의 값은 0(전체)과 4(체결량 0 제외) 둘뿐입니다. 장전 동시호가만 보고 싶어도 고를 수 없으니, 응답의 stck_cntg_hour로 직접 잘라야 합니다. 장전 동시호가는 통상 08:30~09:00, 종가 단일가는 15:20~15:30이지만, 수능일처럼 개장 시각이 바뀌는 날이 있으니 시각 상수는 코드에 박지 말고 그날 장 운영 시간을 받아 쓰는 게 안전합니다(KRX 휴장일·스케줄 점검).

③ 같은 이름 FID_MKOP_CLS_CODE가 API마다 다른 뜻이다

같은 저장소의 domestic_stock_functions.py에서 이 파라미터를 받는 예상체결 계열 함수 넷을 나란히 놓으면 이렇습니다.

함수 · tr_idFID_MKOP_CLS_CODE 정의
exp_price_trend · FHPST018100000:전체, 4:체결량 0 제외
exp_index_trend · FHPST018400001: 장시작전, 2: 장마감
exp_total_index · FHKUP117500001:장시작전, 2:장마감
exp_trans_updown · FHPST018200000:장전예상 1:장마감예상

지수 API에서 쓰던 "1"(장시작전)을 이 API에 넣으면 정의에 없는 값이고, 순위 API의 "0"(장전예상)은 여기서 '전체'입니다. Postman은 이 파라미터를 "장운영 구분 코드"라 부르지만, examples_llm판 함수 주석은 이름 칸이 비어 있고 값 예시만 있습니다. 파라미터 이름이 아니라 tr_id별 정의를 기준으로 코드를 짜야 합니다.

④ output1과 output2의 필드 경계가 매핑에 없다

COLUMN_MAPPING 14개는 output1·output2 구분 없이 한 딕셔너리에 섞여 있습니다. 이름으로 보면 rprs_mrkt_kor_name·antc_*는 요약, stck_bsop_date·stck_cntg_hour는 시계열 쪽 같지만 어느 키가 어디에 오는지는 저장소에 적혀 있지 않습니다. 특히 시계열 행의 가격이 antc_cnpr(예상 체결가)인지 stck_prpr(주식 현재가)인지가 중요합니다. 형제 API 장마감 예상체결가 FHKST117300C0도 응답 가격이 stck_prpr뿐이었습니다. 첫 실행에서 키 목록을 남겨 확인하십시오.

print(sorted(head.keys()))
print(sorted(rows.columns))
price_col = "antc_cnpr" if "antc_cnpr" in rows.columns else "stck_prpr"

⑤ 숫자 변환은 직접 — NUMERIC_COLUMNS가 비어 있다

공식 확인 스크립트의 NUMERIC_COLUMNS = []라 모든 값이 문자열 그대로 출력됩니다. antc_cntg_vrss_sign·prdy_vrss_sign은 부호 코드이고 antc_cntg_vrss는 대비 값이라, 부호를 어떻게 합쳐 쓰는지 한 번 대조한 뒤 pd.to_numeric(errors="coerce")로 바꾸십시오. 시장코드도 공식 설명은 J 하나라, NXT 예상체결이 필요하면 NXT·KRX 주문 라우팅에 정리한 NXT 전용 TR을 따로 봐야 합니다.

장전 동시호가 (통상 08:30~09:00) 정규장 응답 = 최대 30건 간격에 따라 빠질 수 있는 구간 08:58 호출 → 갭 점검 FHPST01810000 · tr_cont "" · 다음 조회 불가
그림 — 한 번 호출로는 최대 30건. 행 간격을 재 보고, 모자라면 주기 호출로 쌓거나 H0STANC0를 구독한다. 장 운영 시각은 KRX 공지 기준으로 확인.

4. 봇에서 쓰는 법 — 장전 갭 점검

이 API는 "무엇을 살까"보다 "시가 주문을 그대로 내도 되나"를 점검하는 데 맞습니다. 시가에 진입하는 전략이라면 08:58 무렵 대상 종목의 예상체결 흐름을 받아, 전일 대비율이 기준을 넘거나 마지막 몇 행에서 크게 흔들리면 시가 주문을 보류하고 사람에게 알립니다.

def premarket_gap_check(code, max_gap=5.0):
    head, rows, _ = exp_trend(code, mkop="4")          # 체결량 0 행 제외
    rows = rows[rows["stck_cntg_hour"] < "090000"]     # 장전 구간만 (②)
    if rows.empty:
        return {"code": code, "ok": False, "why": "장전 행 없음"}
    last = rows.sort_values("stck_cntg_hour").iloc[-1]
    gap = pd.to_numeric(head.get("antc_cntg_prdy_ctrt"), errors="coerce")
    ok = pd.notna(gap) and abs(gap) <= max_gap
    return {"code": code, "ok": ok, "gap": gap, "at": last["stck_cntg_hour"]}

for code in ["005930", "000660"]:
    res = premarket_gap_check(code)
    if not res["ok"]:
        notify(f"{code} 장전 예상 갭 {res.get('gap')}% — 시가 주문 보류")

위 코드의 antc_cntg_prdy_ctrt가 output1에 있다는 가정은 ④에서 키 목록으로 확인한 뒤에 쓰십시오. 장 시작 직후 급변으로 VI가 걸리는 경우는 VI 발동과 자동매매 봇, 장전 시간외 손절 주문은 KIS 장전 손절에 따로 정리했습니다.

예상체결가는 동시호가 접수 상황에 따라 계속 바뀌는 그 순간의 예상이며 실제 시가와 다를 수 있습니다. 이후 가격 방향을 알려 주지 않으므로 매매 신호가 아니라 점검용 필터로 쓰십시오. 동시호가 시간 등 시장 제도는 한국거래소 공지를, API 명세는 KIS Developers 공식 문서를 확인하십시오(2026-10-11 공식 저장소 기준).

5. 자주 묻는 질문

KIS 예상체결가 추이 API의 tr_id와 URL은 무엇인가요?

tr_id는 FHPST01810000이고 GET /uapi/domestic-stock/v1/quotations/exp-price-trend 로 호출합니다. 필수 파라미터는 FID_COND_MRKT_DIV_CODE(J), FID_INPUT_ISCD(종목코드), FID_MKOP_CLS_CODE(0:전체, 4:체결량 0 제외) 세 개입니다. 공식 저장소 legacy/README.md 기준 모의투자 제공 칸은 비어 있어 실전 앱키로 호출해야 합니다.

예상체결가 추이를 30건 넘게 받을 수 있나요?

공식 설명은 최대 30건 확인 가능하며 다음 조회가 불가하다고 적고 있고, 공식 함수도 tr_cont를 빈 값으로 고정해 한 번만 호출합니다. 더 긴 흐름이 필요하면 주기적으로 호출해 직접 쌓거나, 국내주식 실시간예상체결 웹소켓(H0STANC0)을 구독해 저장해야 합니다.

FID_MKOP_CLS_CODE에 1을 넣으면 장시작전 데이터가 나오나요?

이 API에서는 아닙니다. FHPST01810000의 FID_MKOP_CLS_CODE는 0:전체, 4:체결량 0 제외 두 값만 적혀 있습니다. 1:장시작전, 2:장마감은 예상체결지수 추이(FHPST01840000)와 예상체결 전체지수(FHKUP11750000)의 정의이고, 예상체결 상승/하락상위(FHPST01820000)는 0:장전예상, 1:장마감예상입니다. 장전·장마감 구분은 응답의 stck_cntg_hour로 직접 나눠야 합니다.

장전 예상체결가가 높으면 시가에 매수해도 되나요?

그렇게 단정할 수 없습니다. 예상체결가는 동시호가 접수 상황에 따라 계속 바뀌는 그 순간의 예상이며 실제 시가와 다를 수 있습니다. 자동매매에서는 매수 신호보다 갭이 지나치게 큰 날 시가 주문을 보류하는 점검 필터로 쓰는 것이 일반적입니다.

장전 점검까지 넣은 봇, 만들어 드립니다

전략과 진입 시점만 알려 주시면 됩니다. 24시간 빠른 답변 가능합니다.

무료 상담 시작하기