📚 토스 자동매매 개발기 시리즈 (현재 Phase 2-1 · 전체 8편 중 8번째)
- #0 기초 시스템 구축 (5파일 구조, 삼중 안전장치)
- #0-1 해외 보유 종목 누락 버그 수정
- #3 설정 중앙화 + 재시도 데코레이터
- #4 설정/재시도 후속 조치 + 회귀 이슈
- #5 pytest 단위 테스트 (33개 통과)
- #6 RotatingFileHandler로 로그 순환 처리
- #7 매수 조건을 전략 클래스로 분리하기 (현재 글)
👉 이전 글: #6 RotatingFileHandler로 로그 순환 처리
Phase 1의 4개 항목(설정 중앙화, 재시도 로직, pytest 도입, 로그 순환)을 다 끝내고 나니, 로드맵에 다음으로 적어뒀던 게 “전략 모듈화”였다. 이 자동매매 봇은 지금까지 auto_trader.py의 감시 루프 안에 if current_price <= TARGET_BUY_PRICE: 라는 조건문이 그냥 박혀 있는 구조였는데, 여기에 이동평균이나 RSI 같은 다른 매수 조건을 하나 더 추가하려고 하면 결국 이 루프 코드를 계속 건드려야 하는 상황이었다.
왜 지금 손대야 했나
당장 이동평균 전략을 쓸 계획이 있는 건 아니지만, “나중에 조건 하나 추가하려면 루프 코드부터 뜯어야 한다”는 구조 자체가 부담이었다. 그래서 Phase 2를 세 단계로 나눴다.
- ① 기존 조건을 클래스로 추상화
- ② 플러그인 형태의 전략 인터페이스 설계
- ③ 단일 종목 → 복수 종목 동시 감시 지원
한 번에 다 하면 검증이 복잡해질 것 같아서, 이번 세션은 딱 ①번만 최소 범위로 진행하기로 했다. 안전장치(DRY_RUN, TARGET_BUY_PRICE)는 절대 건드리지 않는다는 원칙은 그대로 유지했다.
strategy.py 신설 — ThresholdBuyStrategy 클래스
새 파일 strategy.py에 ThresholdBuyStrategy 클래스를 만들고, should_buy(current_price) 메서드 안에 기존 조건을 그대로 옮겼다. 값도 판단 로직도 바뀐 게 하나도 없고, 표현 방식만 함수에서 클래스로 이동한 거라 리스크는 크지 않다고 판단했다.
class ThresholdBuyStrategy:
def __init__(self, target_price: float):
self.target_price = target_price
def should_buy(self, current_price: float) -> bool:
return current_price <= self.target_price
(예시 코드이며 실제 종목코드·목표가는 삼성전자 005930, 임의 금액으로 마스킹했다)
auto_trader.py의 감시 루프 안에 있던 if current_price <= TARGET_BUY_PRICE: 하드코딩 조건문을 if buy_strategy.should_buy(current_price): 호출 한 줄로 바꿨다. 목표가는 여전히 config.py의 TARGET_BUY_PRICE 값을 그대로 주입받아 쓴다.
검증 — pytest 38개 통과
test_strategy.py를 새로 만들어서 정상 케이스, 경계값(현재가와 목표가가 정확히 같을 때), 그리고 실제 안전장치 값(1원)까지 반영한 시나리오로 4개 테스트를 작성했다. 전체 pytest를 다시 돌려보니 기존 34개 + 신규 4개, 총 38개 전부 통과했다.
테스트만 믿고 넘어가지 않고, python auto_trader.py를 직접 짧게 실행해서 기존과 동일하게 5초 간격으로 정상 감시되는지, 목표가 1원 조건이라 매수 신호 없이 안전하게 동작하는지, Ctrl+C로 정상 종료되는지까지 확인했다.
사이드 이슈 — 프로젝트 저장소 덮어쓰기
수정 파일을 프로젝트 저장소에 반영하는 과정에서, 같은 이름 파일을 새로 올리면 기존 파일이 자동으로 덮어써지는지 궁금해서 확인해봤다. 결과는 아니었다 — 이 플랫폼의 프로젝트 첨부파일은 읽기 전용으로 취급돼서, 같은 이름으로 다시 올려도 자동 덮어쓰기가 안 되고 중복 파일이 생길 수 있었다. 그래서 이후로는 기존 파일을 먼저 지우고 재업로드하는 절차로 바꿨다.
Toss 자동매매 봇의 매수 조건을 하드코딩 대신 ThresholdBuyStrategy 클래스로 분리하면, 나중에 이동평균·RSI 같은 다른 전략을 추가할 때 감시 루프 코드를 건드리지 않아도 된다.
다음으로 이어질 것
Phase 2의 나머지 두 항목이 남아 있다. 순서는 복수 종목 동시 감시 지원을 먼저 하고, 그다음에 이동평균·RSI 등을 붙일 수 있는 플러그인 인터페이스를 설계할 계획이다.
FAQ
Q1. 클래스로 옮기면 성능에 영향이 있나요?
없다. 메서드 호출 한 단계가 추가되는 정도라 감시 루프 주기(5초)에서 체감될 수준의 오버헤드는 아니다.
Q2. 기존 안전장치(DRY_RUN, TARGET_BUY_PRICE)는 그대로인가요?
그대로다. 이번 작업은 판단 로직의 표현 방식만 바꾼 것이고, 값이나 동작 자체는 전혀 건드리지 않았다.
Q3. 왜 플러그인 인터페이스까지 한 번에 안 만들었나요?
인터페이스까지 미리 설계하면 검증해야 할 범위가 커지고 리스크가 늘어난다고 판단해서, 이번 세션은 클래스 추상화 하나로 범위를 최소화했다.
“전략 클래스 추상화로 매매 로직 분리하기 | 토스 개발기 #2-1”에 대한 3개의 생각