프로젝트를 시작한 이유
최근 주식 이야기가 주변에서 자주 들리기 시작했다. 뉴스에서도, 커뮤니티에서도, 점심시간 대화에서도 주식과 투자 이야기는 빠지지 않았다. 처음에는 그냥 지나가는 이슈라고 생각했지만, 어느 순간 “나도 용돈에서 조금씩 모아 굴려보면 어떨까”라는 생각이 들었다.
큰돈을 벌겠다는 거창한 목표는 아니었다. 오히려 반대에 가까웠다. 작은 금액으로 시작해서 시장이 어떻게 움직이는지 직접 보고, 내가 어떤 기준으로 사고파는지 기록해보고 싶었다. 막연히 감으로 매수하고 매도하는 것보다, 관심 종목을 정리하고, 조건을 세우고, 결과를 다시 확인하는 작은 도구가 있으면 공부가 더 잘 될 것 같았다.
그렇게 시작한 프로젝트가 QuantPilot이다.
이름처럼 처음부터 완전 자동 투자 시스템을 만들겠다는 의미는 아니었다. 사용자가 정한 기준을 바탕으로 관심 종목을 추적하고, 단기 매수 시뮬레이션을 해보고, 나중에는 AI 판단을 보조적으로 붙여보는 실험 프로젝트에 가깝다.
진행하면서 먼저 고려한 현실적인 제약
이번 프로젝트에서 가장 먼저 봐야 했던 것은 기술보다 시간이었다.
엄연히 직장이 있고, 회사에서는 회사 일을 해야 한다. 그래서 개발은 집에서만 진행하기로 했다. 대신 실제 시장 데이터나 매수/매도 흐름을 확인하는 테스트는 점심시간에 약 30분 정도만 볼 수 있었다.
이 제약은 생각보다 프로젝트 방향에 큰 영향을 줬다.
실시간으로 오래 붙어서 확인해야 하는 기능은 당장 맞지 않았다. 복잡한 매매 전략을 여러 개 동시에 돌리거나, 장중 내내 모니터링해야 하는 구조도 부담이 컸다. 그래서 첫 번째 단계에서는 기능을 넓히기보다 짧은 시간 안에 상태를 확인하고 판단할 수 있는 구조를 우선하기로 했다.
결론은 다음과 같았다.
- 개발과 테스트 시간을 분리한다.
- 장중 테스트는 점심시간에 확인 가능한 범위로 제한한다.
- 실제 매수/매도보다 시뮬레이션을 먼저 만든다.
- 자동 판단은 보조 기능으로 두고, 초기에는 사람이 확인할 수 있게 한다.
- 실패하거나 판단이 애매한 상황을 로그와 통계로 남긴다.
이 결정 덕분에 프로젝트가 조금 현실적으로 보이기 시작했다.
개발 언어와 프레임워크 선택
QuantPilot은 백엔드 중심 프로젝트로 시작했다. 화면보다 중요한 것은 시장 데이터 수집, 조건 판단, KIS Open API 연동, 결과 기록이었다. 그래서 빠르게 API를 만들고, 작은 단위로 테스트하면서, 나중에 대시보드까지 같이 붙일 수 있는 언어와 프레임워크가 필요했다.
이번에는 Python + FastAPI 조합을 기준으로 잡았다.
Python을 선택한 이유는 몇 가지가 있었다.
- 주식 데이터 수집, 시뮬레이션, AI 판단 실험을 빠르게 붙이기 좋다.
httpx,pydantic,SQLAlchemy,pytest같은 도구로 API 연동과 검증을 작게 반복할 수 있다.- FastAPI를 쓰면 REST API와 Swagger 문서가 자연스럽게 생겨 테스트하기 편하다.
- 나중에 Ollama나 OpenAI 같은 AI 판단 엔진을 붙일 때 Python 생태계가 부담이 적다.
- Docker Compose로 FastAPI 서버와 MySQL을 같이 띄우기 쉽다.
주식 매매 로직은 결국 작은 조건들이 계속 쌓이는 구조다. 현재가, 등락률, 거래량, 보유 여부, 주문 가능 금액, 매수 후 경과 시간, 손절/익절 기준 같은 값들이 계속 들어온다. 그래서 pydantic 모델로 요청과 응답을 정리하고, DB에는 판단 기록과 주문 관련 이벤트를 남기는 방향이 맞다고 봤다.
FastAPI를 선택한 것도 같은 이유였다. 처음부터 큰 프론트엔드 앱을 만들기보다, /dashboard, /watchlist-page, /statistics 같은 내부 운영 화면을 서버에서 바로 제공하고, 필요한 기능은 API로 먼저 검증하는 편이 개인 프로젝트에는 더 현실적이었다.
저장소는 MySQL 8.4를 기준으로 두었다. 주문, 체결, 시세 로그, AI 판단 기록은 나중에 다시 봐야 의미가 있으므로 파일보다 DB에 쌓는 쪽이 맞다고 판단했다.
어떤 기능을 만들 것인가
초기 기능은 욕심을 줄여서 정했다.
가장 먼저 필요한 것은 관심 종목 관리였다. 직접 종목을 등록하고, 현재가와 기본 지표를 확인하고, 단타 후보로 볼지 말지를 정리할 수 있어야 했다. 여기서 바로 자동 매매로 넘어가면 위험하다고 봤다. 종목을 왜 봤는지, 어떤 조건에서 관심이 생겼는지 기록이 남아야 나중에 판단을 복기할 수 있다.
두 번째는 단타 매수 시뮬레이션이다. 실제 돈이 들어가기 전에 조건이 맞았을 때 매수했다고 가정하고, 이후 가격 변화에 따라 익절/손절 조건이 어떻게 작동하는지 확인하는 기능이다.
세 번째는 실제 주문 API 연동이다. 다만 이 단계에서도 자동 판단은 바로 붙이지 않기로 했다. 주문 가능 여부, 계좌 잔고, 체결 결과, 실패 응답을 먼저 확인해야 했다. 매매 기능은 성공보다 실패 처리가 더 중요하다. 주문이 거절됐을 때, 부분 체결됐을 때, API 응답이 늦을 때 시스템이 어떤 상태로 남는지 봐야 했다.
초기 화면은 다음 정도로 정의했다.
- 대시보드
/dashboard: KIS 잠금 상태, 현재가, 계좌 잔고, 안전 설정 확인 - 관심목록
/watchlist-page: 종목 등록, 활성 여부, 메모, 현재가 조회 - 단타 시뮬레이션: AI 없이 사용자가 정한 매수 범위와 익절/손절률로 가상 매매 실행
- 설정: KIS/OpenAI/OpenDART 키 암호화 저장, 운용금액, 손절/익절 기준 관리
- 통계
/statistics: 이후 시뮬레이션과 실제 주문 결과를 월별로 확인
API 연동에서 생각한 것
주식 API 연동은 단순히 현재가를 가져오는 작업이 아니었다.
시세 조회와 주문은 성격이 다르다. 시세 조회는 실패해도 다시 조회하면 되지만, 주문은 한 번 나가면 실제 돈과 연결된다. 그래서 처음부터 조회 API와 주문 API를 분리해서 생각했다.
특히 주문 API는 다음 기준을 세웠다.
- 기본값은 항상
dry_run과kill_switch=true로 둔다. - KIS API 키는
.env에 평문 저장하지 않고, 대시보드에서 입력받아 암호화해 MySQL에 저장한다. - 서버가 떠도 사용자가 마스터 비밀번호로 잠금 해제하기 전에는 KIS API를 사용할 수 없게 한다.
- 실제 주문은 설정에서 명시적으로 켜고,
SEND_REAL_ORDER확인 문구까지 통과해야 한다. - 주문 전에는 금액과 수량을 다시 계산한다.
- 응답 원문과 내부 판단 결과를 모두 기록한다.
- 실패 응답도 정상적인 이벤트로 저장한다.
이 구조를 선택한 이유는 단순하다. 투자 도구에서 “아마 됐겠지”는 위험하다. 시스템이 무엇을 보고 어떤 판단을 했는지 남겨야 나중에 고칠 수 있다.
처음 시작하며 정리한 결론
QuantPilot의 첫 단계는 자동으로 돈을 벌어주는 시스템이 아니다.
오히려 내가 어떤 종목에 관심을 가졌고, 어떤 기준으로 단타를 생각했고, 실제 시장에서는 그 판단이 어떻게 흘러갔는지 확인하는 기록 도구에 가깝다. 자동화는 그다음 문제다.
이번 단계의 결론은 이렇게 정리했다.
- 개발은 집에서, 장중 테스트는 점심시간 약 30분 안에서 진행한다.
- Python + FastAPI로 백엔드와 내부 대시보드를 먼저 만든다.
- 관심목록, 단타 시뮬레이터, KIS 키 관리, 안전 설정을 초기 범위로 둔다.
- AI 판단은 처음부터 넣지 않고, 사람이 세운 조건과 결과를 먼저 기록한다.
- 실제 매수/매도보다 시뮬레이션과 로그를 우선한다.
“주식 자동매매를 만든다는 말은 멋있지만, 첫 번째 목표는 자동화가 아니라 판단을 기록하는 일이었다.”
시리즈
- QuantPilot 프로젝트를 시작하며 (현재 글)
- 단타 매수/매도 시뮬레이션과 AI 모델 검토
- AI 자동 판단 테스트와 현재 시스템 정리