NOONOO TRADING무료 채팅방 입장

봇 재시작 — 껐다 켜는 순간 포지션을 잃어버리는 이유

자동매매 봇은 언젠가 반드시 멈춥니다. 코드를 고쳐서, 정전이 나서, 프로그램이 죽어서 멈춥니다. 문제는 멈추는 것이 아니라 다시 켜지는 순간입니다. 계좌에는 포지션이 그대로 남아 있는데, 봇은 아무것도 기억하지 못한 채 시작하기 때문입니다.

봇의 기억은 어디에 있나

봇이 돌아가는 동안 알고 있는 것들 — 지금 롱인지 숏인지, 진입가가 얼마인지, 손절을 어디에 뒀는지, 물타기를 몇 번 했는지 — 는 대부분 프로그램 메모리 안에 있습니다. 메모리는 프로그램이 종료되면 같이 사라집니다.

종료와 함께 사라지는 것들

메모리에만 있으면 사라진다
  · 현재 방향 (롱 / 숏)
  · 진입가 · 진입 시각
  · 손절가 · 목표가
  · 물타기 몇 단계인지
  · 이미 낸 주문의 번호

거래소에는 남아 있다
  · 실제 포지션 수량 · 평단가
  · 미체결 지정가 주문

─────────────
재시작 직후
  계좌 = 포지션 있음
  봇 = 포지션 없음이라고 믿음

이 어긋남이 모든 재시작 사고의 출발점입니다. 봇 입장에서는 방금 태어났으므로 "나는 아무것도 들고 있지 않다"가 기본값입니다. 그런데 계좌는 껐다 켜는 동안에도 계속 살아 있었습니다. 이 차이를 다루는 방식은 포지션 대사와 뿌리가 같지만, 재시작은 그 어긋남이 확실히 발생하는 순간이라는 점이 다릅니다.

기억을 잃은 봇이 첫 사이클에 하는 일

대부분의 봇은 켜지자마자 시세를 보고 신호를 계산합니다. 이때 "포지션 없음"이라고 믿고 있으면, 신호가 맞는 순간 그냥 새로 진입합니다.

수량이 두 배가 되는 경로

재시작 전
  BTC 롱 0.1 · 진입 100,000
  20배 · 증거금 500
  손절 97,000 (봇 메모리에만 존재)

봇 종료 → 코드 수정 → 재기동

부팅 첫 사이클
  봇이 아는 포지션 = 0
  롱 신호 발생 → 0.1 신규 진입

실제 계좌
  0.1 + 0.1 = 0.2 계약
  증거금 1,000

─────────────
가격이 97,000으로 −3%
  계획대로면 −300에서 손절
  실제 손실 −600
  봇이 닫는 수량 = 0.1뿐

결과는 중복 주문과 같은 모양입니다. 원인만 다릅니다 — 그쪽은 응답이 유실돼서, 이쪽은 기억이 유실돼서 같은 진입이 두 번 일어납니다. 마지막 줄이 특히 나쁩니다. 봇은 자기가 낸 0.1만 관리하므로, 손절이 걸려도 나머지 0.1은 계좌에 그대로 남습니다. 아무도 손절을 걸어두지 않은 포지션이 하나 생기는 셈입니다.

반대 방향도 있습니다. 재시작 후 숏 신호가 나오면, 봇은 "포지션 없으니 숏 진입"을 합니다. 계좌에는 기존 롱 0.1과 새 숏 0.1이 동시에 잡히거나(양방향 모드), 롱이 상계되어 사라집니다(단방향 모드). 어느 쪽이든 봇의 기록과 계좌는 완전히 다른 이야기를 하게 됩니다.

첫 사이클에는 주문을 내지 않는다

해결의 첫 단계는 단순합니다. 켜지자마자 판단하지 말고, 먼저 현재 상태를 확인합니다.

부팅 순서

1. 거래소에서 포지션 조회
2. 거래소에서 미체결 주문 조회
3. 저장해둔 내부 기록 읽기
4. 둘을 대조해서 상태 확정
5. 그다음부터 신호 계산 시작

─────────────
조회에 실패하면
  → 주문 금지 · 재시도
  → 계속 실패하면 알림 후 대기

절대 하면 안 되는 것
  조회 실패 = 포지션 없음으로 간주

마지막 줄이 실전에서 가장 자주 나오는 실수입니다. 조회가 안 되면 빈 값이 돌아오고, 빈 값을 "포지션 없음"으로 읽으면 봇은 자신 있게 새로 진입합니다. 모른다와 없다는 다릅니다. 모르는 상태에서는 주문을 내지 않는 것이 정답입니다. 이는 웹소켓 끊김에서 다룬 원칙과 같습니다 — 침묵을 정보로 해석하면 안 됩니다.

무엇을 저장해두어야 하나

거래소 조회만으로는 복구되지 않는 것이 있습니다. 수량과 평단가는 거래소가 알려주지만, "왜 이 포지션을 잡았는지"는 봇만 압니다.

거래소가 알려주는 것 / 아닌 것

거래소가 알려준다
  · 방향 · 수량 · 평단가
  · 미실현 손익 · 미체결 주문

거래소가 모른다
  · 어떤 신호로 들어갔는지
  · 물타기 몇 단계째인지
  · 다음 물타기 예정 가격
  · 진입 후 최고·최저 도달가
  · 이 거래에 붙인 주문 이름표

─────────────
따라서
  수량 = 거래소를 권위
  맥락 = 내 파일을 권위
  둘이 충돌하면 거래소가 이긴다

그래서 상태는 메모리에만 두지 말고 거래가 바뀔 때마다 파일에 씁니다. 진입할 때, 물타기할 때, 손절가를 옮길 때, 청산할 때 — 값이 바뀌는 그 시점에 기록합니다. 몇 분에 한 번 몰아서 저장하면, 마지막 저장 이후의 변화는 재시작과 함께 사라집니다.

저장 시점이 어긋나면 반쪽 기록이 남는다

주문을 낸 다음 기록을 쓰는데, 그 사이에 프로그램이 죽으면 어떻게 될까요. 순서에 따라 남는 흔적이 다릅니다.

순서별 결과

① 주문 → 죽음 → 기록 못 씀
  계좌 있음 · 기록 없음
  → 재시작 후 유령 포지션

② 기록 먼저 → 죽음 → 주문 못 냄
  계좌 없음 · 기록 있음
  → 재시작 후 유령 기록

─────────────
어느 쪽이 안전한가
  ②가 낫다 — 없는 포지션을
  닫으려다 실패하는 것이
  있는 포지션을 방치하는 것보다 낫다

진짜 해법
  부팅 때 거래소 조회로 덮어쓴다
  → ①②가 전부 정리된다

어떤 순서로 짜도 그 사이에 죽는 경우는 없앨 수 없습니다. 그래서 순서를 완벽하게 만드는 대신, 부팅 때 반드시 대조한다는 규칙으로 덮습니다. 기록이 틀렸을 수 있다고 가정하고 시작하면, 반쪽 기록은 사고가 아니라 정정 대상이 됩니다.

파일을 쓰는 도중에 죽는 경우도 있습니다. 그러면 파일이 깨져서 아예 못 읽게 됩니다. 임시 파일에 다 쓴 다음 이름을 바꾸는 방식으로 저장하면, 파일은 이전 내용 아니면 새 내용 둘 중 하나가 되고 중간 상태로는 남지 않습니다.

재시작은 예고 없이 온다

계획된 재시작만 있는 것이 아닙니다. 오히려 예고 없는 쪽이 더 자주 옵니다.

재시작이 발생하는 경로

계획된 것
  · 코드 수정 후 재기동
  · 설정 변경 · 서버 이전

예고 없는 것
  · 정전 · PC 강제 종료
  · 프로그램 비정상 종료
  · 운영체제 자동 업데이트 재부팅
  · 메모리 부족으로 강제 종료

─────────────
공통점
  "정리하고 나갈 시간"이 없다
  → 종료 직전 저장에 기댈 수 없다

종료 신호를 받아서 정리하는 코드는 넣어두면 좋지만, 그것만 믿으면 안 됩니다. 전원이 끊기면 어떤 정리 코드도 돌지 않습니다. 그래서 저장은 종료할 때가 아니라 값이 바뀔 때마다 해야 합니다.

재부팅 후 봇이 자동으로 다시 켜지게 해두는 것도 같은 맥락입니다. 다만 자동 재기동을 켜둘 거라면 부팅 시 상태 복원이 먼저 갖춰져 있어야 합니다. 복원 없이 자동 재기동만 켜두면, 정전 한 번에 봇이 스스로 중복 진입을 하게 됩니다. 거래소 쪽 정기 점검으로 잠시 조회가 막히는 구간도 같은 방식으로 다룹니다 — 모르면 멈춥니다.

재시작 전에 확인할 것

사람이 직접 껐다 켜는 경우에는 타이밍을 고를 수 있습니다. 이것만으로도 사고 대부분이 사라집니다.

재시작 체크리스트

끄기 전
  · 보유 포지션 있는지 확인
  · 있으면 손절이 거래소에 걸려 있나
    (봇 메모리에만 있으면 무방비)
  · 미체결 주문 목록 기록해두기
  · 가능하면 무포지션 상태에서

켠 뒤
  · 봇이 인식한 수량 = 거래소 수량?
  · 프로세스가 하나만 떠 있나
  · 첫 주문이 나가기 전에 로그 확인

─────────────
가장 위험한 조합
  포지션 보유 + 손절이 봇 안에만
  + 재시작이 오래 걸림

맨 아래 조합을 풀어보면 이렇습니다. 손절을 거래소에 실제 주문으로 걸지 않고 봇이 가격을 지켜보다 시장가로 닫는 방식이라면, 봇이 꺼져 있는 동안 그 포지션에는 손절이 없는 상태입니다. 5분이 걸리든 한 시간이 걸리든 그 시간 동안은 무방비입니다. 재시작이 잦은 개발 단계라면 손절은 거래소 주문으로 걸어두는 편이 안전합니다.

프로세스가 하나만 떠 있는지 확인하는 것도 빼면 안 됩니다. 이전 프로세스가 안 죽은 상태에서 새로 켜면 봇 두 개가 같은 계좌에 주문을 냅니다. 이 경우 상태 복원이 아무리 잘 돼 있어도 소용이 없습니다 — 두 봇이 각자 복원하고 각자 주문합니다.

검증하는 법

재시작 복구는 평소에 안 보이다가 사고 때 한 번 드러나는 기능입니다. 그래서 일부러 시험해봐야 합니다.

시험 순서

1. 모의 또는 소액으로 진입
2. 봇을 강제 종료한다
  (정상 종료 말고 강제로)
3. 다시 켠다
4. 로그 확인
  · 포지션을 인식했나
  · 수량·평단이 거래소와 같나
  · 손절가를 복원했나
  · 새 진입을 하지 않았나

─────────────
추가 시험
  · 상태 파일을 지우고 켜본다
  · 상태 파일을 일부러 깨뜨리고 켜본다
  → 둘 다 주문 없이 멈춰야 정상

마지막 두 줄이 핵심입니다. 상태 파일이 없거나 깨졌을 때 봇이 조용히 "처음부터 시작"해버리면, 그것이 가장 비싼 실패 방식입니다. 파일이 이상하면 멈추고 알리는 쪽이 맞습니다. 연동과 인증 전반은 거래소 API 연동 가이드에 정리돼 있습니다.

정리

봇의 기억은 종료와 함께 사라진다
계좌의 포지션은 그대로 남는다
재시작 직후 봇은 "포지션 없음"이라 믿는다
그 상태로 신호가 나면 수량이 두 배
봇은 자기가 낸 수량만 닫아 절반이 방치
부팅 첫 사이클에는 주문을 내지 않는다
조회 실패를 포지션 없음으로 읽으면 안 된다
수량은 거래소, 맥락은 내 기록이 권위
저장은 종료할 때가 아니라 바뀔 때마다
파일은 임시 파일 → 이름 변경으로 깨지지 않게
손절이 봇 안에만 있으면 꺼진 동안 무방비
강제 종료로 직접 시험해봐야 확인된다

한 줄로 줄이면 이렇습니다. 봇은 언제든 죽는다고 가정하고, 켜질 때마다 계좌에 다시 물어보게 만듭니다. 이 구조가 있으면 재시작은 사고가 아니라 그냥 일상적인 동작이 됩니다.

주의

본문의 수량, 가격, 증거금, 배율, 손익 수치는 구조를 설명하기 위한 가정 예시이며 특정 거래소의 실제 측정값이 아닙니다. 포지션·주문 조회 방식, 단방향/양방향 모드 동작, 조건부 주문이 재시작 후에도 유지되는지 여부, 조회 요청 한도는 거래소마다 다르므로 본인이 쓰는 거래소 문서에서 확인하고 소액으로 직접 시험해야 합니다. 레버리지 거래는 원금 전액을 잃을 수 있으며, 투자 판단과 그 결과는 본인 책임입니다.

NOONOO TRADING 무료 채팅방에서 실시간 트레이딩을 같이 보세요.

무료 채팅방 입장 →

📈 OKX 신규 가입 시 거래 수수료 할인

OKX 수수료 할인 가입 →