본문 바로가기
AI·개발 도구

AI 자동매매 구현하는 방법|Python 백테스트부터 모의주문까지

by mr.k0 2026. 9. 3.
반응형

 

항목 내용
환경 Python 3.10 이상
증상 인증·주문 단계에서 중단
원인 키·검증·위험 제한 누락
해결 백테스트 후 모의주문
바로가기 Alpaca-py 문서

 

AI 자동매매를 처음 연결하면 ModuleNotFoundError: No module named 'alpaca', 401 Unauthorized, 주문은 보냈는데 체결 결과를 기록하지 못하는 현상에서 자주 멈춘다.

모델 정확도부터 높이기보다 데이터 시점, 주문 API, 손실 제한을 분리해야 원인을 찾기 쉽다.

ModuleNotFoundError: No module named 'alpaca'
401 Unauthorized

이 글의 예제 환경은 Ubuntu·Windows·macOS에서 사용할 수 있는 Python 3.11과 2026년 9월 PyPI 최신판 alpaca-py 0.44.0이다.

패키지는 Python 3.10 이상을 지원하며 모의투자는 무료지만, 실거래 수수료·규제 비용과 시장 데이터 조건은 별도로 확인해야 한다.

증상부터 분리해야 하는 이유

 

 

자동매매는 데이터 수집, 특징 계산, 매수·매도 판단, 주문 실행의 네 구간으로 나뉜다.

예측값이 정상이어도 오래된 시세를 읽거나 동일 신호를 두 번 처리하면 주문 결과는 달라진다.

첫 점검은 AI 모델이 아니라 어느 구간에서 멈췄는지 기록하는 것이다.

수익률이 과장되는 원인

일반적인 무작위 분할은 미래 데이터를 학습 세트에 섞을 수 있다.

scikit-learn의 TimeSeriesSplit 공식 문서도 시간 순서가 있는 표본에는 과거로 학습하고 이후 구간으로 평가하는 방식을 안내한다.

수수료, 스프레드, 주문 지연을 빼고 종가 그대로 체결했다고 계산하는 것도 흔한 오류다.

정확도 대신 기간 밖 수익률, 최대 낙폭, 거래 횟수와 비용 차감 후 손익을 함께 저장해야 한다.

방법 사용 시점 핵심 확인값
규칙 전략 주문 연결 첫 검증 신호·체결 일치
지도학습 라벨 기준이 명확할 때 기간 밖 손익
LLM 보조 뉴스 분류가 필요할 때 출력 형식·지연

처음에는 단순 규칙을 기준선으로 만들고 AI가 비용 차감 후에도 개선하는지 비교한다.

1단계 백테스트와 모델 검증

 

 

가격을 시간 오름차순으로 정렬하고, 예측 대상보다 늦게 발표된 데이터는 특징에서 제외한다. 다음 코드는 마지막 20%를 한 번도 학습하지 않은 평가 구간으로 남기는 최소 구조다.

import pandas as pd
from sklearn.ensemble import RandomForestClassifier

df = pd.read_csv("prices.csv", parse_dates=["date"]).sort_values("date")
df["ret1"] = df["close"].pct_change()
df["ma5"] = df["close"].rolling(5).mean() / df["close"] - 1
df["target"] = (df["close"].shift(-1) > df["close"]).astype(int)
df = df.dropna()
cut = int(len(df) * 0.8)
X, y = df[["ret1", "ma5"]], df["target"]
model = RandomForestClassifier(n_estimators=200, random_state=42)
model.fit(X.iloc[:cut], y.iloc[:cut])
print(model.score(X.iloc[cut:], y.iloc[cut:]))

정확도가 높다는 이유만으로 주문하지 않는다. 거래별 비용을 반영한 순손익이 기준 전략보다 나은지, 하락 구간에서도 최대 낙폭이 허용 범위 안인지 확인할 때 쓰는 해결책이다.

2단계 Alpaca 모의주문 연결

Paper Trading 계정에서 발급한 키를 환경 변수로 저장한다.

공식 SDK는 TradingClient(..., paper=True)로 모의 환경을 선택하며, Paper 키와 Live 키를 섞으면 인증에 실패한다.

python -m pip install "alpaca-py==0.44.0"
export APCA_API_KEY_ID="발급받은_PAPER_KEY"
export APCA_API_SECRET_KEY="발급받은_PAPER_SECRET"

아래 예제는 계좌 상태를 조회한 뒤 미국 주식 SPY 1주를 모의 시장가로 제출한다.

실제 주문으로 전환하지 않도록 paper=True를 고정했으며, 시장가는 주문 가격이 보장되지 않는 주문 방식이다.

import os
from alpaca.trading.client import TradingClient
from alpaca.trading.enums import OrderSide, TimeInForce
from alpaca.trading.requests import MarketOrderRequest

client = TradingClient(
    os.environ["APCA_API_KEY_ID"],
    os.environ["APCA_API_SECRET_KEY"],
    paper=True,
)
account = client.get_account()
if account.trading_blocked:
    raise RuntimeError("Trading is blocked")
order = client.submit_order(MarketOrderRequest(
    symbol="SPY", qty=1,
    side=OrderSide.BUY,
    time_in_force=TimeInForce.DAY,
))
print(order.id, order.status)

주문 ID와 상태를 저장할 수 있을 때까지는 AI 신호를 자동 실행에 연결하지 않는다.

실거래 전 재발 방지 점검

 

 

하루 최대 손실, 종목별 최대 보유액, 주문당 수량, 중복 주문 방지 키, 전체 주문 취소 스위치를 코드 밖 설정값으로 둔다.

프로세스 재시작 후에도 마지막 신호와 주문 ID를 읽을 수 있도록 SQLite 같은 영속 저장소를 사용한다.

실시간 체결 상태는 폴링만 하지 말고 TradingStream 공식 문서의 주문 업데이트 스트림으로 대조한다.

네트워크가 끊기면 신규 주문을 중단하고 미체결 주문과 실제 포지션을 다시 조회한 뒤 재개해야 한다.

모의투자는 API 흐름을 검증하는 해결책이고 실제 체결 품질이나 수익을 보장하지 않는다.

최소 수 주 동안 로그·비용·낙폭을 검토한 뒤에도 실거래 전환은 paper=False 한 줄만 바꾸지 말고 별도 키, 별도 설정, 작은 주문 한도로 승인 절차를 거치는 편이 안전하다.

AI 자동매매의 완성 기준은 높은 예측 점수가 아니라 손실 제한과 복구 절차가 실제로 작동하는 상태다.

사진: RDNE Stock project, AlphaTradeZone, Mikhail Nilov, Liza Summer · Pexels

반응형