KIS 예상체결가 추이 FHPST01810000 — 30건 함정
한국투자증권 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:장마감"이라 그대로 옮기면 틀립니다. 공식 저장소 기준 모의투자 칸은 비어 있어 실전 앱키 전용입니다.
목차
- 스펙 한 장
- 요청·응답 실물
- 함정 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] — 설명문 표기는 "예상체결지수 추이" |
| 메서드 · URL | GET /uapi/domestic-stock/v1/quotations/exp-price-trend |
| tr_id | FHPST01810000 (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_id | FID_MKOP_CLS_CODE 정의 |
|---|---|
exp_price_trend · FHPST01810000 | 0:전체, 4:체결량 0 제외 |
exp_index_trend · FHPST01840000 | 1: 장시작전, 2: 장마감 |
exp_total_index · FHKUP11750000 | 1:장시작전, 2:장마감 |
exp_trans_updown · FHPST01820000 | 0:장전예상 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을 따로 봐야 합니다.
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로 직접 나눠야 합니다.
장전 예상체결가가 높으면 시가에 매수해도 되나요?
그렇게 단정할 수 없습니다. 예상체결가는 동시호가 접수 상황에 따라 계속 바뀌는 그 순간의 예상이며 실제 시가와 다를 수 있습니다. 자동매매에서는 매수 신호보다 갭이 지나치게 큰 날 시가 주문을 보류하는 점검 필터로 쓰는 것이 일반적입니다.