AlgoLab Blog · 한국투자증권 계좌 · 2026

KIS API 매도가능수량조회 TTTC8408R — 보유 100주인데 70주만 팔리는 이유

한국투자증권 · 주문 실무 2026-10-01 · 알고랩 AlgoLab
한 줄 요약

한국투자증권 KIS API에서 매도 주문 수량은 보유수량 hldg_qty가 아니라 주문가능수량 ord_psbl_qty로 정해야 합니다. 한 종목만 확인할 때는 매도가능수량조회 TTTC8408R(GET /uapi/domestic-stock/v1/trading/inquire-psbl-sell, 입력은 CANO·ACNT_PRDT_CD·PDNO 3개)를 쓰면 됩니다. 단 이 API는 모의투자에서 제공되지 않으므로, 모의 계좌에서는 주식잔고조회 TTTC8434R(모의 VTTC8434R) 응답 output1의 ord_psbl_qty를 대신 씁니다.

이 글은 KIS API 잔고조회 — 50건에서 잘리는 연속조회 해결의 매도 수량 편입니다. 잔고조회 글이 "보유 종목 목록을 끝까지 받는 법"이었다면, 여기서는 그중 한 종목을 지금 몇 주 팔 수 있나 한 가지만 다룹니다. 근거는 한국투자증권 공식 GitHub 저장소 koreainvestment/open-trading-api의 examples_llm/domestic_stock/inquire_psbl_sell와 legacy/README.md의 API 제공 목록입니다.

1. TTTC8408R 스펙 — 입력 3개

항목값
API명매도가능수량조회 [국내주식-165]
메서드 · URLGET /uapi/domestic-stock/v1/trading/inquire-psbl-sell
tr_idTTTC8408R (실전만 — 공식 예제에 모의 분기 없음)
쿼리 파라미터CANO(종합계좌번호 8자리) · ACNT_PRDT_CD(계좌상품코드, 보통 01) · PDNO(보유종목 코드 6자리)
모의투자미제공 — legacy/README.md 제공 목록에서 모의 칸 공란

연속조회 키(CTX_AREA_FK100 같은 것)가 없습니다. 종목 하나를 넣고 한 행을 받는 API라서 잔고조회처럼 50건 페이지 처리를 신경 쓸 필요가 없습니다. 계좌번호 두 필드를 나누는 법은 CANO·ACNT_PRDT_CD 정리에 있습니다.

import os, requests

BASE = "https://openapi.koreainvestment.com:9443"   # 실전 도메인
H = {
    "content-type": "application/json; charset=utf-8",
    "authorization": f"Bearer {access_token}",
    "appkey": os.environ["KIS_APPKEY"],
    "appsecret": os.environ["KIS_APPSECRET"],
    "tr_id": "TTTC8408R",
    "custtype": "P",
}

def sellable_qty(pdno: str) -> int:
    r = requests.get(BASE + "/uapi/domestic-stock/v1/trading/inquire-psbl-sell",
                     headers=H, timeout=10,
                     params={"CANO": CANO, "ACNT_PRDT_CD": "01", "PDNO": pdno}).json()
    if r["rt_cd"] != "0":
        raise RuntimeError(f'{r["msg_cd"]} {r["msg1"]}')
    out = r["output"]
    out = out[0] if isinstance(out, list) else out   # 공식 예제도 dict/list 둘 다 처리
    return int(out["ord_psbl_qty"])

access_token 발급과 만료 처리는 KIS 접근토큰 만료·재발급을 보십시오. rt_cd가 "0"이 아니면 msg_cd·msg1을 그대로 로그에 남기는 것이 원칙입니다(KIS API 에러코드 허브).

2. 응답 필드 12개 — 봐야 할 건 ord_psbl_qty 하나

공식 테스트 코드 chk_inquire_psbl_sell.py의 COLUMN_MAPPING 기준 응답 필드입니다.

필드공식 한글명봇에서의 쓰임
pdno상품번호요청 종목 확인
buy_qty / sll_qty매수수량 / 매도수량당일 체결 확인용
cblc_qty잔고수량보유 기준
nsvg_qty비저축수량공식 설명이 더 없음 — 판단에 쓰지 말 것
ord_psbl_qty주문가능수량매도 주문 수량의 상한
pchs_avg_pric / pchs_amt매입평균가격 / 매입금액손익 계산
now_pric / evlu_amt현재가 / 평가금액표시용
evlu_pfls_amt / evlu_pfls_rt평가손익금액 / 평가손익율익절·손절 판단

응답은 이런 모양입니다(필드는 공식 매핑 기준, 값은 설명용 가상 값). 모든 숫자가 문자열로 오므로 int() 변환을 빼먹으면 "70" > "100" 같은 문자열 비교 버그가 납니다.

{
  "rt_cd": "0",
  "msg_cd": "...",
  "msg1": "...",
  "output": {
    "pdno": "005930",
    "buy_qty": "0",
    "sll_qty": "0",
    "cblc_qty": "100",
    "nsvg_qty": "...",
    "ord_psbl_qty": "70",
    "pchs_avg_pric": "...",
    "now_pric": "...",
    "evlu_pfls_rt": "..."
  }
}

3. 보유 100주인데 왜 70주만 팔 수 있나

가장 흔한 원인은 이미 걸어 둔 미체결 매도주문입니다. 증권사는 접수된 매도주문 수량만큼을 묶어 두므로, 잔고수량이 100주여도 30주짜리 지정가 매도가 걸려 있으면 새로 낼 수 있는 건 70주입니다. 봇이 hldg_qty(또는 cblc_qty)로 "전량 매도"를 내면 이 30주가 겹쳐 주문이 거부됩니다.

잔고수량 cblc_qty / hldg_qty = 100주 ord_psbl_qty 70주 — 새 매도 가능 미체결 매도 30주 X 잔고수량 100으로 매도 → 30주 초과 → 주문 거부 O ord_psbl_qty 70으로 매도 → 접수 전량 청산이 목적이면: 미체결 30주를 먼저 취소(TTTC0013U) → 다시 조회 → 100주 매도
잔고수량과 주문가능수량이 갈리는 가장 흔한 경우 — 미체결 매도주문이 수량을 묶는다

그 밖에도 권리 발생 등으로 매도가 막히는 경우가 있습니다. 공식 저장소의 예약주문 설명문은 거부 사유로 "매도가능수량 부족"을 따로 적고 있고, 해외 예약주문 설명에는 "주권변경 등 권리발생으로 인한 주문불가사유"도 나옵니다. 어떤 경우든 봇이 할 일은 같습니다 — 팔기 직전에 ord_psbl_qty를 다시 읽는다.

전량 청산이 목적이라면 순서는 미체결 조회 → 정정취소 TTTC0013U로 취소 → 매도가능수량 재조회 → 매도입니다. 정정취소의 원주문번호·가능수량 처리는 KIS API 정정·취소에 있습니다.

4. 모의투자에서는 — TTTC8434R로 대체

공식 저장소 legacy/README.md와 legacy/postman/README.md의 제공 목록에서 매도가능수량조회는 실전투자만 ⭕이고 모의투자 칸이 비어 있습니다. Postman 샘플도 실전용 J_매도가능수량조회만 있습니다. 반면 주식잔고조회는 모의투자 ⭕이고, 그 응답 output1에 같은 이름의 ord_psbl_qty(주문가능수량)가 들어 있습니다.

def sellable_qty_any(pdno: str, env: str) -> int:
    if env == "real":
        return sellable_qty(pdno)                  # TTTC8408R — 종목 1개, 1회 호출
    # 모의: 잔고조회(VTTC8434R) 전체를 받아 해당 종목 행만 찾는다
    for row in inquire_balance_all(env="demo"):     # 연속조회까지 끝낸 output1 목록
        if row["pdno"] == pdno:
            return int(row["ord_psbl_qty"])
    return 0

모의투자로 매도 로직을 검증한 뒤 실전으로 넘어갈 때 경로가 바뀌는 지점이 여기입니다. 모의에서 잘 돌던 봇이 실전 첫날 다른 API를 타게 되므로, 실전 전환 체크리스트에 한 줄 넣어 두십시오(KIS 모의투자로 어디까지 검증되나). 실전에서도 TTTC8434R로 통일할 수는 있지만, 보유 종목이 많으면 잔고 전체를 페이지 단위로 받아야 하므로 종목 1개 확인에는 TTTC8408R이 호출 수가 적습니다(호출 제한은 EGW00201 초당 제한).

5. 매도 주문으로 잇기 — TTTC0011U

def sell_all(pdno: str, env: str = "real"):
    qty = sellable_qty_any(pdno, env)
    if qty <= 0:
        log.info("skip %s: 주문가능수량 0", pdno)
        return None
    return order_cash(env_dv=env, ord_dv="sell",           # 실전 TTTC0011U / 모의 VTTC0011U
                      cano=CANO, acnt_prdt_cd="01", pdno=pdno,
                      ord_dvsn="01",                        # 시장가
                      ord_qty=str(qty),                     # 문자열로 전달
                      ord_unpr="0",
                      excg_id_dvsn_cd="KRX",
                      sll_type="01")                        # 01 일반매도

공식 order_cash() 설명문 그대로 ORD_QTY·ORD_UNPR는 문자열로 넘기고, 매도 시 sll_type은 01(일반매도)·02(임의매매)·05(대차매도) 중에서 고릅니다. 현재 매도 tr_id가 구 TTTC0801U가 아니라 TTTC0011U인 이유와 EXCG_ID_DVSN_CD 필수화는 KIS 주문 tr_id 신·구 대조에 정리돼 있습니다. 매수 쪽 짝은 매수가능조회 TTTC8908R입니다.

매도 직후 바로 재조회하면 숫자가 안 맞을 수 있습니다. 주문 접수와 체결 반영 사이에는 시차가 있으므로, 매도를 낸 직후 ord_psbl_qty를 읽어 "남은 수량을 또 매도"하는 루프를 만들면 같은 수량을 두 번 내는 사고가 납니다. 한 번 매도한 종목은 체결통보나 체결조회로 결과를 확인한 뒤 다음 판단을 하십시오.

자주 묻는 것

KIS API 매도가능수량조회 tr_id는 무엇인가요?

TTTC8408R입니다. GET /uapi/domestic-stock/v1/trading/inquire-psbl-sell에 CANO·ACNT_PRDT_CD·PDNO 세 가지를 넣어 호출하고, 응답의 ord_psbl_qty(주문가능수량)가 지금 매도할 수 있는 수량입니다.

모의투자에서 TTTC8408R을 쓸 수 있나요?

공식 저장소의 API 제공 목록에서 매도가능수량조회는 모의투자 제공 칸이 비어 있어 실전 전용입니다. 모의 계좌에서는 주식잔고조회(VTTC8434R) 응답 output1의 ord_psbl_qty를 대신 사용하십시오.

보유수량(hldg_qty)으로 매도하면 안 되나요?

미체결 매도주문이 걸려 있으면 그 수량만큼 주문가능수량이 줄어들어, 보유수량 전체로 낸 매도는 거부될 수 있습니다. 매도 수량은 항상 직전에 조회한 ord_psbl_qty로 정하십시오.

잔고조회 TTTC8434R과 매도가능수량조회 중 무엇을 써야 하나요?

둘 다 ord_psbl_qty를 줍니다. 종목 하나만 확인할 때는 TTTC8408R이 호출 한 번으로 끝나고, 모의투자이거나 전 종목을 한꺼번에 볼 때는 TTTC8434R(연속조회 포함)을 씁니다.

고지. 이 글은 기술 자료이며 특정 종목·전략을 권유하지 않습니다. tr_id·필드·제공 여부는 한국투자증권 공식 GitHub 저장소(koreainvestment/open-trading-api)를 2026-10-01 기준으로 대조했습니다. 증권사 API 스펙은 예고 없이 바뀔 수 있으니 실제 주문 전 KIS Developers 포털 공지를 다시 확인하십시오.

매도 로직이 가끔 거부되나요?

KIS 봇의 매도 수량 계산·미체결 정리·실전 전환 경로를 점검해 드립니다. 24시간 빠른 답변 가능합니다.

상담 문의하기