연금저축·IRP 자동매매 되나 — KIS 퇴직연금 API 5종
한국투자증권 KIS Developers 가 공개한 API 목록 334개 중 연금계좌 전용은 조회 5종뿐이고 주문 전용 TR 은 없습니다. 계좌를 가리키는 방법은 명시돼 있어서 acnt_prdt_cd 에 개인연금은 22, 퇴직연금은 29 를 넣고, cano 여덟 자리는 주식계좌와 같습니다. 대신 공식 설명에 제약이 세 줄 박혀 있습니다 — 55번 계좌(DC가입자계좌)는 이용 불가, 퇴직연금 잔고조회는 주식·ETF·ETN 만 조회되고 펀드는 불가, 모의투자(vps) 분기에는 연금 상품코드가 아예 없습니다. 여기에 제도 제약이 더 붙어서 연금저축은 개별주식·레버리지·인버스가 막혀 있고 IRP 는 위험자산 70퍼센트 한도가 걸립니다.
이 글에서 다루는 것
- 결론부터 — 조회는 열려 있고 주문은 다른 문제다
- 계좌상품코드가 계좌 종류를 가른다 (
01·03·08·22·29) - KIS 퇴직연금 API 5종 전수표
- 공식 설명에 박혀 있는 제약 세 줄
- 모의투자로 리허설이 안 된다
- API 보다 먼저 걸리는 제도 제약
- 키움증권 쪽은 어떤가
- 그래서 명세서에 뭘 적나
1. 결론부터 — 조회는 열려 있고 주문은 다른 문제다
“연금저축계좌로 적립식 ETF 매수를 자동화할 수 있나요”는 상담에서 꾸준히 들어오는 질문입니다. 답을 먼저 말하면 계좌 상태를 읽는 일은 공식 경로가 있고, 그 계좌로 주문을 내는 일은 별개의 확인이 필요합니다.
근거는 한국투자증권이 공개한 저장소 koreainvestment/open-trading-api 입니다. 이 저장소에는 KIS Developers 의 API 메타데이터를 정리한 파일이 들어 있고, 여기에 실린 항목은 모두 334개입니다. 그중 domestic_stock 의 주문/계좌 범주는 23개인데, 이름에 연금이 들어간 것이 정확히 다섯 개입니다.
# 공개 저장소 MCP/KIS Code Assistant MCP/data.csv 에서 추출
# domestic_stock | 주문/계좌 → 전체 23개
주식주문(현금) 주식주문(신용) 주식주문(정정취소)
주식예약주문 주식예약주문조회 주식예약주문정정취소
주식잔고조회 주식잔고조회_실현손익 매수가능조회
신용매수가능조회 매도가능수량조회 주식통합증거금 현황
주식일별주문체결조회 주식정정취소가능주문조회
기간별계좌권리현황조회 투자계좌자산현황조회
기간별매매손익현황조회 기간별손익일별합산조회
퇴직연금 잔고조회 ← 조회
퇴직연금 체결기준잔고 ← 조회
퇴직연금 미체결내역 ← 조회
퇴직연금 매수가능조회 ← 조회
퇴직연금 예수금조회 ← 조회
다섯 개 모두 조회입니다. tr_id 의 끝자리도 전부 R(조회)이고 U(주문)로 끝나는 연금 TR 은 목록에 없습니다. 주문 쪽은 일반 주식주문(현금) TR 에 계좌상품코드만 연금 값으로 바꿔 보내는 구조이고, 그 요청을 서버가 받아 주는지는 계좌 유형·상품·증권사 정책에 달려 있습니다. 이 글은 공개 문서로 확인되는 범위만 단정하고, 주문 수용 여부는 확인 대상으로 남겨 둡니다.
이 글의 근거 — 모든 코드값·TR·제약 문장은 한국투자증권이 GitHub 에 공개한 open-trading-api 저장소 원문과 키움증권 공개 저장소 Kiwoom-REST-API 원문에서 직접 확인했습니다. 제도(연금저축 매매 대상·IRP 한도)는 별도로 표시했고, 둘 다 변경될 수 있으니 실행 전 공식 안내를 확인하십시오.
2. 계좌상품코드가 계좌 종류를 가른다
KIS API 에서 계좌는 두 조각으로 들어갑니다. cano 가 앞 여덟 자리 종합계좌번호, acnt_prdt_cd 가 뒤 두 자리 계좌상품코드입니다. 이 두 자리가 어떤 성격의 계좌인지를 결정합니다. 공개 저장소의 설정 안내 문서에 값이 그대로 적혀 있습니다.
# MCP AI 도구 연결 방법.md — 공개 저장소 원문
my_prod: "01" # 01(종합계좌), 03(국내선물옵션), 08(해외선물옵션), 22(개인연금), 29(퇴직연금)
# README.md — 같은 저장소
# my_prod: "22" # 개인연금 계좌
# my_prod: "29" # 퇴직연금 계좌
그리고 인증 모듈 kis_auth.py 에는 상품코드별 분기가 코드로 박혀 있습니다. 여기서 한 가지가 드러납니다 — 연금계좌의 앞 여덟 자리는 주식계좌와 같은 값을 씁니다.
# backtester/kis_auth.py — 공개 저장소 원문
if svr == "prod" and product == "01": # 실전투자 주식투자, 위탁계좌, 투자계좌
cfg["my_acct"] = _cfg["my_acct_stock"]
elif svr == "prod" and product == "03": # 실전투자 선물옵션(파생)
cfg["my_acct"] = _cfg["my_acct_future"]
elif svr == "prod" and product == "08": # 실전투자 해외선물옵션(파생)
cfg["my_acct"] = _cfg["my_acct_future"]
elif svr == "prod" and product == "22": # 실전투자 개인연금저축계좌
cfg["my_acct"] = _cfg["my_acct_stock"]
elif svr == "prod" and product == "29": # 실전투자 퇴직연금계좌
cfg["my_acct"] = _cfg["my_acct_stock"]
elif svr == "vps" and product == "01": # 모의투자 주식투자, 위탁계좌, 투자계좌
cfg["my_acct"] = _cfg["my_paper_stock"]
elif svr == "vps" and product == "03": # 모의투자 선물옵션(파생)
cfg["my_acct"] = _cfg["my_paper_future"]
실무적으로 이 말은 연금계좌를 쓰려고 계좌번호를 새로 적을 필요가 없고, 설정에서 상품코드 두 자리만 바꾼다는 뜻입니다. 대신 이 두 자리를 문자열로 다뤄야 합니다. 1 이 아니라 "01", 22(숫자)가 아니라 "22" 입니다. 앞자리 0 이 날아가서 생기는 계좌 오류는 위탁계좌에서도 가장 흔한 입문 실수라 KIS API 계좌번호 오류 — CANO·ACNT_PRDT_CD에서 따로 다뤘습니다.
3. KIS 퇴직연금 API 5종 전수표
다섯 개 API 의 tr_id 와 엔드포인트를 공개 저장소의 예제 코드에서 그대로 뽑았습니다. 사이트에 이 표를 정리해 둔 곳이 없어서 전수로 옮깁니다.
| API | tr_id | 엔드포인트 | 필수 파라미터(계좌 외) |
|---|---|---|---|
| 퇴직연금 잔고조회 | TTTC2208R | /uapi/domestic-stock/v1/trading/pension/inquire-balance | acca_dvsn_cd, inqr_dvsn |
| 퇴직연금 체결기준잔고 | TTTC2202R | /uapi/domestic-stock/v1/trading/pension/inquire-present-balance | user_dvsn_cd |
| 퇴직연금 미체결내역 | TTTC2201R | /uapi/domestic-stock/v1/trading/pension/inquire-daily-ccld | user_dvsn_cd, sll_buy_dvsn_cd, ccld_nccs_dvsn, inqr_dvsn_3 |
| 퇴직연금 매수가능조회 | TTTC0503R | /uapi/domestic-stock/v1/trading/pension/inquire-psbl-order | pdno, acca_dvsn_cd, cma_evlu_amt_icld_yn, ord_unpr, ord_dvsn |
| 퇴직연금 예수금조회 | TTTC0506R | /uapi/domestic-stock/v1/trading/pension/inquire-deposit | acca_dvsn_cd |
여기서 낯선 파라미터가 acca_dvsn_cd 입니다. 공개 저장소의 인자 설명에는 적립금구분코드로 적혀 있고 예시값이 "00" 입니다. 위탁계좌 API 에는 없는 필드라서, 기존 KIS 주식잔고조회 코드를 복사해 오면 이 필드 때문에 그대로는 안 돕니다.
매수가능조회 호출 예시
공개 저장소의 예제 호출을 그대로 옮기면 이런 모양입니다. pdno 에 069500(KODEX 200)이 들어가 있는 것이 눈에 띕니다 — 연금계좌의 주 매매 대상이 ETF 라는 현실이 예제에 그대로 반영돼 있습니다.
# 공개 저장소 예제 — 퇴직연금 매수가능조회 (tr_id: TTTC0503R)
df = pension_inquire_psbl_order(
cano=trenv.my_acct, # 8자리 종합계좌번호
acnt_prdt_cd=trenv.my_prod, # "29" — 퇴직연금
pdno="069500", # 종목코드 (ETF)
acca_dvsn_cd="00", # 적립금구분코드
cma_evlu_amt_icld_yn="Y", # CMA평가금액 포함여부
ord_unpr="30800", # 주문단가
ord_dvsn="00", # 00: 지정가, 01: 시장가
)
print(df)
응답 필드는 다섯 개로 단순합니다. 공개 저장소의 컬럼 매핑 원문입니다.
# 퇴직연금 매수가능조회 응답 컬럼 매핑 (공개 저장소 원문)
{
'ord_psbl_cash' : '주문가능현금',
'ruse_psbl_amt' : '재사용가능금액',
'psbl_qty_calc_unpr' : '가능수량계산단가',
'max_buy_amt' : '최대매수금액',
'max_buy_qty' : '최대매수수량'
}
봇 관점에서 실제로 쓰는 값은 max_buy_qty 하나입니다. 적립식 매수라면 “이번 달 넣을 금액 ÷ 현재가”를 직접 계산하기보다 max_buy_amt 와 max_buy_qty 를 신뢰하는 편이 안전합니다. 위탁계좌에서도 같은 원칙이고, 그 이유는 KIS 매수가능조회 — 주문가능금액을 직접 계산하면 안 되는 이유에 정리해 두었습니다.
잔고조회 응답이 주는 것
# 퇴직연금 잔고조회 응답 컬럼 매핑 일부 (tr_id: TTTC2208R)
{
'prdt_name' : '상품명', 'pdno' : '상품번호',
'item_dvsn_name' : '종목구분명', 'hldg_qty' : '보유수량',
'ord_psbl_qty' : '주문가능수량', 'pchs_avg_pric' : '매입평균가격',
'evlu_amt' : '평가금액', 'evlu_pfls_amt' : '평가손익금액',
'evlu_erng_rt' : '평가수익율', 'dnca_tot_amt' : '예수금총금액',
'tot_evlu_amt' : '총평가금액', 'scts_evlu_amt' : '유가평가금액'
}
item_dvsn_name(종목구분명)이 연금계좌 리밸런싱에서 쓸모가 있습니다. 같은 계좌 안에 성격이 다른 상품이 섞여 있을 때 이 값으로 분류를 잡을 수 있습니다. 비중을 목표대로 되돌리는 계산 자체는 위탁계좌와 같아서 리밸런싱 주기·밴드 백테스트의 판단 기준을 그대로 쓸 수 있습니다.
4. 공식 설명에 박혀 있는 제약 세 줄
다섯 개 API 의 설명문에는 같은 문장이 다섯 번 반복됩니다. 설계 단계에서 이걸 놓치면 개발이 끝난 뒤에 계좌 종류 때문에 못 쓰는 일이 생깁니다.
# 다섯 개 API 설명에 공통으로 붙은 문장 (공개 저장소 원문)
※ 55번 계좌(DC가입자계좌)의 경우 해당 API 이용이 불가합니다.
KIS Developers API의 경우 HTS ID에 반드시 연결되어있어야만 API 신청 및
앱정보 발급이 가능한 서비스로 개발되어서 실물계좌가 아닌 55번 계좌는
API 이용이 불가능한 점 양해 부탁드립니다.
# 퇴직연금 잔고조회에만 추가로 붙은 문장
주식, ETF, ETN만 조회 가능하며 펀드는 조회 불가합니다.
세 줄 요약
55번 계좌(DC가입자계좌)는 API 대상이 아니다 — 회사가 가입해 준 DC 계좌라면 상품코드 확인이 최우선입니다.- 펀드는 잔고조회에 안 나온다 — 연금계좌에 펀드가 섞여 있으면 봇이 보는 총액과 실제 총액이 다릅니다. 비중 계산이 조용히 틀립니다.
- HTS ID 연결이 전제다 — API 신청 자체가 실물계좌·HTS ID 기준입니다.
두 번째 항목이 특히 위험합니다. 펀드가 30퍼센트 들어 있는 IRP 에서 ETF 비중을 60퍼센트로 맞추라고 지시하면, 봇은 펀드를 못 보는 상태에서 분모를 잘못 잡습니다. 잔고를 읽는 쪽이 조용히 틀리면 로그에는 아무 오류도 남지 않습니다. “오류 없이 틀리는” 유형이라 로그만 봐서는 발견되지 않습니다.
5. 모의투자로 리허설이 안 된다
앞서 인용한 kis_auth.py 분기를 다시 보십시오. svr == "vps"(모의투자) 쪽에는 01 과 03 두 개만 있습니다. 22 도 29 도 없습니다.
즉 연금계좌를 대상으로 하는 봇은 “모의투자에서 한 달 돌려 보고 실전 전환”이라는 일반적인 검증 경로를 쓸 수 없습니다. 실무에서 택할 수 있는 우회는 두 갈래입니다.
- 전략·주문 로직은 위탁계좌 모의투자에서 검증한다. 상품코드
01과 모의 도메인으로 주문 흐름·예외 처리·재시도를 전부 태운 뒤, 계좌만 바꿔 끼운다. - 연금계좌에서는 조회 API 로 먼저 산다.
TTTC2208R(잔고)·TTTC0506R(예수금)·TTTC0503R(매수가능)만 며칠 돌려 실제 응답 구조와 값을 확인한 뒤 주문 단계로 넘어간다.
모의투자로 어디까지 검증되고 어디서부터 안 되는지는 위탁계좌에서도 오해가 많은 지점이라 KIS 모의투자로 어디까지 검증되나에 따로 정리했습니다.
6. API 보다 먼저 걸리는 제도 제약
여기까지는 API 이야기였습니다. 그런데 연금계좌에서는 제도 제약이 API 제약보다 먼저 걸립니다. 봇의 종목 유니버스를 짜기 전에 확인해야 할 것들입니다.
| 구분 | 연금저축계좌 | IRP |
|---|---|---|
| 개별 주식 직접 매수 | 불가 | 불가 |
| 국내 상장 ETF | 가능(레버리지·인버스 제외) | 가능(레버리지·인버스 제외) |
| 위험자산 한도 | 별도 한도 없음 | 적립금의 70퍼센트까지 |
| 안전자산 의무 | 없음 | 30퍼센트 |
연금저축계좌는 일반 주식·해외 주식 직접 거래가 되지 않고, 국내 상장 ETF 중 레버리지·인버스형을 제외한 ETF 와 상장리츠·상장인프라펀드 등이 거래 대상입니다. IRP 에는 여기에 위험자산 투자한도 70퍼센트가 더 붙어서 나머지 30퍼센트는 안전자산으로 채워야 합니다. 파생상품 비중이 일정 수준을 넘는 상품은 편입 자체가 제한됩니다.
변경 논의 중인 항목 — IRP·DC 의 위험자산 70퍼센트 한도(안전자산 30퍼센트 규제)는 폐지·완화 논의가 진행 중입니다. 관계 부처 간 입장 차이가 있어 이 글 작성 시점에는 기존 한도가 유효하지만, 봇의 한도 검사 로직을 코드에 상수로 박지 말고 설정 파일로 빼 두는 편이 안전합니다. 현재 기준은 반드시 증권사·감독당국 공식 안내에서 확인하십시오.
봇 설계에 그대로 옮기면 세 줄입니다.
- 유니버스 필터를 먼저 둔다. 종목코드를 넣기 전에 “연금계좌 매매 대상인가”를 통과시킨다. 레버리지·인버스 ETF 는 이름만으로 걸러지지 않는 경우가 있어 상품 분류를 확인해야 합니다.
- IRP 는 한도 검사를 주문 전에 넣는다. 매수 후 위험자산 비중이 70퍼센트를 넘으면 주문을 내지 않는 사전 검사입니다. 계좌 종류에 따라 한도 초과분이 자동으로 처리되지 않는 경우가 있습니다.
- 분모에 펀드를 반영할 방법을 정한다. 앞서 본 대로 잔고조회에 펀드가 안 나옵니다. 펀드가 있는 계좌라면 비중 계산의 기준을 무엇으로 할지 명세에 적어야 합니다.
7. 키움증권 쪽은 어떤가
같은 방법으로 키움증권 공개 저장소 Kiwoom-Securities/Kiwoom-REST-API 전체를 대상으로 문자열을 찾아봤습니다. 결과는 연금 0건, IRP 0건입니다.
# 키움증권 공개 REST API 저장소 전수 검색 결과
검색어: 연금 | IRP
매칭 파일: 0
매칭 라인: 0
# 대비 — 한국투자증권 open-trading-api 저장소
검색어: 연금
매칭 라인: 99 (data.csv · configs/domestic_stock.json · README.md ·
kis_auth.py · examples_llm/domestic_stock/pension_* 5종)
이것이 곧 “키움에서는 연금계좌를 쓸 수 없다”는 뜻은 아닙니다. 공개 문서·예제 수준에서 참고할 근거가 없다는 뜻입니다. 봇을 맡기거나 직접 만들 계획이라면 증권사 선택 단계에서 이 차이가 실질적인 영향을 줍니다 — 같은 기능을 만들어도 한쪽은 공식 예제가 있고 한쪽은 문의부터 시작해야 합니다. 증권사별 API 지원 범위 비교는 국내 증권사 API 비교에, 키움 REST 의 전반적인 구조는 키움 REST API 자동매매 가이드에 있습니다.
8. 그래서 명세서에 뭘 적나
연금계좌 봇을 제작 의뢰한다면, 견적을 받기 전에 아래 다섯 줄을 먼저 확정해 두는 것이 실제로 시간을 아낍니다. 이 다섯 줄이 없으면 개발 도중에 “그 계좌로는 안 된다”가 나옵니다.
연금계좌 봇 — 명세서에 먼저 적을 다섯 줄
- 계좌상품코드가
22(개인연금)인지29(퇴직연금)인지,55(DC가입자)는 아닌지 - 봇이 할 일의 범위 — 조회·리포트만인지, 주문까지인지 (주문은 증권사 확인 필요 항목으로 명시)
- 유니버스 — 매수 대상 ETF 목록과 레버리지·인버스 배제 기준
- 한도 규칙 — IRP 라면 위험자산 비중 상한과 위반 시 동작(주문 보류 / 알림)
- 펀드 보유 여부와, 있을 경우 비중 계산의 분모를 무엇으로 할지
견적 단계에서 무엇을 정해 두면 왕복이 줄어드는지는 자동매매 제작 의뢰 — 견적 전 정할 5가지에, 명세서 자체를 쓰는 방법은 자동매매 명세서 작성 가이드에 있습니다.
마지막으로 한 가지. 연금계좌는 성격상 중도 인출에 불이익이 따르는 장기 자금이고, 매매 빈도를 올리는 전략과는 궁합이 나쁩니다. 실제로 상담에서 연금계좌를 말씀하시는 분들의 목적은 대부분 “매달 정해진 금액을 정해진 비중으로 기계적으로 넣는 것”이었습니다. 그 목적이라면 필요한 것은 복잡한 신호 로직이 아니라 빠뜨리지 않는 실행과 기록입니다. 어느 쪽이 목적인지를 먼저 정하는 편이, API 를 파는 것보다 결과를 크게 바꿉니다.
※ 본 글의 API 코드값·TR·제약 문장은 한국투자증권과 키움증권이 공개한 공식 저장소 원문이며 작성 시점(2026-09-26) 기준입니다. 연금계좌의 매매 가능 상품·위험자산 한도·세제는 제도 변경 대상이고 증권사별로 운영이 다를 수 있으니, 실행 전 반드시 해당 증권사와 감독당국의 공식 안내로 현재 기준을 확인하십시오. 본 글은 수익을 보장하거나 특정 종목·상품을 추천하지 않습니다. 알고랩(퀀트웍스)은 투자자문업·투자일임업을 영위하지 않으며, 본 글은 도구 제작에 관한 기술 정보 제공입니다. 투자 판단과 그 결과의 책임은 투자자 본인에게 있습니다.
계좌 종류만 알려 주셔도 됩니다
상품코드가 22·29·55 중 무엇인지, 원하시는 동작이 조회까지인지 주문까지인지에 따라 가능 범위가 갈립니다. 먼저 그 선부터 그어 드립니다.
24시간 빠른 답변 가능합니다.