코스피200 자동매매를 처음부터 정직하게
1장. 데이터부터, 정직하게
왜 이 글을 쓰는가
인터넷에는 자동매매로 돈을 벌었다는 이야기가 넘친다. 대부분은 아름다운 그래프 한 장으로 시작한다. 우상향하는 수익 곡선, "연 수익률 40%", "샤프 지수 2.0". 그리고 그 끝엔 대개 강의나 프로그램을 파는 링크가 있다.
나는 그 그래프들이 거짓이라고 말하려는 게 아니다. 더 나쁘다. 그것들은 대부분 진짜다. 진짜로 과거 데이터에서 그렇게 나온다. 문제는 그 그래프가 보여주는 게 '미래에 벌 돈'이 아니라 '과거에 벌었을 돈'이라는 것, 그리고 그 둘 사이에는 건너기 힘든 강이 있다는 것이다.
이 강의 이름이 백테스트다. 과거 데이터에 전략을 대보고 "이랬으면 이만큼 벌었다"를 계산하는 것.
비유하자면 이렇다. 로또 지난 회차 당첨 번호를 모두 안다고 하자. 그 번호들을 보고 "이 번호를 샀으면 20억을 벌었다"고 말하는 건 쉽다. 하지만 그게 다음 주 당첨을 보장하는가? 백테스트의 함정이 정확히 이것이다. 과거를 아는 상태에서 과거에 맞는 답을 만드는 건 누구나 할 수 있다.
나는 이 프로젝트로 그 강을 실제로 건너보려 한다. 그리고 건너는 모든 과정을 — 성공이든 실패든 — 공개하려 한다. 예쁜 결과만 보여주는 게 아니라, 데이터를 어디서 어떻게 구했는지, 무엇이 잘못됐고 어떻게 고쳤는지, 그리고 최종적으로 이 시장에서 정말로 돈을 벌 수 있는지를.
솔직히 말하면 나는 하나의 믿음을 갖고 있다. 이전의 다른 실험에서, 나는 단순한 전략 대부분이 시장에서 살아남지 못한다는 것을, 그리고 살아남는 것이 있다면 그것은 추세를 끝까지 따라가는 인내에서 나온다는 것을 보았다. 공포를 이기고 버티는 쪽이 이긴다는 믿음.
하지만 이 프로젝트에서 나는 그 믿음조차 아직 증명하지 않았다. 그래서 나는 나 자신의 믿음을 의심하는 것부터 시작한다. 만약 검증 끝에 내 믿음이 틀렸다고 나오면, 나는 그것을 쓸 것이다. 반대로 아무도 예상 못 한 새로운 기회가 우연히 발견된다면, 그것 또한 엄청난 수확으로 기록할 것이다.
결론은 정해두지 않았다. 그것이 이 글이 저 수많은 '후기'들과 다른 유일한 점이다.
무엇을 거래할 것인가 — 코스피200
첫 번째 결정은 무대를 고르는 일이었다. 나는 코스피200을 골랐다. 한국을 대표하는 200개 종목. 삼성전자부터 시작해 우리가 이름을 아는 대부분의 큰 회사들이 여기 있다.
이유는 단순하다. 개별 종목 몇 개로 실험하면 요행이 끼어들기 쉽다. 어쩌다 대박 난 한 종목이 전체 결과를 만들어낼 수 있다.
비유하자면, 동전 던지기 실력을 평가하는데 딱 세 번만 던져보는 것과 같다. 운 좋게 세 번 다 앞면이 나올 수 있다. 200개라는 넓은 판에서 실험해야, 특정 종목의 운이 아니라 '전략 자체'가 작동하는지 볼 수 있다.
데이터란 무엇인가 — 매일 쌓이는 여섯 개의 숫자
그렇다면 '주가 데이터'란 정확히 무엇일까. 거창하게 들리지만, 실은 단순하다. 하나의 종목은 거래가 있는 매일, 여섯 개의 숫자를 남긴다.

시가는 그날 장이 열릴 때의 첫 거래 가격, 종가는 장이 닫힐 때의 마지막 가격이다. 고가와 저가는 그날 하루 동안 가장 높았던 값과 가장 낮았던 값. 거래량은 그날 사고팔린 주식의 수, 거래대금은 그 거래의 총 금액이다.
비유하자면 하루의 주가는 마라톤 한 경기와 같다. 시가는 출발선에서의 위치, 종가는 결승선에서의 위치. 고가와 저가는 경기 중 가장 앞섰던 순간과 가장 뒤처졌던 순간이다. 그리고 거래량은 그 경기를 지켜본 관중의 수라고 할 수 있다.
이 여섯 숫자 중에서 가장 중요한 것은 종가다. 하루의 최종 성적표이자, 대부분의 분석이 기준으로 삼는 값이기 때문이다. 우리가 앞으로 "이 종목이 올랐다, 내렸다"를 말할 때, 그 기준은 거의 언제나 종가다.
이 여섯 개의 숫자가, 하나의 종목에 대해, 매 거래일마다 쌓인다. 그것이 우리가 다루는 데이터의 정체다.
그리고 이 숫자들을 시간 순서로 이어 그리면, 우리에게 익숙한 그림이 된다.

이것을 캔들차트(봉차트)라 부른다. 막대 하나가 하루다. 빨간 봉은 어제보다 오른 날, 파란 봉은 내린 날. 봉의 몸통은 시가와 종가 사이를, 위아래로 뻗은 가는 선(심지)은 그날의 고가와 저가를 나타낸다. 아래쪽 막대들은 그날의 거래량이다.
이 한 장의 그림 안에 이미 시장의 성격이 담겨 있다. 가격은 매끄럽게 오르지 않는다. 오르다가 급락하고, 바닥을 다지다가 튀어 오른다. 위 삼성전자 차트만 봐도, 상승할 땐 빨간 봉이 이어지다가 최근 급락 구간엔 파란 봉이 몰려 있는 것이 보인다. 저 출렁임 하나하나가, 실제로 돈을 넣은 사람들에게는 환희와 공포였을 것이다. 백테스트의 매끄러운 수익 곡선이 감추는 것이 바로 이 실시간의 요동이다. 곡선 위에서는 20% 하락이 점 하나지만, 그 안에 있는 사람에게는 잠 못 드는 밤들이다.
어떻게 모으는가 — 실제 코드
말로만 설명하면 막연하니, 실제로 데이터를 받아온 코드를 공개한다. 생각보다 단순하다. 세 단계다.
1단계, 인증. 증권사 서버에 "나는 허가받은 사용자"임을 증명하고 출입증(토큰)을 받는다.

은행 창구에 가서 신분증을 보여주고 번호표를 받는 것과 같다. 이 번호표(토큰)는 하루 동안만 유효하다.
2단계, 요청. 종목코드와 기간을 지정해서 "이 종목의 이 기간 시세를 주세요"라고 서버에 요청한다.

삼성전자의 종목코드는 005930이다. 이 번호와 시작일·종료일을 함께 보내면, 서버가 그 기간의 매일치 시세를 돌려준다.
3단계, 저장. 받은 데이터를 표 형태로 정리해 파일로 저장한다.

한 종목이 한 파일이 된다. 이 과정을 코스피200 전 종목, 즉 200번 반복하면 수집이 끝난다. 프로그램이 알아서 반복하니, 사람은 시작 버튼만 누르면 된다.
이게 전부다. 화려한 알고리즘도, 인공지능도 없다. 그냥 서버에 정중히 요청하고, 받은 것을 차곡차곡 쌓는 일이다.
어디서 얻는가 — 데이터의 출처와 환경
투명하게 밝힌다. 이 프로젝트의 모든 것은 재현 가능해야 하고, 그러려면 출처와 도구를 감추면 안 된다.
데이터 출처는 한국투자증권 KIS Open API다. 증권사가 공식 제공하는 프로그래밍 인터페이스로, 국내 상장 종목의 과거 일별 시세를 받을 수 있다. 놀랍게도 1995년까지 거슬러 올라가는 데이터를 제공한다.
종목 목록의 출처도 같은 증권사가 제공하는 종목 정보 파일이다. 로그인 없이 받을 수 있는 이 파일 안에, 각 종목이 코스피200에 속하는지가 표시되어 있었다. 나는 이것으로 '오늘의 코스피200' 200종목을 확정했다.
이 파일이 제대로 읽혔는지 어떻게 확신할까? 영리한 확인법이 있었다. 파일이 표시한 코스피200이 정확히 200개, 코스피100이 100개, 코스피50이 50개였고, 이 셋이 서로 부분집합 관계로 맞아떨어졌다.
비유하자면, 어떤 명단을 받았는데 그 안에 "상위 200명", "상위 100명", "상위 50명" 표시가 각각 정확한 인원수로 들어있고, 50명이 100명 안에, 100명이 200명 안에 빠짐없이 포함되어 있다면 — 이 명단은 신뢰할 만하다. 우연으로는 이런 정합성이 나오지 않는다.
실험 환경은 Google Colab Pro와 Google Drive다. 클라우드에서 돌아가는 파이썬 노트북 환경이고, 수집한 데이터는 모두 Google Drive에 저장했다. 개인 PC가 아니라 클라우드를 쓴 이유는, 어디서 접속하든 같은 환경에서 작업을 이어갈 수 있고, 데이터가 한곳에 안전하게 쌓이기 때문이다.
이 조합은 특별할 것이 없다. 오히려 그게 핵심이다. 누구나 접근할 수 있는 무료에 가까운 도구들로, 나는 이 실험을 한다. 수백만 원짜리 데이터 단말기나 전용 서버가 있어야 퀀트를 할 수 있다는 것도, 어떤 의미에서는 신화다.
한편, 데이터에는 이 여섯 숫자 외에 몇 가지 항목이 더 딸려 온다. 전부 정리하면 이렇다.

'stck_clpr' 같은 영어 이름은 증권사 API가 데이터를 돌려줄 때 쓰는 실제 항목명이다. 낯설어 보이지만 뜻은 단순하다 — 'stck'은 stock(주식), 'clpr'은 close price(종가)의 줄임말이다. 이 이름들을 그대로 밝히는 이유는, 누구든 같은 데이터를 같은 방식으로 받아 이 실험을 재현할 수 있도록 하기 위해서다. 특히 맨 아래 '락 구분'을 기억해 두자 — 배당락 같은 이벤트를 표시하는 이 항목이, 다음 장에서 중요한 단서가 된다.
언제부터 — 2015년 1월이라는 선
데이터는 1995년까지 있었지만, 나는 2015년 1월 1일을 실험의 출발선으로 정했다. 30년치를 다 쓰지 않은 데는 이유가 있다.
여기서 자동매매의 가장 은밀한 함정을 만난다. "오늘의 코스피200"과 "10년 전의 코스피200"은 다른 종목 집합이다. 회사는 흥하고 망하고, 지수에 들어오고 나간다. 만약 내가 '오늘 코스피200에 속한 200종목'을 골라 먼 과거부터 실험한다면, 나는 무의식중에 반칙을 하는 셈이 된다 — 이 회사들이 오랜 세월을 살아남아 오늘도 대표 기업으로 남을 것을 이미 알고 고르는 것이기 때문이다.
이것을 생존편향이라 부른다.
비유하자면, 백전노장 사업가 200명을 모아놓고 "봐라, 사업은 이렇게 성공하는 것이다"라고 말하는 것과 같다. 하지만 그 자리에는 실패해서 사라진 수천 명이 빠져 있다. 살아남은 승자만 보고 "성공 확률이 높다"고 결론 내리는 것 — 그것이 생존편향이다. 저 수많은 '연 40% 후기'의 숨은 비밀이 바로 이것이다.
이 함정의 크기를 실제로 그려보면 이렇다.

오늘의 코스피200 중에서, 2015년에 이미 존재했던 회사는 200개 중 155개였다. 나머지 45개는 그 이후에 하나씩 상장했다. 만약 더 먼 과거로 가면 이 숫자는 급격히 줄어든다 — 1995년까지 가면 겨우 68개, 즉 30년을 버틴 '초생존자'들만 남는다. 그들만으로 실험하면 결과는 비현실적으로 장밋빛이 된다.
2015년을 기준으로 삼으니 그 시점의 유효 종목이 155개, 전체의 77%까지 올라온다. 여전히 완벽하진 않지만, 68개(34%)로 시작하는 것과는 비교할 수 없이 건강하다.
두 번째 이유도 있다. 한국 주식시장의 하루 가격 변동 제한폭이 2015년 중반에 ±15%에서 ±30%로 바뀌었다. 시장의 성질 자체가 그 무렵 달라진 것이다. 너무 먼 과거는 '다른 시장'이라, 지금과 같은 규칙으로 실험하기 어렵다.
30년의 데이터를 손에 쥐고도 11년만 쓰기로 한 이 결정에, 이 프로젝트의 태도가 담겨 있다. 데이터가 많다고 다 쓰는 게 아니라, 믿을 수 있는 만큼만 쓴다.
그래서, 모았다
결정을 마치고 나니 나머지는 노동이었다. 200개 종목 각각에 대해, 2015년 1월부터 오늘까지의 매일의 가격을 하나씩 받아 모았다.

200개 종목, 2,832거래일. 이것을 곱하면 50만 개가 넘는 행이 되고, 각 행에 담긴 일곱 개의 지표까지 세면 약 350만 개의 숫자가 된다. 오늘 코스피200에 속한 200개 회사의, 지난 11년 반의 발자취가 이제 내 손에 있다.
(2015년 1월 2일이 실제 시작인 이유는 1월 1일이 신정 휴장이기 때문이다. 200개 종목 모두 마지막 거래일이 정확히 일치했고, 빠진 종목은 없었다.)
이것이 이 프로젝트의 첫 번째 벽돌이다. 화려한 전략도, 인공지능도 아니다. 그냥 믿을 수 있는 데이터.
비유하자면, 요리를 시작하기 전 장을 보는 일과 같다. 아무리 뛰어난 요리사라도 상한 재료로는 좋은 요리를 만들 수 없다. 저 '연 40% 후기'들이 보여주지 않는 것이 바로 이 장보기 단계다 — 그들의 재료가 신선한지, 어떤 함정 위에 놓여 있는지.
다음 장에서
데이터를 모았다고 끝이 아니다. 다음 장에서 나는 이 데이터를 의심할 것이다. 사 온 재료가 정말 멀쩡한지, 눈에 보이지 않는 오염은 없는지 하나하나 검사한다. 그리고 놀랍게도, 겉보기에 멀쩡한 데이터 속에서 몇 가지 함정을 실제로 찾아낸다 — 배당이 빠진 가격, 하루에 900% 뛴 유령 같은 기록, 그리고 한 종목 코드 안에 전혀 다른 두 회사가 섞여 있는 경우까지.
그 다음에야, 비로소 이 프로젝트의 진짜 질문을 던질 수 있다.
이 시장에, 정말로 돈 벌 방법이 남아있는가? 그리고 그것은, 내가 믿는 대로 '버티는 자'의 것인가?
나는 답을 안다고 믿는다. 하지만 믿음과 증명은 다르다. 그 차이를, 앞으로 이 자리에서 하나씩 확인해 나가겠다.
(2장에서 계속)
'주식 자동매매' 카테고리의 다른 글
| 백테스트는 거짓말을 한다 ② 깨끗해 보이는 데이터를 의심하다 (0) | 2026.07.23 |
|---|