1회 주문 한도 방어 로직으로 안전장치 강화하기 | 토스 자동매매 개발기 #19

🌐 Read in English

💡 이번 Phase 7 요약

  • 목적: 버그나 설정 실수로 의도치 않게 큰 수량이 주문되는 것을 막는 방어 로직 구현
  • 핵심 포인트: DRY_RUN보다 먼저 검사되는 “안전 0단계”로 삽입해, 시뮬레이션 상태에서도 한도 초과 주문을 즉시 거부하도록 설계
  • 검증: 신규 테스트 4개 추가, 전체 pytest 122개 전부 통과 (기존 118개 + 신규 4개)

Phase 0~6을 지나 드디어 Phase 7, 실전 전환 준비

Phase 0부터 Phase 6까지, 설정 분리부터 전략 클래스, DB 영속성, 백테스트 엔진, 텔레그램 제어, 스케줄러/워치독까지 한 단계씩 쌓아왔다. 로드맵 마지막에 남은 건 Phase 7, 이름하여 “실전 전환 준비”다. 이번 글에서는 그 첫걸음으로 1회 주문 한도 방어 로직을 다룬다.

근데 이 단계는 이름부터 부담스럽다. 지금까지는 어디까지나 DRY_RUN이라는 안전망 안에서 놀았지만, Phase 7이 끝나면 진짜 내 계좌에 진짜 주문이 나갈 수도 있다는 얘기니까. 그래서 곧바로 세이프티 장치를 풀어버리는 대신, 먼저 준비해두면 좋을 것들부터 하나씩 짚기로 했다.

실전 전환 전 체크리스트

정리한 순서는 이랬다.

  1. 1회 주문 한도 방어 로직 (오늘 다룰 부분)
  2. 일일/누적 손실 한도 자동 정지
  3. 실제 목표가·전략으로 백테스트 검증
  4. (승인 후) 3중 안전장치 단계적 해제

사용량 한도도 고려해야 해서 하루에 하나씩 진행하기로 했다. 오늘은 1번, 1회 주문 한도 방어 로직부터.

문제: 큰 수량 주문을 막을 장치가 없었다

코드를 다시 훑어보니 허점이 하나 눈에 띄었다. 수량 계산 로직에 버그가 있거나, 설정값을 잘못 입력하는 실수를 하면 의도치 않게 큰 수량으로 주문이 나갈 수 있는 구조였다. 지금까지의 3중 안전장치(DRY_RUN, 목표가 1원, API 물리적 주석 처리)는 “거래 자체”를 막아주지만, 코드 로직의 실수까지 잡아주진 못한다.

그래서 config.pyMAX_ORDER_QUANTITY_PER_TRADE라는 설정을 추가했다. 기본값은 10주. 한 번의 주문에서 이 수량을 넘기면 무조건 거부되도록 만드는 게 목표다. 이게 바로 이번 글의 핵심인 1회 주문 한도 방어 로직이다.

설계: DRY_RUN보다 먼저 검사하기

여기서 가장 중요한 설계 결정을 하나 했다. 이 1회 주문 한도 체크를 기존 3중 안전장치보다 앞서 검사되는 “안전 0단계”execute_order() 안에 삽입한 것이다.

왜 이 순서가 중요하냐면, DRY_RUN=True인 시뮬레이션 상태에서도 한도 초과 시 즉시 거부되게 만들면, 실전 전환 전에 “수량 계산 실수” 같은 코드 버그를 미리 잡아낼 수 있기 때문이다. 시뮬레이션 중에 몰래 숨어있던 버그를 실전 직전이 아니라 지금 발견하는 게 훨씬 안전하다.

가상 종목(삼성전자, 005930)을 예로 들면, 원래 5주를 사려던 주문이 계산 실수로 500주가 되어버려도, 이 0단계에서 바로 걸러진다.

참고: 한도를 초과한 주문은 ERROR 레벨 경고 알림만 발송하고, 거래 이력에는 전혀 남기지 않도록 처리했다. 실제로 체결되지 않은 거래가 통계에 섞여서 나중에 손익 분석을 왜곡하는 걸 막기 위해서다.

검증: 테스트 4개 추가, 122개 전부 통과

test_auto_trader.py에는 아래 3개 테스트를 추가했다.

  • 한도 초과 시 주문이 거부되는지
  • 한도와 정확히 같은 경계값(예: 10주)에서는 정상 체결되는지
  • 한도 초과 주문이 거래 이력에 남지 않는지

여기에 test_config.py에는 한도 값 자체가 안전한 범위(1~100)를 벗어나지 않는지 확인하는 회귀 방지 테스트도 추가했다. 나중에 이 값을 실수로 너무 크게 바꿔버리면 방어선 자체가 무력화되니까, 그 실수를 미리 막기 위한 안전장치다.

전체 pytest를 재실행한 결과 122개 전부 통과(기존 118개 + 신규 4개)했고, 기존 DRY_RUN·TARGET_BUY_PRICE 안전장치 값은 전혀 건드리지 않았다는 것도 다시 확인했다.

최종 결과: 4중 안전장치 체계

이번 작업으로 기존 3중 안전장치에 1회 주문 한도까지 더해져 아래처럼 4중 구조가 됐다.

단계내용
0단계 (신규)1회 주문 한도 초과 시 즉시 거부
1단계DRY_RUN=True 시뮬레이션 모드
2단계목표가 1원 (시장 체결 불가)
3단계실제 주문 API 물리적 주석 처리

로컬 실행 환경과 프로젝트 저장소 양쪽 반영 및 동기화까지 확인 완료했다.

다음 단계: 일일/누적 손실 한도 자동 정지

다음으로 준비할 건 일일/누적 손실 한도를 넘으면 감시 루프를 자동으로 일시정지시키는 로직이다. Phase 5에서 만든 engine_control.pause()를 재사용할 예정이다. 그 다음엔 실제 목표가·전략으로 백테스트 검증까지 마치고, 사용자가 명시적으로 승인할 때 3중 안전장치의 단계적 해제를 진행할 계획이다.

👉 다음 편에서는 일일/누적 손실 한도 자동 정지 로직을 다룰 예정입니다.

FAQ

Q1. 1회 주문 한도 방어 로직은 왜 DRY_RUN보다 먼저 검사하나요?

시뮬레이션 상태에서도 한도 초과를 즉시 거부하게 만들어야, 실전 전환 전에 수량 계산 버그 같은 코드 실수를 미리 발견할 수 있기 때문입니다.

Q2. 한도를 초과한 주문은 거래 이력에 남나요?

아니요, ERROR 레벨 경고 알림만 발송하고 거래 이력에는 전혀 남기지 않습니다. 실제로 체결되지 않은 거래가 통계에 섞이는 걸 막기 위해서입니다.

Q3. 기본 주문 한도는 몇 주인가요?

MAX_ORDER_QUANTITY_PER_TRADE의 기본값은 10주이며, 설정에서 자유롭게 조정할 수 있습니다.

Q4. 다음 Phase는 무엇인가요?

일일/누적 손실 한도를 넘으면 감시 루프를 자동으로 일시정지시키는 로직을 준비할 예정입니다.

“1회 주문 한도 방어 로직으로 안전장치 강화하기 | 토스 자동매매 개발기 #19”에 대한 2개의 생각

댓글 남기기