"매일 제가 정한 로직대로 사고팔고, 하루 결과를 받아 보고 싶습니다." 의뢰인은 매수와 매도 규칙을 문서로 정리해 오셨고, 맥에서 돌아가야 한다는 조건이 있었습니다.
처음에는 키움을 생각하셨는데 키움 OpenAPI+는 Windows 전용이라, 운영체제를 가리지 않는 한투 KIS로 방향을 정했습니다.
만들면서 고친 것은 대부분 시세를 받아 오는 쪽에서 나왔습니다.
플랫폼
한국투자증권 KIS OpenAPI (국내주식 REST)
구조
4단계 점수 선별 후보 5종목 감시
실행 환경
macOS, Windows 같은 소스로 실행
제작 기간
약 9일
대시보드. 위가 상태와 계좌 요약, 가운데가 그 시각의 후보 5종목, 아래가 보유 종목 (모의투자 모드, 종목과 숫자는 예시값)
01하루의 흐름
단계
내용
후보 선별
5분마다 네 단계를 거쳐 후보를 5종목으로 줄입니다. 1차는 거래량과 거래대금, 체결강도. 2차는 평소 대비 거래량과 과열 여부, 업종 흐름. 3차는 5분봉 차트 상태. 4차는 재무 지표 점수
매수 금지 확인
VI 발동 종목, 이미 보유했거나 주문이 진행 중인 종목, 직전 매수 후 일정 시간이 지나지 않은 종목은 건너뜁니다
진입
후보가 눌렸다가 다시 오르는 조건을 모두 채우면 지정가로 1차 매수. 시장가는 쓰지 않고, 허용 폭보다 비싸게는 사지 않습니다
추가 매수
오르는 쪽으로만 2차, 3차를 삽니다. 손실 중에는 더 사지 않습니다
매도
손절을 가장 먼저 봅니다. 그다음이 단계별 익절이고 남은 수량은 트레일링으로 정리합니다. VWAP과 이동평균선 이탈은 5분봉이 닫힌 뒤에만 판정합니다
자동 중지
일일 손실 한도, 연속 손절, 지수 급락 중 하나라도 걸리면 그날 신규 매수를 멈춥니다
장 마감 후
매매 내역과 종목별 결과를 텔레그램으로 보내고 파일로 남깁니다. 체결과 오류는 생길 때마다 알립니다
4차의 재무 지표 점수는 종목을 거르는 데 씁니다. 거래가 몰려 1차부터 3차까지 통과했더라도 재무 상태가 기준에 못 미치는 종목을 후보에서 빼는 용도로 의뢰인이 설계했습니다.
배점과 통과 기준은 의뢰인의 것이어서 여기에는 싣지 않습니다.
봉이 진행 중일 때 조건을 보면 같은 봉 안에서 신호가 켜졌다 꺼졌다 합니다. 상담 단계에서 이 점을 말씀드렸고, 추세 이탈 판정은 봉 마감 기준으로 정했습니다.
02만들면서 고친 것들
전달하기 전에 장중에 직접 돌려 보며 나온 문제들입니다.
로그에 서버 오류와 재시도가 줄줄이 찍혔습니다. 원인은 분봉 조회였습니다. 장 초반에는 당일 봉만으로 이동평균선을 계산할 수 없어 전일 분봉을 함께 받는데, 이걸 5분마다 수십 종목에 대해 처음부터 다시 받고 있었습니다. 전일 분봉은 하루 동안 바뀌지 않습니다. 종목당 한 번만 받아 저장해 두고 재사용하도록 바꿨고, 당일 봉이 충분히 쌓인 오후에는 전일 조회를 아예 건너뜁니다. 모의투자 서버는 초당 호출 허용량이 실전보다 훨씬 낮아서 호출 속도 제한도 모드에 따라 따로 둡니다.
차트에 MA20과 MA60이 보이지 않는 문제도 있었습니다. 5분봉 60개가 쌓이려면 장 시작 후 다섯 시간이 걸립니다. 그 전에는 선이 없고, 선이 없으면 MA20이 MA60 위에 있어야 한다는 매수 조건도 오전 내내 판정할 수 없습니다. 이동평균선은 전일 봉에서 이어서 계산하고, VWAP은 당일 누적 지표라 날짜가 바뀌는 지점에서 다시 시작하도록 나눴습니다. 차트에는 전일과 당일의 경계선을 그립니다.
처음에는 로그에 1차 통과 22, 2차 통과 9, 3차 통과 0처럼 숫자만 나왔습니다. 이것만으로는 어떤 종목이 왜 떨어졌는지 확인할 방법이 없습니다. 단계마다 통과한 종목명과 점수, 떨어진 종목의 사유를 별도 로그 파일에 남기고, 3차는 분봉 조회에 실패한 것과 점수가 모자란 것을 따로 셉니다. 서버 오류로 후보가 0이 된 것과 조건에 맞는 종목이 정말 없었던 것이 구분됩니다.
필터 결과가 0이면 감시하던 후보까지 같이 사라졌습니다. 일시적인 조회 실패 한 번에 후보 목록이 비면 그 5분 동안은 아무것도 하지 못합니다. 결과가 0일 때는 직전 후보를 정해 둔 시간 동안 유지하고, 그 시간이 지나면 비웁니다. 유지 시간은 설정에서 바꿉니다.
실시간 시세는 WebSocket을 쓰지 않고 몇 초마다 조회해서 받습니다. 감시 대상이 후보 5종목과 보유 종목뿐이라 그걸로 충분하고, 연결이 끊겼을 때 재접속과 재구독을 관리할 일이 없어집니다. 봉 마감 기준으로 판정하는 전략이라 이 선택으로 잃는 것이 거의 없습니다.
프로그램을 켜면 한참 동안 창이 뜨지 않았고, 위쪽 자산과 지수 칸도 비어 있었습니다. 시작할 때 잔고 조회와 4단계 필터를 다 끝낸 뒤에 창을 그리고 있었습니다. 초기화를 뒤로 돌려 창이 먼저 뜨게 하고, 상태 값은 시작 직후 한 번 바로 채웁니다.
API에 없는 값도 있었습니다. 의뢰인의 점수 항목 중 EPS 증가율은 KIS가 주는 재무비율에 들어 있지 않습니다. 같은 응답의 순이익 증가율로 대신하기로 하고 그 사실을 문서에 적어 전달했습니다. 거래량 순위도 등락률 상위 목록을 받아 누적 거래량으로 다시 정렬해 같은 결과를 냅니다.
차트 탭. 이동평균선은 전일에서 이어지고 VWAP은 당일 경계에서 다시 시작합니다 (가격은 합성 데이터)
03왜 안 샀는지, 왜 멈췄는지
조건이 많은 전략을 돌리다 보면 오늘은 왜 한 번도 안 샀는지 궁금해지는 날이 옵니다. 그래서 매매 시그널 탭을 따로 뒀습니다.
후보 종목마다 매수 조건을 순서대로 검사하고, 처음 걸린 조건의 이름과 그때 값을 한 줄로 남깁니다.
VWAP 아래였는지, 눌림 폭이 범위 밖이었는지, 이미 보유 중이었는지를 그 자리에서 확인할 수 있습니다.
매매 시그널 탭. 리스크 중지 상태에서는 모든 후보가 같은 사유로 막힙니다 (예시값)
자동 중지 조건은 이렇습니다. 일일 손실이 한도에 닿으면 신규 매수를 멈추고 보유 종목을 정리합니다. 손절이 연속으로 나오면 신규 매수만 멈춥니다. 코스피나 코스닥이 기준 이상 급락하면 신규 매수를 멈추고 보유 종목을 정리합니다.
한 번 멈추면 그날은 다시 켜지지 않고, 멈춘 사유는 화면 상단과 텔레그램에 표시됩니다.
같은 종목을 두 번 사는 사고는 여러 단계에서 막습니다. 주문이 진행 중인 종목, 미체결이 남은 종목, 이미 보유한 종목, 직전 매수 후 일정 시간이 지나지 않은 종목은 신규 주문 대상에서 빠집니다.
주문을 보낸 뒤 응답이 없으면 일정 시간 뒤 주문 상태를 직접 조회해 진행 중 표시를 정리합니다. 프로그램이 꺼졌다 켜져도 포지션 상태를 파일에서 복원하고 계좌 잔고와 맞춰 봅니다.
04납품물과 기술
Windows 실행 파일, macOS와 Windows 각각의 빌드 스크립트. macOS에서는 스크립트 한 줄로 앱을 만듭니다
소스코드 전체와 사용설명서. 의뢰인이 계약 전에 소스를 받을 수 있는지 물으셨고 함께 전달했습니다
화면이 있는 실행 방식과 화면 없이 로그와 텔레그램만 쓰는 실행 방식. 매매 엔진은 같습니다
대시보드, 매매 시그널, 차트, 일일 리포트, 로그 다섯 탭. 매수 일시중지, 전량 청산, 후보 즉시 갱신 버튼
모의투자와 실전 전환, 실제 주문을 보내지 않는 연습 모드(기본으로 켜짐)
KIS와 통신하지 않고 매수 조건, 매도 우선순위, 자동 중지, 상태 복원을 검사하는 자체 테스트
한국투자증권 KIS OpenAPI (REST)Python 3.11tkinter, matplotlibAPSchedulerTelegram Bot APIPyInstaller
화면을 tkinter로 만든 이유는 파이썬에 기본으로 들어 있어 macOS와 Windows에서 추가 설치 없이 같은 코드가 돌기 때문입니다.
의뢰인의 원래 요청은 맥에서 도는 파이썬 스크립트였고, 화면과 Windows 실행 파일은 그 위에 얹은 것입니다.