파이썬 주식 자동매매 기초 개념 — 시스템 구성 4요소 정리
주식 자동매매 시스템의 4가지 구성요소
"파이썬으로 자동매매 만들기"라고 검색하면 특정 증권사 API 연동 코드부터 나오는 경우가 많다. 그런데 개념 없이 따라 친 코드는 API가 바뀌는 순간 무너지고, 어디가 왜 고장 났는지 스스로 찾지도 못하게 된다. 코드를 치기 전에 자동매매 시스템이 어떤 부품들로 이루어지는지부터 잡아두는 게 훨씬 오래간다. 이 글은 특정 API 사용법이 아니라, 어떤 구성요소가 왜 필요한지를 정리한다.
일반적으로 자동매매 시스템은 아래 네 가지 축으로 나뉜다.
- 시세/데이터 수집: 현재가, 호가, 과거 데이터를 가져오는 부분
- 전략(신호 생성): 데이터를 보고 "사라/팔아라/대기"를 판단하는 로직
- 주문 실행: 전략의 판단을 실제 주문으로 바꿔 보내는 부분
- 리스크 관리: 손절, 포지션 한도, 이상 상황 감지 등 안전장치
이 네 개를 하나의 거대한 함수에 다 몰아넣지 않고 분리해두는 것이 유지보수와 디버깅 측면에서 훨씬 유리하다.
1. 시세 데이터 수집 — 현재가·과거 데이터 조회
가장 먼저 필요한 건 "지금 가격이 얼마인가"를 알아오는 부분이다. 실전에서는 증권사나 데이터 제공업체의 API를 쓰지만, 개념 설명을 위해 인터페이스만 추상화해보면 이렇다.
python 코드 보기
class MarketDataClient:
def get_current_price(self, symbol: str) -> float:
"""현재가 조회 (실제 구현은 증권사 API 문서에 따라 다름)"""
raise NotImplementedError
def get_price_history(self, symbol: str, days: int) -> list[float]:
"""과거 종가 리스트 조회"""
raise NotImplementedError핵심은 이 부분을 인터페이스로 분리해두는 것이다. 나중에 증권사를 바꾸거나 모의투자용 가짜 데이터로 테스트하려면, 이 클래스만 구현체를 바꿔 끼우면 나머지 코드는 손댈 필요가 없다.
2. 전략 — 매수·매도 신호 생성 로직
전략은 "데이터를 넣으면 매수/매도/대기 신호가 나오는" 순수 함수로 짜는 게 이상적이다. 가장 단순한 예로 이동평균 기반 신호를 개념적으로 보면 이렇다.
python 코드 보기
def moving_average(prices: list[float], window: int) -> float:
return sum(prices[-window:]) / window
def generate_signal(prices: list[float]) -> str:
short_ma = moving_average(prices, window=5)
long_ma = moving_average(prices, window=20)
if short_ma > long_ma:
return "BUY"
elif short_ma < long_ma:
return "SELL"
return "HOLD"여기서 중요한 설계 원칙은 전략 함수가 주문을 직접 실행하지 않는다는 점이다. 전략은 "신호"만 반환하고, 그 신호를 실제 주문으로 옮기는 건 다음 단계인 실행 레이어의 몫이다. 이렇게 분리해야 전략 로직만 따로 백테스트하기 쉬워진다.
3. 주문 실행 — 검증을 거쳐 주문 내보내기
신호를 받아 실제로 주문을 넣는 레이어다. 이 부분이 왜 별도 레이어여야 하냐면, 주문 실행 전에 검증 로직을 끼워 넣을 수 있는 지점이 필요하기 때문이다.
python 코드 보기
def execute_signal(signal: str, symbol: str, order_client, risk_checker):
if signal == "HOLD":
return
order = build_order(signal, symbol)
if not risk_checker.is_allowed(order):
log_rejected(order)
return
order_client.submit(order)risk_checker.is_allowed(order) 부분이 바로 다음에 다룰 리스크 관리다. 신호가 나왔다고 무조건 주문을 내보내는 게 아니라, 반드시 이 검증을 거치게 만드는 구조가 핵심이다.
4. 리스크 관리 — 가장 자주 생략되고, 가장 비싸게 대가를 치르는 부분
튜토리얼이나 예제 코드에서 가장 흔히 생략되는 부분이 리스크 관리다. 하지만 실전에서는 이 부분이 없으면 전략 로직의 사소한 버그가 그대로 손실로 이어진다. 최소한 아래 항목은 개념적으로 넣어두는 걸 권한다.
- 포지션 한도: 한 종목에 전체 자산의 몇 %까지만 투입할지 상한
- 손절 기준: 특정 손실률 도달 시 자동 청산
- 주문 빈도 제한: 짧은 시간에 동일 신호가 반복될 때 중복 주문을 막는 장치
- 이상 데이터 방어: 시세 데이터가 끊기거나 비정상 값일 때 신호 생성을 멈추는 장치
이 항목들은 "당장 급한 건 아니고 나중에 붙이면 되지"라고 미루기 쉬운데, 실제로는 전략 로직보다 먼저 갖춰두는 게 안전하다. 전략은 틀려도 손실이 제한적이지만, 리스크 관리 부재는 손실의 상한 자체가 없다는 뜻이기 때문이다. 이 항목들을 실제 규칙으로 어떻게 구체화하는지는 자동매매 리스크 관리 규칙 설계에서 따로 다뤘다.
자동매매 개발 순서 — 무엇부터 만들어야 하나
- 시세 데이터 클라이언트를 인터페이스로 먼저 설계(실제 구현은 나중)
- 전략 함수를 과거 데이터로 백테스트할 수 있는 형태로 분리
- 리스크 관리 규칙을 먼저 문서화하고 코드로 구현
- 마지막으로 주문 실행 레이어를 붙이되, 처음엔 반드시 모의투자(페이퍼 트레이딩) 환경에서만 실행
이 순서를 거꾸로(주문 실행부터 짜고 리스크 관리는 나중에 붙이는 식으로) 진행하면, 리스크 관리가 "이미 돌아가는 시스템에 억지로 끼워 맞추는" 형태가 되어 빠지는 구멍이 생기기 쉽다.
오늘의 정리
- 자동매매 시스템은 데이터 수집·전략·주문 실행·리스크 관리 네 축으로 분리해서 설계하는 게 유지보수에 유리하다.
- 전략 함수는 신호만 반환하고, 주문은 별도 레이어에서 검증을 거쳐 실행하는 구조가 안전하다.
- 리스크 관리는 가장 생략되기 쉽지만, 손실 상한을 결정하는 가장 중요한 부분이다.
이 네 축 중 "시세/데이터 수집과 주문 실행"에 해당하는 증권사 REST API 연동의 일반적인 흐름은 증권사 REST API 파이썬 첫걸음 — 인증과 잔고조회에서 이어서 다룬다.
이 글의 코드는 개념 설명을 위한 예시이며, 특정 증권사 API나 실제 운영 중인 시스템의 코드가 아닙니다. 실전 적용 전 반드시 모의투자 환경에서 충분히 검증하시기 바랍니다. 이 글은 투자 조언이 아니며 특정 종목이나 매매기법을 추천하지 않습니다. 수익을 보장하지 않으며, 투자 손실에 대한 책임은 투자자 본인에게 있습니다.