카테고리 없음

주식 자동매매 포지션 동기화 오류 — 사라진 주식 되찾기

우베르 2026. 6. 21. 21:37
반응형
주식 자동매매 포지션 동기화 오류 — 사라진 주식 되찾기
직장인 자동매매 체험기 · 7편
← 6편: Claude Desktop으로 자동매매 코드 오류 잡기

주식 자동매매 포지션 동기화 오류 — 사라진 주식 되찾기

증권사엔 그대로 있는데 내 시스템만 "포지션 없음"이라 판단한 사건, 그리고 로그에서 함께 찾은 4가지 함정

장 마감하고 리포트를 열어봤는데, 보유 종목이 0개로 나왔다. 분명 어제 아침에 두 종목을 사뒀는데. 잘못 봤나 싶어서 다시 봐도 positions: {}. 내가 지운 적도 없는데 내 주식이 사라져 있었다.

알고 보니, 진짜로 사라진 게 아니라 시스템이 스스로 "이건 없는 포지션"이라고 착각하고 자기 손으로 지운 거였다. 그것도 1초 만에 자기 판단이 틀렸다는 걸 다시 발견하면서.

모의투자 한 달은 -1.1%로 끝났다. "이 정도면 실전 가도 되겠다" 싶었는데, 실전 첫 달(5/7~6/5) 결과는 -5.2%, -52,010원이었다. 손실 폭이 다섯 배가 됐다. 전략이 갑자기 나빠진 게 아니었다. 한 달치 리포트와 로그를 처음부터 끝까지 다시 읽다 보니, 문제는 전략 바깥, 신호를 처리하는 과정 곳곳에 있었다. 이번 편은 그 다섯 번의 기록이다.

-52,010원
한 달 손익 (-5.2%)
11건
청산 거래 (1승 10패)
5가지
로그에서 찾은 함정

사건 1. 하루에 두세 번씩 늘려 산 날들

터틀 전략의 피라미딩 원칙은 "가격이 0.8N 오르면 한 번 추가매수"다. 그런데 신호 스캔이 1분마다 돌다 보니, 가격이 빠르게 움직이는 날엔 이 조건을 하루에 두세 번씩 충족시켜 버린다는 걸 로그에서 처음 알았다.

제일 비싼 수업료를 낸 게 대한광통신이었다. 5월 11일 24,600원에 2주로 들어갔는데, 같은 날 26,550원에서 한 번, 28,300원에서 또 한 번, 하루 만에 피라미딩이 두 번 들어갔다. 다음 날 30,450원에서 한 번 더 늘려 5주가 됐고, 그날 바로 24,950원에서 손절됐다. 평균 매입가 26,900원 대비 -10,013원, 한 달 중 가장 큰 손실이었다.

2026-05-11 OPEN_LONG 010170 24,600원 2주 2026-05-11 ADD_LONG 010170 26,550원 +1주 (당일 1차 추가) 2026-05-11 ADD_LONG 010170 28,300원 +1주 (당일 2차 추가) 2026-05-12 ADD_LONG 010170 30,450원 +1주 (익일 추가) 2026-05-12 CLOSE_LONG 010170 24,950원 pnl: -10,013원 (stop_loss)

같은 패턴이 PS일렉트로닉스(5/13, 13,720원·14,480원 동시 추가)와 서울바이오시스(5/14, 진입 당일에 17,620원·19,240원 동시 추가)에서도 반복됐다. 피라미딩 간격을 0.8N으로 둔 이유는 "가격이 추세를 그릴 시간을 주고, 단계적으로 비중을 늘리자"는 거였는데, 하루에 두세 번 들어가면 그 단계적 분산이 의미가 없어진다. 비중이 하루 만에 다 들어가니, 손절선에 닿았을 때 손실도 하루 만에 그만큼 커졌다.

대처

같은 종목에 대해 "진입 당일 피라미딩 금지", "하루 1회 제한" 규칙을 코드에 넣었다. 상태: 해결

사건 2. 돈을 벌어도 "손절"이라고 찍힌다

대덕전자1우는 5월 12일 36,100원에 들어가서 5월 14일 45,400원에 나왔다. +9,206원, 한 달 중 유일하게 웃은 거래였다. 그런데 이 거래의 사유(reason) 필드를 열어보니 "stop_loss"라고 적혀 있었다.

2026-05-14 CLOSE_LONG 35320K 대덕전자1우 entry_price: 36,100원 → price: 45,400원 pnl: +9,206원 reason: "stop_loss" ← 추세청산인데도 같은 라벨

오타인가 싶어서 다시 봤는데, 시스템 자체가 "20일 저점 이탈로 인한 추세청산"과 "1.8N 손절"을 구분 안 하고 둘 다 같은 라벨로 기록하고 있었다. 당장 매매 결과엔 영향이 없지만, 이 라벨로 통계를 내면 사실과 달라진다. "청산 11건 중 1승"을 "손절 11건 중 1승"이라고 쓰면 틀린 설명이 된다.

대처

추세청산(trend_exit)과 손절(stop_loss)을 별도 사유로 나누는 작업이 필요하다. 상태: 미해결

사건 3. 실전인데 모의투자 서버로 접속하고 있었다

5월 27일 로그를 켜자마자 에러가 떴다.

[ERROR] 계좌 잔고 조회 실패: HTTPSConnectionPool(host='openapivts.koreainvestment.com', port=9443) SSL: CERTIFICATE_VERIFY_FAILED Hostname mismatch, certificate is not valid for 'openapivts.koreainvestment.com' 거래대금 1500억↑: 0개 ← 종목 조회 전체 실패

openapivts는 모의투자(가상서버) 도메인이다. 실전 계좌를 돌리는데 요청은 모의투자 서버로 가고 있었다. 인증서가 안 맞으니 연결이 통째로 막혔고, 그날은 매수도 매도도, 신호 스캔조차 일어나지 않았다. 다음 날(5/28) 로그에는 이 에러가 한 줄도 없었다. 정상 도메인으로 26개 종목이 조회됐다.

대처

환경(실전/모의)에 따라 URL을 하드코딩하지 않고 변수로 분기하도록 바꿨다. 시작 로그에 "지금 어떤 도메인에 접속하는지"를 한 줄로 명시하게 했다. 상태: 해결

사건 4. 시스템이 내 주식을 스스로 지운, 가장 섬뜩했던 사건

이게 이번에 찾은 것 중 제일 등골이 서늘했던 사건이다. 6월 2일 오전 9시, KODEX AI반도체TOP2플러스에 피라미딩이 정상적으로 들어가서 2주(평균 52,150원)가 됐다. 여기까진 평범한 하루였다.

장 마감 후 15시 30분 20초, 동기화 로직이 돌면서 이런 경고가 찍혔다.

⚠ 395160 포지션 상태 불일치: 로컬에만 존재 → 제거 ⚠ 395270 포지션 상태 불일치: 로컬에만 존재 → 제거

시스템이 "이 두 종목은 내 기록에만 있고 실제 증권사 계좌엔 없다"고 판단해서 로컬에서 지워버렸다. 그래서 그날 저녁 리포트에 positions: {}, 보유 0종목으로 찍혔다. 그런데 1초 뒤, 같은 동기화의 사후 점검에서 정반대 결과가 나왔다.

position_mismatch: 브로커 2주 / 로컬 0주 불일치 position_mismatch: 브로커 1주 / 로컬 0주 불일치

증권사 쪽엔 실제로 2주, 1주가 그대로 있었다. 직전에 "없다"고 판단한 게 틀렸다는 증거가 같은 로그 안에서 1초 만에 나온 거다. 포지션 존재 여부를 "매수가능조회(fallback)" 방식 한 곳에만 의존해서 판단하고 있었는데, 이 조회 방식이 일시적으로 불완전한 값을 돌려주면서 "포지션 없음"으로 오판한 것으로 보인다.

다음 날(6/3) 정오, 시스템이 다시 이 종목들을 찾아냈다.

⚠ 395160 미추적 포지션 감지: 2주 @52150.0원 ⚠ 395160 price_data 없음 → 손절가 임시 -8% 적용 (47,978원) ⚠ [395160] price_data 없음 → 추세청산/피라미딩 불가 (손절만 적용)

다행히 중복 매수는 안 일어났다. 대신 복구 과정에서 ATR이 0으로 리셋되면서, 원래의 1.8N 손절 대신 임시 -8% 손절가가 적용됐다. 6월 3일 한나절 동안 이 두 종목은 원래 전략의 보호 장치 없이, 임시방편 손절가 하나로만 버티고 있었던 거다.

봇을 개선하는 건 코드를 고치는 게 아니다. 내가 놓친 규칙을 찾아내는 것이다.

대처

포지션 존재 여부를 캐시 하나에 의존하지 않고 여러 소스로 교차 검증하도록 바꿔야 한다. 지금은 "미추적 포지션 감지" 로그가 뜨면 그날 아침 무조건 수동으로 확인하는 걸 체크리스트에 넣어뒀다. 상태: 진행 중

사건 5. 절대 안 지워지는 유령 경고

매일 장 마감 무결성 점검에서 "체결 로그는 있으나 주문 제출 이벤트 없음"이라는 경고가 뜬다. 처음엔 신경 안 썼는데 건수를 세보니 5/27 11건 → 5/28~29 12건 → 6/4 19건으로 계속 늘고 있었다.

내용을 들여다보면 옛날에 청산된 종목이 매일 똑같이 다시 찍히고, 6월 4일부터 새 종목이 또 추가됐다. 한 번 찍힌 경고가 절대 사라지지 않고 계속 쌓이기만 하는 구조였다. 체결을 정상 흐름이 아니라 사후 매칭으로 복구한 거래들이 정상적인 "주문 제출 이벤트" 로그를 안 남기는 것으로 보였다. 실제 문제가 있는 게 아니라 로그 구조의 한계인데, 매일 19건씩 경고가 뜨면 그 안에 진짜 새 문제가 섞여 있어도 놓치기 쉽다.

대처

지금은 "어제보다 종목이 늘었는가"만 매일 확인해서 새 경고와 누적된 옛 경고를 구분하고 있다. 경고를 정리(clear)하는 로직 자체는 다음 과제다. 상태: 진행 중

마무리: 고친 것과 아직 안 고친 것

사건상태
1. 당일 동시 피라미딩 당일/1일 1회 제한 추가
2. 손절/추세청산 라벨 혼용 사유 필드 분리 필요
3. 모의투자 URL 오접속 환경별 분기 + 시작 로그 명시
4. 동기화 오판으로 포지션 삭제 단일 캐시 의존 문제 남음
5. 유령 경고 누적 노이즈/실제 구분만 운영 중

5개 중 2개는 고쳤고, 3개는 여전히 진행 중이다. -5.2%라는 숫자만 보면 "전략이 별로다"로 끝낼 수도 있었는데, 로그를 뒤지니 전략 탓이 아니라 운영의 디테일에서 새고 있었다.

반응형