"계좌 세 개를 각각 다른 조건식과 다른 규칙으로, 로그인은 한 번만." 2026년 4월에 납품한 키움 OpenAPI+ 프로그램입니다.
슬롯 하나가 계좌 하나·조건식 하나·매매룰 한 벌이고, 세 슬롯이 한 화면에서 따로 돕니다.
납품 뒤 3주 동안 패치를 열여덟 번 냈습니다. 대부분 실계좌에서만 드러나는 키움 API의 성질 때문이었고, 그 목록이 이후 저희 키움 프로젝트의 표준이 됐습니다.
플랫폼
키움증권 OpenAPI+ (OCX, 32bit)
구조
3슬롯 독립 운용 1로그인 · 최대 3계좌
전략
HTS 조건검색 편입 → 분할매수 → 손절·분할익절
제작 기간
약 3주 + 패치 3주
슬롯 A 탭. 왼쪽이 그 슬롯의 계좌·조건식·분할매수 설정, 오른쪽이 매칭 종목과 포지션, 아래가 슬롯별 로그 (계좌·종목은 예시값)
01슬롯 하나의 규칙
단계
내용
편입
HTS에서 만든 조건검색식을 실시간 등록. 슬롯별 매매 시간 창(예: 09:00~15:20) 안에서만
필터
보조지표는 v2부터 조건식에 내장. 재무 필터는 DART OpenAPI 영업이익 증가율
분할매수
1차 즉시, 2차·3차는 직전 차수 대비 ±N% 트리거(양수 불타기 / 음수 물타기). 단위는 만원 또는 주
체결통보는 계좌번호(FID 9201)로 슬롯에 라우팅합니다. 같은 종목이 두 슬롯 조건에 동시에 걸리면 각자 자기 계좌에서 사고, 한쪽 매도가 다른 쪽에 영향을 주지 않습니다.
v1의 단일 슬롯 설정은 v2 슬롯 배열로 자동 마이그레이션됩니다.
02납품 후 3주, 패치 18회
의뢰인 보고로 시작된 것과 로그 분석에서 나온 것을 섞어 적습니다.
"오이솔루션 −3% 떨어졌는데 2차 매수가 안 됨" — 주문을 보낸 뒤 체결통보가 와야 "진행 중" 표시를 지우는데, VI 발동·단일가·키움의 조용한 거부에서는 통보가 아예 안 옵니다. 그러면 그 종목 분할매수가 영원히 막힙니다. 타임스탬프를 같이 두고 15초 지나면 자동 해제하는 정리 루틴을 넣었습니다. 주문 후 통보에 의존하는 상태는 전부 이 패턴을 씁니다.
"17주씩 두 번 체결됐는데 DB에 68주" — 키움 체결통보의 체결수량은 증분이 아니라 누적치입니다. 17 → 34로 오는 걸 17 + 34로 더했습니다. 직전 누적치를 저장하고 차이만 반영하도록 고쳤습니다.
"오전에 판 종목을 오후에 다시 샀는데 손절이 이상하게 잡힘" — 전량 매도로 수량이 0이 돼도 이전 매수 내역이 남아 있었고, 재매수 때 그 위에 새 내역이 얹혀 평단이 두 사이클의 가중평균이 됐습니다. 수량 0 매도 시 즉시 리셋, 매수 시 잔존 내역 감지 리셋, 잔고 동기화 시 리셋 — 세 군데서 지킵니다.
잔고 조회가 체결통보보다 늦다 — 매수 직후 잔고를 동기화하면 새 종목이 응답에 아직 없어 수량이 0으로 초기화되고, 이후 손절·익절 평가가 안 됩니다. 진행 중 주문 종목은 0 처리에서 보호합니다. 잔고 응답을 절대 기준으로 삼지 않습니다.
"켜자마자 어제 들고 있던 종목을 또 샀음" — 잔고 동기화가 끝나기 전에 조건 매칭이 들어와 빈 포지션북을 보고 신규 매수로 판단. DB 복원 + "잔고 동기화 성공 후 90초 이내"가 아니면 매수 보류.
스케줄러 스레드에서 OCX를 부르면 응답이 안 온다 — 키움 OCX는 메인 스레드 전용(STA). 스케줄러는 시간 트리거만 하고 실행은 시그널로 메인 스레드에 넘깁니다. 체결통보 핸들러 안에서 processEvents()를 부르면 다른 통보가 재진입해 상태가 꼬이는 것도 같은 계열입니다.
"2차 매수를 자동으로 안 했는데 됐다" — 코드 문제가 아니었습니다. 의뢰인이 같은 계좌에서 HTS로 직접 산 걸 프로그램이 체결통보로 받아 2/3단계로 표시한 것. 자동매매가 보낸 주문만 식별되는 요청명 패턴을 두어 로그로 바로 가릴 수 있게 했습니다.
정지 중인 슬롯은 설정이 열립니다. 실행 중엔 잠깁니다
03납품물 · 기술
Windows 32bit 실행 파일(PyInstaller) — 영웅문 OpenAPI+ 상시 로그인 필요, 1계정당 1프로세스