본문 바로가기
자동매매 일지/시스템 운영

주식 자동매매 직접 만들기 — 실제 사고로 배운 5가지

by 아트스탁 2026. 8. 28.
한눈에
  • 「어디까지 했는지」를 파일에 저장했더니 다른 PC에서 5일 지난 목록으로 주문이 나갔습니다.
  • 막을 것을 목록으로 셌더니 사기로 정한 17개 중 5개가 조용히 빠졌습니다.
  • 비율의 위아래 기준이 달라서 실제 90.5%가 125.7%로 읽혀 주문이 전부 막혔습니다.
  • 다른 폴더의 코드를 빌려 썼더니 그 폴더를 옮길 때마다 죽었습니다 — 세 번이요.
  • 매일 돈다고 믿었던 결산이 13일간 멈춰 있었고, 그중 자산 기록은 영영 못 살렸습니다.

주식 자동매매 프로그램을 직접 만들어 실제 돈으로 돌리고 있습니다. 코딩을 몰랐던 사람이 AI의 도움으로 만든 것이라, 사고를 꽤 냈습니다.

그중 「미리 알았으면 안 겪었을」 다섯 가지를 골랐습니다. 다섯 다 실제로 돈이 걸린 자리에서 터졌고, 다섯 다 같은 형태가 여러 번 재발했습니다.

자동매매가 아니어도 혼자 만든 프로그램을 오래 돌리는 사람이면 그대로 걸릴 자리입니다.

자동매매를 만들며 겪은 사고 다섯 — 상태 파일 저장, 막을 것 열거, 분자와 분모 단위, 남의 폴더 빌려 쓰기

① 「어디까지 했는지」를 파일에 저장하지 마세요

제 프로그램에는 이런 규칙이 있습니다.

어떤 조건이 맞는 날이 오면 「살 종목 목록」이 만들어집니다.
그 목록은 바로 다음 거래일 아침에 딱 한 번만 씁니다. 그날이 지나면 버립니다.

그 목록은 파일 하나에 저장됩니다. 프로그램을 껐다 켜도 남아 있어야 하니까요. 안에는 「언제 만들어진 목록인지」와 「어떤 종목인지」가 들어 있습니다.

{  만들어진 날: 7월 29일,
  종목: [ … ]  }

여기서 문제가 생깁니다. 「이 목록을 이미 썼는지」를 프로그램이 어떻게 아느냐입니다. 프로그램은 아침마다 도는데, 모르면 같은 목록으로 두 번 삽니다.

저는 흔한 방법을 썼습니다. 그 파일 안에 칸을 하나 더 만들어 「썼음」을 적어두는 것입니다.

{  만들어진 날: 7월 29일,
  종목: [ … ],
  쓴 날: 7월 30일  ← 이 칸을 새로 만들었습니다  }

아침에 이 목록을 처음 쓰면 「쓴 날」에 오늘 날짜를 적고, 이미 적혀 있으면 건너뜁니다.

잘 돌았습니다. 그 PC에서는요.

사고는 PC를 하나 더 늘리면서 났습니다

같은 프로그램을 다른 PC에도 깔았습니다. 목록 파일도 함께 옮겨졌습니다.

그런데 「쓴 날」 칸은 비어 있었습니다. 그 칸은 프로그램이 그날 아침에 실제로 돌아야만 찍히는데, 새 PC에서는 아직 한 번도 안 돌았기 때문입니다.

{  만들어진 날: 7월 29일,
  종목: [ … ],
  쓴 날: (없음)  ← 프로그램은 이걸 「아직 안 썼구나」로 읽습니다  }

그래서 7월 29일에 만들어진 목록을 8월 3일 아침에 그대로 실행했습니다. 5일 지난 목록으로 실제 주문이 나갔습니다.

5일이면 시장이 완전히 다릅니다. 8월 3일은 그 목록을 만들 조건이 전혀 아닌 날이었습니다. 프로그램은 그걸 「어제 만든 목록」으로 알고 샀습니다.

여기가 이 사고의 고약한 점입니다. 새로 깐 PC에서는 이게 「가끔」이 아니라 100% 일어납니다. 「쓴 날」이 비어 있는 게 그 PC의 정상 상태이기 때문입니다.
그런데 원래 PC에서는 아무리 테스트해도 재현되지 않습니다 — 거기엔 그 칸이 채워져 있으니까요. 「내 PC에선 잘 되는데」가 이렇게 만들어집니다.

고친 방법은 「저장하지 않는 것」이었습니다

제가 파일에 적어두려던 건 결국 「이 목록이 언제 만들어진 것인가」였습니다. 그런데 그건 저장해야만 알 수 있는 값이 아니었습니다. 조건이 맞은 날이 언제였는지는 날짜별 시세만 보면 다시 계산됩니다.

그래서 파일을 아예 없애고, 아침마다 「이 목록은 어제 만들어진 게 맞나?」를 그 자리에서 다시 계산하게 했습니다.

그러자 문제가 사라진 게 아니라 문제가 생길 자리 자체가 없어졌습니다. 재시작해도, 새 PC에 깔아도, 파일이 지워져도 계산 결과는 같습니다.

저장을 아예 하지 말라는 뜻은 아닙니다. 다만 저장할 것을 만들기 전에 「이건 저장해야만 알 수 있는가, 아니면 다시 계산할 수 있는가」를 한 번 물어보시라는 것입니다.
다시 계산할 수 있는 것을 저장하면 얻는 건 속도뿐이고, 대신 「그 파일이 없을 때」·「그 파일이 틀렸을 때」라는 망가질 경로가 새로 생깁니다.

② 막을 것을 목록으로 세지 마세요

「이런 건 주문 내지 마라」를 만들 때 저는 막을 것들을 나열했습니다.

A인 경우 막는다  ·  B인 경우 막는다  ·  C인 경우 막는다

이 구조의 문제는 단순합니다. 목록에 없는 D가 오면 그냥 통과합니다. 그리고 D는 제가 D를 생각하지 못했기 때문에 목록에 없습니다.

실제로 저는 같은 형태의 사고를 하루에 세 번 냈습니다. 세 번 다 「막을 것을 세는」 구조였고, 세 번 다 제가 안 센 경우가 빠져나갔습니다.

이름으로 걸렀더니 사야 할 것이 막혔습니다

더 나빴던 건 이름으로 거르던 자리였습니다.

사면 안 되는 것들을 「이름에 이런 낱말이 들어 있으면 막는다」로 걸러뒀습니다. 목록에는 「증권」·「인프라」·「액티브」 같은 낱말이 들어 있었습니다. 그때는 그게 맞았습니다.

한참 뒤에 사야 할 대상 17개를 새로 정했습니다. 제가 하나하나 직접 고른 것들입니다. 그런데 그중 다섯 개의 이름에 하필 그 낱말들이 들어 있었습니다.

17개 중 5개가 조용히 빠지고 있었습니다. 에러도 로그도 없었습니다. 「사기로 정한 것을 안 사고 있다」는 걸 알 방법이 없었습니다 — 하나씩 세어 보기 전까지는요.

제가 직접 고른 목록에 넣어둔 것인데도 그랬습니다. 막는 목록이 사는 목록보다 힘이 셌습니다.

고친 방법 — 방향을 뒤집었습니다

⛔ 전  —  막을 것이 A · B · C 중 하나인가?
✅ 후  —  내가 사기로 정한 목록에 들어 있는가?

「이미 시도했나」를 나열하던 ①의 자리도 같은 식으로 「지금이 시도할 수 있는 때인가」로 바꿨습니다.

「막을 것」을 세면 빠뜨린 것이 사고가 되고, 「허용할 것」을 정하면 빠뜨린 것이 그냥 안 됩니다. 방향이 정반대입니다.
뒤쪽은 안 되는 게 바로 눈에 보이지만, 앞쪽은 사고가 나야 압니다. 나열은 빠뜨릴 수 있지만 정의는 빠뜨릴 것이 없습니다.

③ 비율을 계산할 때 위와 아래의 기준을 맞추세요

한도 계산 오류 — 예수금 32만원이 남았는데 실제 90.5%가 125.7%로 읽혀 주문이 전부 차단됨

이건 제가 낸 사고 중 가장 오래 못 찾은 것입니다.

어느 날 조건이 맞아 주문이 나가야 하는 날인데 아무것도 안 샀습니다. 계좌엔 현금이 있었습니다. 로그에는 「한도에 걸림」이라고만 찍혀 있었습니다.

그날 증권계좌 상태가 이랬습니다.

증권계좌 금액
예수금 (당장 쓸 수 있는 현금) 약 32만원
주식 평가액 (지금 팔면 받는 값) 약 313만원
총자산 3,455,690원
참고 — 그 주식들을 산 가격 합계 4,344,270원 (약 122만원 손실 중)

제 프로그램에는 「주식을 총자산보다 많이 담지 마라」는 한도가 걸려 있습니다. 문제는 그 비율을 재는 두 값이 서로 다른 것을 보고 있었다는 점입니다.

자리 쓰던 값
위 (분자) 산 가격 합계 4,344,270원 — 과거의 값이라 안 변합니다
아래 (분모) 오늘 총자산 3,455,690원 — 손실이 나면 줄어듭니다

주식이 122만원 손실 중이었습니다. 그러면 아래는 그만큼 줄어드는데 위는 그대로입니다. 비율이 저절로 부풀어 오릅니다.

프로그램이 한 계산
4,344,270 ÷ 3,455,690 = 125.7%  →  한도 초과, 전부 차단

맞는 계산
3,127,399 ÷ 3,455,690 = 90.5%  →  아직 살 수 있었습니다

코드에는 버그가 없었습니다. 나누기도 맞고 비교도 맞습니다. 틀린 것은 「위와 아래가 같은 기준인가」였고, 그건 코드를 아무리 읽어도 안 보입니다.

계좌에 현금 32만원이 놀고 있는데 프로그램은 「이미 총자산보다 많이 담았다」고 믿고 있었습니다.

고친 것은 한 줄입니다. 위를 「산 가격」에서 「지금 평가액」으로 바꿨습니다. 그러자 위아래가 둘 다 오늘 값이 되어 비율이 제 뜻대로 움직입니다.

나눗셈이 나오면 그 자리에서 한 번 물어보세요. 「위와 아래가 같은 시점, 같은 기준인가?」
하나가 과거값이고 하나가 현재값이면 그 비율은 처음엔 맞다가 시간이 갈수록 저절로 틀려집니다. 그래서 만들 때는 멀쩡해 보이고, 손실이 커지고 나서야 터집니다.

④ 다른 폴더의 코드를 빌려 쓰지 마세요

프로그램을 여러 개 만들다 보면 이미 만들어 둔 코드를 다시 쓰고 싶어집니다. 복사하면 같은 파일이 두 개가 되니 아깝습니다. 그래서 「저쪽 폴더에서 읽어오게」 해둡니다. 파이썬이면 경로를 추가하는 한 줄이면 됩니다.

제 종목 검색 프로그램 하나가 옆 폴더의 코드를 그렇게 빌려 읽고 있었습니다.

어느 날 폴더를 정리하면서 그 옆 폴더를 「일단 보관」 자리로 옮겼습니다. 그러자 그 프로그램이 안 떴습니다. 버튼을 눌러도 아무 일이 안 일어났습니다.

고약한 건 이게 세 번째였다는 점입니다

앞의 두 번은 경로를 고쳐 때웠습니다. 그리고 폴더를 옮길 때마다 또 죽었습니다. 코드를 열어보니 제가 직접 적어둔 주석이 있었습니다.

# 폴더 안으로 옮긴 뒤 두 단계가 모자라 앱이 안 떴다
# 옆 폴더를 보관으로 옮긴 상태 보정

두 번 다 같은 이유로 죽었고, 두 번 다 경로만 고쳤습니다. 그러니 세 번째가 왔습니다.

고친 방법 — 빌리지 말고 가져왔습니다

이번엔 때우지 않고, 그 프로그램이 실제로 무엇을 빌려 쓰는지 전부 따라가 필요한 파일만 자기 폴더로 복사했습니다.

옮긴 것은 파일 10개, 합쳐서 238KB였습니다. 「중복이 아까워서」 빌려 쓴 대가가 세 번의 장애였습니다.

⚠ 옮길 때 새 함정이 하나 열립니다

이름이 같은 파일이 두 곳에 생기면 파이썬은 먼저 찾은 것을 씁니다. 어느 쪽이 먼저인지는 실행 상황에 따라 달라집니다.

제 경우 화면 색을 정하는 파일이 정확히 그랬습니다. 이름은 똑같은데 내용이 전혀 달랐습니다.

같은 이름의 파일 크기
빌려 쓰던 쪽 6.8KB
이 프로그램이 원래 쓰던 것 18.4KB

그냥 옮겼으면 그 화면 색이 통째로 깨졌을 것입니다. 그래서 그 파일만 빼고 옮겼습니다.

파일 몇 개 복사하는 것이 폴더 하나 못 옮기는 것보다 쌉니다. 다만 옮기기 전에 이름이 겹치는 파일이 있는지는 꼭 보세요 — 이름이 같은데 내용이 다른 파일이 제일 위험합니다.

⑤ 「매일 돌고 있다」를 믿지 마세요

매일 장이 끝나면 그날 하루치를 결산하는 프로그램을 만들어 두었습니다. 그날 얼마를 사고팔았는지, 자산이 얼마가 됐는지를 파일에 쌓습니다.

이걸 윈도우 「작업 스케줄러」에 등록해 뒀습니다. 이름은 HYN_DailyReview, 평일 장 마감 뒤에 알아서 도는 것으로요. 제 메모에도 「작업 스케줄러에 등록되어 있다」고 적어뒀습니다.

어느 날 다른 일로 결산 파일을 열어봤습니다.

마지막 기록이 8월 5일이었습니다. 그날은 8월 18일이었습니다.
13일 동안 아무것도 안 쌓이고 있었고, 저는 매일 도는 줄 알고 있었습니다.

확인해 보니 작업 스케줄러에 그 등록이 아예 없었습니다. 결산 프로그램을 부르는 실행 파일도 한 개도 없었습니다. 언제 어떻게 사라졌는지는 지금도 모릅니다.

제 메모에는 있다고 적혀 있었고, 실제로는 없었습니다. 예전엔 분명히 있었는데 어느 시점에 사라졌고, 그 뒤로 아무 일도 일어나지 않았습니다. 에러도 알림도 없었습니다 — 그냥 안 돌았습니다.

다시 걸면서 하나 더 밟았습니다

실행 파일(.bat)에 무슨 일을 하는지 한글로 주석을 적어뒀습니다. 그런데 윈도우가 그 한글을 다른 문자로 읽어 오류를 냈습니다.

손으로 실행하면 화면에 오류가 뜨니 바로 압니다. 그런데 스케줄러가 돌리는 것은 화면이 없습니다. 오류가 나도 아무 데도 안 보입니다. 주석을 영문으로 바꾸고서야 돌았습니다.

되살린 것과 못 되살린 것

빠진 9거래일치를 소급해서 다시 돌렸습니다. 매매 기록은 원본이 따로 남아 있어 전부 복구됐습니다.

그런데 하나는 영영 못 살렸습니다. 날짜별 자산 기록입니다.

증권사가 알려주는 잔고는 「지금 잔고」뿐입니다. 「8월 7일에 내 계좌가 얼마였나」는 물어볼 데가 없습니다.
그날 안 적었으면 그 값은 그냥 사라진 것입니다. 그래서 제 자산 그래프에는 8월 6일부터 17일까지 구멍이 있습니다. 영구히 못 메웁니다.

이건 프로그램의 잘못이 아니라 「그날에만 잡을 수 있는 값이 있다」는 성질입니다. 그래서 더 뼈아팠습니다 — 고쳐도 지나간 13일은 안 돌아옵니다.

「돌고 있다」는 문서나 기억으로 확인하는 게 아니라 결과 파일의 마지막 날짜로 확인하는 것입니다.
자동으로 도는 것은 멈춰도 아무도 안 알려줍니다. 조용히 멈추는 게 기본값입니다. 그리고 그날에만 잡을 수 있는 값이 섞여 있으면 나중에 복구도 안 됩니다.

다섯 가지의 공통점

고친 방법 — 저장 대신 다시 계산, 열거 대신 허용 정의, 믿음 대신 결과 파일 날짜 확인

다시 보니 다섯 다 같은 모양이었습니다.

제가 한 것 벌어진 것
상태를 파일에 저장했다 파일이 없는 PC에서 5일 지난 목록으로 샀다
막을 것을 열거했다 17개 중 5개가 조용히 빠졌다
기준이 다른 값을 나눴다 현금이 있는데 주문이 전부 막혔다
남의 폴더를 빌렸다 폴더를 옮길 때마다 세 번 죽었다
돌고 있다고 믿었다 13일간 멈췄고 일부는 못 살렸다

다섯 다 「제가 조심하면 되는 것」으로 두었던 자리입니다. 그리고 다섯 번 다 제가 조심하지 못했습니다.

공통점이 하나 더 있습니다. 다섯 다 「만들 때는 멀쩡했다」는 것입니다. PC가 하나일 때, 목록이 짧을 때, 손실이 없을 때, 폴더를 안 옮겼을 때, 스케줄러가 살아 있을 때는 전부 제대로 돌았습니다. 조건이 바뀌고 나서야 틀어졌습니다.

그래서 얻은 하나
사람이 지켜야 하는 규칙은 언젠가 깨집니다. 규칙을 지키게 하려면 규칙을 코드 안으로 옮겨야 합니다.
저는 지금 「이렇게 하면 안 된다」는 것들을 프로그램이 스스로 거부하게 만들어 두고 있습니다. 제가 실수로 그렇게 쓰면 에러가 나면서 멈춥니다. 주석에 적어두는 것보다 그게 훨씬 잘 지켜집니다 — ④에서 제가 주석을 두 번이나 적어놓고도 세 번째를 밟은 것이 그 증거입니다.

덧 — 만들기 전이라면

이 다섯 가지는 「어떻게 만드나」가 아니라 「무엇이 나를 물었나」입니다. 처음 만드실 때 참고가 될 순서로 적으면 이렇습니다.

  • 상태 파일을 만들기 전에 — 이 값을 다시 계산할 수는 없는지 먼저 보세요. 계산할 수 있으면 저장하지 마세요.
  • 조건을 쓸 때 — 「막을 것」이 아니라 「허용할 것」으로 쓰세요.
  • 나눗셈을 쓸 때 — 위와 아래가 같은 시점인지 그 자리에서 확인하세요.
  • 코드를 재사용할 때 — 빌리지 말고 가져오세요. 단 이름이 겹치는 파일은 빼고요.
  • 자동으로 돌게 걸었으면 — 결과 파일의 마지막 날짜를 가끔 보세요. 그리고 그날에만 잡히는 값이 있는지도요.

다섯 다 제가 겪고 나서야 알게 된 것입니다. 이 글이 누군가의 13일을 아껴주면 좋겠습니다.

※ 이 글은 개인이 만든 프로그램에서 실제로 난 사고를 정리한 기록입니다. 매매 전략이나 수익률은 담지 않았고, 특정 종목의 매수·매도를 권유하지 않습니다.