한 줄로
자동매매 엔진에서 실시간 구독이 26종목 중 3종목만 붙는 문제를 조사했다. 원인은 우리 코드가 아니라 10/12에 재발급한 KIS 실전 앱키 자체의 제한으로 좁혀졌다. 재시도 누적, 구독 코드 변경, 중복 접속, 다른 프로세스의 키 사용을 하나씩 지웠다. 엔진과 무관한 측정 스크립트로 재도 실전 키는 3/26, 모의 키는 26/26이었다. 확정하려면 KIS 답변이 필요하다.
문서상 한도
KIS 공식 문서에 적힌 한도는 다음과 같다.
- 웹소켓: 앱키당 41건
- REST: 실전 초당 20건
- 토큰 발급: 1분 1회
26종목 구독은 문서상 웹소켓 한도 41건 안에 들어온다. 그러니 3건에서 막히는 것은 문서와 맞지 않는다.
증상
옛 키는 매일 26종목을 구독했다. 마지막 기록은 10/12 08:42다.
10/12 15:33에 새 실전 키로 처음 구독을 시도했다. 이때부터 26건 중 23건이 거절됐다. 실시간 구독 TR H0STCNT0가 3건까지만 받아들여지고, 나머지는 MAX SUBSCRIBE OVER로 돌아왔다.
용의자를 하나씩 지웠다
| 의심 | 반박 근거 |
|---|---|
| 재시도가 쌓여 한도를 넘었다 | 첫 시도부터 23건이 거절됐다. 재시도가 쌓이기 전이다 |
| 구독 코드가 바뀌었다 |
data/websocket_feed.py:214 _on_open은 8/19(PR #62) 이후 바뀌지 않았다 |
| 웹소켓을 여러 번 열었다 | 접속은 autotrading/realtime_engine.py:2573에서 한 번만 만든다. ALREADY IN USE는 0건이다 |
| 엔진 내부의 문제다 | 엔진과 무관한 ws_quota_probe.py로 재도 실전 키 3/26, 모의 키 26/26이다 |
| 다른 프로세스(v2)가 같은 키를 쓴다 | v2 쪽이 새 실전 키를 쓴 기록은 0건이다. 지금 떠 있는 atv2-loop-m3에는 kis-paper.env만 있다 |
가장 강한 근거는 네 번째 줄이다. ws_quota_probe.py는 엔진 코드를 거치지 않는다. 같은 계좌에서 모의 키는 26건을 모두 받았고 실전 키만 3건에서 멈췄다. 그러면 남는 차이는 키뿐이다.
첫 번째 줄도 시점으로 판가름 났다. 재시도가 원인이라면 처음에는 붙다가 나중에 막혀야 한다. 그런데 새 키는 첫 시도부터 23건이 거절됐다.
같이 바로잡은 오해
그동안 “v2가 모의 키를 건드리면 운영 시세가 끊긴다”는 걱정이 있었다. 확인해 보니 v2 루프가 쓰는 모의 키는 1Password KIS_IMITATION_*와 다른 값이었다. 그래서 이 걱정은 생각보다 작다.
REST는 영향이 없다
제한은 웹소켓 구독에만 걸린다. 주문·잔고·현재가처럼 REST로 받는 기능은 정상이다.
조사 중에 새로 보인 것: EGW00201 급증
초당 한도 초과 경고 EGW00201이 크게 늘었다.
| 기간 | 하루 건수 |
|---|---|
| 10/8~11 | 0~1건 |
| 10/12 오후 | 56건 |
| 10/13 | 273건 |
원인이 폴링 모드인지, 새 키의 한도가 낮아서인지는 아직 가리지 못했다. 자동 재시도 덕분에 주문 실패는 없었다.
외부 사례
- GitHub에도 실계좌에서 “3건” 한도를 겪은 사례가 2건 있다.
- 초당 100건으로 늘려 주는 캠페인이 있다. 신청 마감은 10/30이다.
KIS에 보낼 문의
남은 일은 KIS 문의다. 문구는 이렇게 정리했다.
10/12 재발급 실전 앱키가 H0STCNT0를 3건까지만 받고 나머지는 MAX SUBSCRIBE OVER. 같은 계좌 모의 키는 26건 정상. 문서상 41건.
REST 초당 한도가 20건이 맞는지.
보류한 개선
답을 기다리는 동안 할 수 있는 일을 정리해 두었다. 요청이 있을 때 진행한다.
- 거절 시점에 성공한 개수(3)만큼만 실시간으로 받는다. 예를 들어 손절가에 가까운 보유 종목만 받는다.
- 폴링 모드의 REST 호출량을 잰다.
EGW00201급증의 원인을 가리는 데 필요하다. - 30분마다 도는 실시간 재시도를 끈다. 키가 그대로인 동안에는 결과가 바뀌지 않는다.
- 장중에 모의 키로 시세를 받아 보고 실측한다.