- 장 마지막 10분(15:20~15:30)은 주문을 모으기만 합니다. 체결은 15:30에 한꺼번에 일어납니다.
- 그 시간에 팔면 돈이 15:30에 들어오는데, 그때는 장이 끝납니다. 그날 그 돈으로 살 수가 없습니다.
- 제 프로그램은 「팔면 돈이 생긴다」고 계산하고 있었습니다. 그래서 돈이 있는 줄 알고 사려다 못 샀습니다.
- 답은 순서였습니다 — 파는 건 장중에 먼저, 사는 건 마지막에.
- 덤으로 배운 것: 거래정지된 종목은 날짜가 멈춰 있습니다. 한 종목만 보고 「오늘이 며칠인지」를 정하면 안 됩니다.
자동매매를 돌리다 보면 이해가 안 되는 날이 있습니다. 계좌에 돈이 있는데 아무것도 안 사는 날입니다.
로그를 보면 프로그램은 사려고 했습니다. 돈이 있다고 계산했고, 주문을 내려고 했습니다. 그런데 안 샀습니다.
원인은 제 코드가 아니라 시장이 돌아가는 방식이었습니다.
동시호가란 — 마지막 10분은 주문만 모읍니다

장은 3시 30분에 끝납니다. 그런데 마지막 10분은 다르게 돌아갑니다.
| 시간 | 무슨 일이 |
|---|---|
| ~ 15:20 | 주문이 들어오는 대로 바로바로 체결됩니다 |
| 15:20 ~ 15:30 | 주문을 받아만 둡니다. 아무것도 체결되지 않습니다 |
| 15:30 | 모인 주문을 하나의 값으로 한꺼번에 체결합니다 — 이게 종가입니다 |
이걸 동시호가라고 부릅니다. 마지막 순간에 몇 주 던져서 종가를 흔드는 걸 막으려고 만든 장치입니다. 아침에 장이 열릴 때도 같은 방식으로 시가를 정합니다.
여기까지는 아는 분이 많습니다. 문제는 그다음입니다.
판 돈이 들어오는 순간, 장이 끝나 있습니다
동시호가에는 파는 주문도 사는 주문도 똑같이 15:30에 체결됩니다. 여기서 함정이 생깁니다.
사람이 손으로 매매할 때는 잘 안 부딪힙니다. 팔고 나서 「어, 돈이 아직 없네」 하고 다음 날 사면 되니까요.
그런데 프로그램은 계산부터 합니다. 「이걸 팔면 얼마가 생기니까 저걸 살 수 있겠다」고 판단하고 주문을 냅니다. 그 계산이 시각을 안 보고 금액만 봤습니다.
시뮬레이션은 이걸 모릅니다

이 문제가 고약한 이유가 있습니다. 과거 데이터로 미리 돌려보는 시뮬레이션에서는 이게 안 보입니다.
시뮬레이션은 하루치 자료를 한 덩어리로 다룹니다. 「이날 팔았다」와 「이날 샀다」 사이에 시간이 없습니다. 그래서 판 돈이 그 자리에서 생기고, 그 돈으로 바로 삽니다.
실제로는 그 사이에 「장이 끝난다」는 사건이 끼어 있습니다.
얼마나 차이가 나는지 세어봤습니다. 시뮬레이션이 「샀다」고 기록한 매수 중에서 여섯 건에 한 건꼴로 실제로는 살 수 없는 것이었습니다. 돈이 제때 없어서입니다.
답은 순서였습니다
고친 방법은 새 기능이 아니라 순서였습니다.
어차피 오늘 팔기로 되어 있는 것이라면, 동시호가까지 기다리지 않고 장중에 미리 팝니다. 그러면 그 돈이 장중에 손에 들어와서 마지막에 살 때 쓸 수 있습니다.
치르는 값은 있습니다. 장중에 팔면 종가가 아니라 그 순간 값에 팔립니다. 조금 손해 볼 수도 있고 이득일 수도 있습니다. 그래도 「사려던 걸 아예 못 사는 것」보다는 낫습니다.
제 기록을 세어보니 매도 186건 중 177건이 장중에 나갔고, 동시호가로 나간 건 9건뿐이었습니다. 원칙이 실제로 지켜지고 있다는 뜻입니다.
고치면서 조심한 것 두 가지
하나. 판단하는 코드를 복사하지 않았습니다.
「장중에 판다」를 만들려면 기존 매도 기능을 하나 더 만드는 게 빠릅니다. 그런데 그러면 「무엇을 팔지 정하는 규칙」이 두 벌이 됩니다. 나중에 한쪽만 고치면 두 코드가 조용히 달라집니다.
그래서 기존 매도 기능에 「지금 팔아도 되나」를 묻는 문 하나만 달았습니다. 무엇을 팔지 정하는 부분은 한 글자도 건드리지 않았습니다.
둘. 기록에 구분을 남겼습니다.
장중에 미리 판 것도, 마지막에 판 것도 결과는 똑같이 「팔았다」입니다. 그래서 처음엔 기록을 하나로 남겼습니다.
그런데 나중에 「이건 미리 판 건가, 원래 순서대로 판 건가」를 물었을 때 답할 수가 없었습니다. 기록에 그 구분이 없으니까요. 지금은 나눠서 적습니다.
번외 — 거래정지 종목은 날짜가 멈춰 있습니다
시간과 관련해 하나 더 걸렸던 게 있습니다.
프로그램이 「지금이 며칠인가」를 알아야 할 때가 있습니다. 달력 날짜가 아니라 장이 열린 날 기준으로요. 주말과 공휴일이 있으니 달력으로는 셀 수 없습니다.
그래서 종목의 일봉 데이터에서 마지막 날짜를 읽는 방법을 썼습니다. 어제 장이 섰으면 어제 날짜가 찍혀 있을 테니까요.
그런데 거래정지된 종목이 있습니다. 거래가 멈추면 일봉도 멈춥니다. 정지된 날짜에서 더 이상 안 늘어납니다.
하필 그 종목을 보고 날짜를 정하면, 프로그램은 몇 달 전을 「오늘」이라고 믿습니다.
고친 방법은 간단합니다. 한 종목만 보지 않고 여러 종목을 본 뒤, 그중 가장 최근 날짜를 씁니다. 멈춘 종목이 섞여 있어도 살아 있는 종목이 하나만 있으면 맞는 날짜가 나옵니다.
정리
| 겪은 것 | 배운 것 |
|---|---|
| 판 돈이 그날 안 들어왔다 | 파는 건 장중에 먼저, 사는 건 마지막에 |
| 시뮬레이션은 이걸 못 본다 | 하루를 한 덩어리로 보면 그 안의 순서가 사라진다 |
| 기능을 하나 더 만들 뻔했다 | 판단하는 코드는 복사하지 말고 문만 연다 |
| 나중에 구분할 수가 없었다 | 물어볼 것 같은 질문은 지금 기록에 넣는다 |
| 거래정지 종목이 날짜를 오염시켰다 | 하나만 보고 정하지 말고 여럿 중 최신을 쓴다 |
다섯 개가 다 「시장은 하루 종일 같은 방식으로 돌아가지 않는다」는 한 가지에서 나왔습니다. 프로그램은 시간을 그냥 흘러가는 숫자로 보지만, 시장에는 성격이 다른 구간이 있고 멈추는 종목이 있습니다.
'자동매매 일지 > 시스템 운영' 카테고리의 다른 글
| 주식 자동매매 직접 만들기 — 실제 사고로 배운 5가지 (0) | 2026.08.28 |
|---|---|
| 검사 프로그램이 진짜 보유 내역을 덮어썼습니다 — 12개는 지켰는데 하나가 (0) | 2026.08.27 |
| 하네스가 무엇인가요 — 말에 채우는 마구에서 클로드 코드까지 (0) | 2026.08.27 |
| SOR은 시장가 주문을 받지 않습니다 — NXT 대체거래소에서 막힌 네 가지 (0) | 2026.08.25 |
| 액면분할로 3주가 7주가 됐는데, 자동매매는 3주만 팔았습니다 (0) | 2026.08.21 |