- 「9종 중 9종 잡아냄」이 거짓이었습니다. 검사가 이미 깨져 있어서 아무것도 안 심어도 「잡음」이 나왔습니다.
- 한 군데인지 확인하려고 셌더니 2가 나왔습니다.
if를 세는데elif가 같이 세어졌고, 다음엔 제가 쓴 주석이 세어졌습니다. - 27개 검사가 전부 통과했는데, 안전장치가 있는 그 줄을 아예 안 태우고 있었습니다.
- 토요일 아침에 검사 50개 중 8개만 돌고 멈췄습니다. 코드는 멀쩡했고 검사가 「오늘」에 기대고 있었습니다.
- 거짓 실패는 빨갛게 떠서 바로 알지만, 거짓 통과는 초록 글씨로 조용히 지나갑니다.
주식 자동매매 프로그램을 직접 만들어 실제 돈으로 돌리고 있습니다. 돈이 걸려 있으니 검사를 꽤 많이 만들어 뒀습니다. 고칠 때마다 전부 돌려서 「다 통과」를 확인하고 넘어갑니다.
그런데 그 「다 통과」가 저를 여러 번 속였습니다.
이 글은 버그를 못 잡은 이야기가 아닙니다. 검사가 「잡았다」고 말했는데 사실은 안 잡고 있던 네 가지입니다.

① 「9종 중 9종 잡아냄」이 거짓말이었습니다

먼저 검사를 검사하는 방법부터 말씀드려야 합니다.
검사를 아무리 많이 만들어도 그게 실제로 버그를 잡는지는 알 수 없습니다. 지금 버그가 없으니 다 통과할 뿐이니까요.
그래서 이렇게 확인합니다. 코드에 일부러 결함을 심고, 검사가 실패하는지 봅니다. 안 실패하면 그 검사는 있으나 마나입니다.
정렬 순서를 거꾸로 뒤집는다 → 검사가 실패해야 정상
「이 시간엔 주문 금지」 가드를 통째로 지운다 → 검사가 실패해야 정상
이런 결함 9종을 심었더니 9종 다 검사가 실패했습니다. 만점입니다. 저는 「내 검사는 튼튼하구나」라고 생각했습니다.
그런데 만점이 나온 이유가 달랐습니다
그날 저는 한도 계산을 고치고 있었습니다. 「주식을 총자산보다 많이 담지 마라」를 재는 부분인데, 위아래 기준이 달라서 실제 90.5%가 125.7%로 읽히던 그 사고를 고치는 중이었습니다. (지난 글 ③에 자세히 적었습니다)
고치면서 한도를 재는 함수를 새로 하나 만들었습니다. 그리고 검사용 가짜 프로그램에는 그 함수를 안 붙였습니다. 현재가를 담아두는 자리도 안 만들었습니다.
그러니 결함을 심기 전부터 검사가 이미 죽고 있었습니다. 없는 함수를 부르니 당연합니다.
하마터면 그대로 넘어갈 뻔했습니다. 9/9는 제가 보고 싶었던 숫자였으니까요.
고친 방법 — 아무것도 안 심고 한 번 돌립니다
② 통과했을 때만 결함을 하나씩 심는다
①에서 실패하면 프로그램이 아예 멈추게 해뒀습니다. 「9종 다 잡음」이라는 거짓 만점을 낼 기회를 없앤 것입니다.
⚠ 여기서 하지 말아야 할 유혹이 하나 있습니다
가짜 프로그램이 죽지 않게 하려면 「그 함수가 없으면 대충 넘어가라」고 한 줄 넣으면 됩니다. 그러면 에러가 안 납니다.
② 한 군데인지 셌더니 2가 나왔습니다
제 프로그램에는 「위기 상황이면 새로 사지 마라」는 잠금이 하나 있습니다. 이 잠금을 여러 군데서 켰다 껐다 하면 위험합니다. 한 군데에서만 다뤄야 합니다.
그래서 「이걸 만지는 자리가 몇 군데인가」를 검사로 세게 해뒀습니다. 가장 쉬운 방법은 파일에서 그 글자를 찾는 것입니다.
그런데 이게 계속 틀렸습니다.
| 세려던 것 | 같이 세어진 것 |
|---|---|
if 이 잠금 이 몇 군데? |
고치면서 새로 넣은 elif 이 잠금글자가 안에 들어 있어서 1이어야 할 것이 2 |
| 그럼 줄 전체로 세자 | 줄 끝에 붙인 주석과 함수 설명글 코드가 아닌데 「사용처」로 잡힘 |
제가 쓴 주석이 저를 속였습니다
다른 검사에서는 「현재가를 조회하는 함수를 어디서 부르나」를 확인하려 했습니다. 조회가 판정보다 앞에 오면 안 되는 자리였습니다.
그런데 저는 바로 그 위 주석에 그 함수 이름을 적어뒀습니다. 「여기서는 이 함수를 부르지 않는다」는 설명이었습니다.
비슷하게 「이 잠금을 켜고 끄는 스위치가 몇 개인가」를 셀 때는, 스위치를 만드는 줄까지 같이 세어졌습니다. 만드는 것과 실제로 값을 읽는 것은 다른데도요.
반대로 놓치기도 합니다
이번엔 못 세는 쪽입니다. 화면에 상자를 그리는 함수를 어디서 부르는지 찾는 검사였는데, 「괄호 열고 첫 값이 이것」을 전제로 찾게 해뒀습니다.
그런데 줄이 길어서 여러 줄에 걸쳐 쓴 호출들이 있었습니다.
고친 방법 — 글자가 아니라 구조로 셉니다
파이썬에는 코드를 「글자」가 아니라 「구조」로 읽어주는 기능이 있습니다. 그걸 쓰면 주석과 설명글은 애초에 안 들어옵니다. 코드가 아니니까요.
✅ 후 — 실행되는 자리에 이게 몇 번 있나?
판정 자체도 바꿨습니다. 「몇 개냐」가 아니라 「어느 함수가 이걸 만지느냐」로요. 지금은 딱 네 함수만 만지는 게 맞고, 다른 데서 만지면 그때 걸립니다.
elif 하나 때문에 1이 2가 된 것처럼요. 「어디서 만지나」는 뜻이 분명해서 안 흔들립니다.③ 27개가 전부 통과했는데, 그 줄을 안 태웠습니다
검사를 돌리려면 진짜 프로그램 대신 쓸 가짜가 필요합니다. 진짜를 돌리면 실제 주문이 나가니까요.
어느 날 저는 이미 산 종목을 조건이 맞으면 한 번 더 사는 기능을 넣었습니다. 돈이 한 번 더 나가는 기능이라 검사를 27개나 만들었습니다. 전부 통과했습니다.
그런데 가짜에 그 정보가 아예 없었습니다
이 기능은 주문을 내기 전에 두 가지를 봐야 합니다.
| 봐야 하는 것 | 안 보면 벌어지는 일 |
|---|---|
| 지금 프로그램이 돌고 있나 | 「중지」를 눌러도 주문이 나갑니다 |
| 사용자가 예약을 걸어뒀나 | 사용자가 따로 쓰려고 잡아둔 현금을 가져다 씁니다 |
그런데 가짜 프로그램에는 그 두 가지가 아예 안 만들어져 있었습니다.
「중지」는 뭔가 잘못됐다고 느낄 때 누르는 버튼입니다. 하필 그때 주문이 나가면 최악입니다.
제대로 고친 뒤 다시 돌리니 검사가 「그런 거 없는데?」 하고 죽었습니다. 그게 안전장치가 실제로 돈다는 증거였습니다. 가짜에 그 두 가지를 만들어 넣고서야 진짜 검사가 됐습니다.
같은 함정을 반대 방향으로도 밟았습니다
다른 검사에서는 어떤 설정값을 0으로 바꿔놓고 「이러면 어떻게 되나」를 보려 했습니다. 그런데 제가 값을 넣은 자리와 프로그램이 값을 읽는 자리가 서로 달랐습니다.
제 프로그램에는 설정값을 담는 자리가 두 갈래입니다. 어떤 부분은 화면의 입력칸을 직접 읽고, 어떤 부분은 따로 복사해둔 목록을 읽습니다. 저는 복사본에 0을 넣었는데, 그 코드는 화면 쪽을 읽고 있었습니다.
지금은 무대를 세운 직후에 「무대가 정말 섰나」를 그 자리에서 되물어봅니다. 값을 넣었으면 프로그램이 읽는 쪽에서 그 값이 나오는지 확인하고, 안 나오면 거기서 멈춥니다.
④ 토요일 아침에 50개 중 8개만 돌고 멈췄습니다
어느 토요일에 검사를 돌렸더니 네 뭉치가 무더기로 깨졌습니다. 그중 하나는 검사 50개 중 8개만 돌고 나머지는 시작도 못 한 채 죽었습니다.
코드를 한참 들여다봤습니다. 아무 문제가 없었습니다.
원인은 「오늘이 토요일」이었습니다
며칠 전 저는 거래 시간을 늘리는 작업을 했습니다. 대체거래소가 생겨서 아침 8시부터 밤 8시까지 주문을 낼 수 있게 된 부분입니다.
그 검사들은 「지금 시각」을 그대로 갖다 쓰고 있었습니다. 오늘 날짜에 시각만 바꿔서 무대를 세우는 방식이었습니다.
그런데 거래 시간을 판정하는 코드는 주말이면 무조건 닫습니다. 당연합니다 — 장이 안 열리니까요.
고친 방법 — 무대를 제가 정합니다
「지금」을 쓰지 않고 특정 평일 하루를 못 박았습니다. 검사 안에서는 언제 돌리든 그날입니다.
그리고 하나 더 만들었습니다. 「지금」에 기대는 검사가 또 있는지 전부 훑는 검사입니다. 다음 주말에 같은 일이 나면 그게 먼저 잡습니다.
네 가지의 공통점

| 검사가 말한 것 | 실제로 벌어진 것 |
|---|---|
| 「9종 중 9종 잡았다」 | 검사가 고장 나서 전부 자동으로 잡힘 처리 |
| 「두 군데에 있다」 | elif와 주석을 셌다 — 실제로는 한 군데 |
| 「27개 전부 통과」 | 안전장치가 있는 그 줄을 아예 안 태웠다 |
| 「50개 중 8개만 돌았다」 | 코드는 멀쩡하고 그날이 토요일이었다 |
네 가지가 두 방향으로 나뉩니다. ①②③은 「실패해야 하는데 통과」였고, ④는 「통과해야 하는데 실패」였습니다.
덧 — 검사를 만들 때 물어볼 네 가지
- 멀쩡할 때 통과하나? — 「몇 개 잡았나」보다 이게 먼저입니다.
- 내가 세는 게 코드인가, 글자인가? — 주석은 실행되지 않습니다.
- 그 줄을 실제로 태웠나? — 통과했다고 지나간 게 아닙니다.
- 무대를 내가 정했나? — 「지금」에 기대면 언젠가 깨집니다.
넷 다 제가 만든 검사가 저를 속인 뒤에야 알게 된 것들입니다. 검사를 늘리는 것보다 검사를 의심하는 게 먼저였습니다.
※ 이 글은 개인이 만든 프로그램에서 실제로 겪은 일을 정리한 기록입니다. 매매 전략이나 수익률은 담지 않았고, 특정 종목의 매수·매도를 권유하지 않습니다.
'자동매매 일지 > 시스템 운영' 카테고리의 다른 글
| 주식 자동매매 직접 만들기 — 실제 사고로 배운 5가지 (0) | 2026.08.28 |
|---|---|
| 검사 프로그램이 진짜 보유 내역을 덮어썼습니다 — 12개는 지켰는데 하나가 (0) | 2026.08.27 |
| 하네스가 무엇인가요 — 말에 채우는 마구에서 클로드 코드까지 (0) | 2026.08.27 |
| 동시호가에 판 돈은 그날 못 씁니다 — 파는 건 장중에, 사는 건 마지막에 (0) | 2026.08.26 |
| SOR은 시장가 주문을 받지 않습니다 — NXT 대체거래소에서 막힌 네 가지 (0) | 2026.08.25 |