백테스트로 전략 평가하기#
백테스팅 시스템 컴포넌트 개요#
pyqqq.backtest 모듈은 다음과 같은 주요 컴포넌트들로 구성되어 있습니다:
핵심 컴포넌트#
Environment: 트레이딩 시스템의 실행 환경을 정의
BacktestEnvironment
: 백테스팅을 위한 가상 환경KISDomesticEnvironment
: 국내주식 실거래 환경KISOverseasEnvironment
: 해외주식 실거래 환경
Broker: 주문 처리와 시장 데이터 조회를 담당
MockBroker
: 백테스팅용 가상 브로커TradingBroker
: 실제 거래 실행 브로커
PositionProvider: 포지션 정보 관리
ManualPositionProvider
: 수동 포지션 관리BackPositionProvider
: DB 기반 포지션 관리KISPositionProvider
: 실시간 포지션 조회
WallClock: 시스템의 시간 관리
실시간 모드: 실제 시간 기준 동작
백테스트 모드: 가상 시간 기준 동작
Strategy: 실제 트레이딩 로직 구현
BaseStrategy
: 모든 전략의 기본 클래스
컴포넌트 간 관계#
Environment
├── WallClock (시간 관리)
└── Broker (주문 처리)
└── PositionProvider (포지션 관리)
Strategy
├── Environment 참조
└── 실제 매매 로직 구현
Step 1: 전략 구현 및 백테스팅#
1.1 전략 코드 작성#
5분 이동평선을 돌파하면 매수하고, %3 수익이 나면 매도하는 간단한 전략을 구현합니다.
# strategy.py
from pyqqq.backtest.environment import BacktestEnvironment
from pyqqq.backtest.strategy import BaseStrategy
from pyqqq.datatypes import OrderSide, OrderType
from pyqqq.utils.market_schedule import is_trading_time
import asyncio
import datetime as dtm
class SimpleBreakoutStrategy(BaseStrategy):
"""5분봉 돌파 매매 전략"""
def __init__(self, environment, symbol="168360"):
super().__init__(environment)
self.symbol = symbol
async def run(self):
while self.clock.is_alive():
try:
if is_trading_time(self.clock.now()):
self.on_trade()
await self.clock.sleep(60)
except Exception as e:
self.logger.exception(f"Error in strategy: {e}")
await self.clock.sleep(60)
def on_trade(self):
positions = self.broker.get_positions()
current_price = self.broker.get_price(self.symbol)
# 현재 포지션 확인
position = next((p for p in positions if p.asset_code == self.symbol), None)
df = self.broker.get_minute_price(self.symbol)
if len(df) < 5:
return
df["ma5"] = df["close"].rolling(5).mean()
ohlcv = df.iloc[-1]
ma5 = df["ma5"].iloc[-1]
open = ohlcv["open"]
close = ohlcv["close"]
if not position and close > ma5 and ma5 > open:
# 매수 신호
quantity = int(10_000_000 / current_price) # 1천만원어치
self.broker.create_order(self.symbol, OrderSide.BUY, quantity, OrderType.MARKET)
self.logger.info(f"매수 주문: {quantity}주 @ {current_price}")
elif position and position.current_pnl > 3:
# 매도 신호
for position in positions:
if position.asset_code == self.symbol:
self.broker.create_order(self.symbol, OrderSide.SELL, position.quantity, OrderType.MARKET)
self.logger.info(f"매도 주문: {position.quantity}주 @ {current_price}")
1.2 백테스팅 실행#
# backtest.py
import asyncio
import datetime as dtm
from pyqqq.backtest.environment import BacktestEnvironment
from strategy import SimpleBreakoutStrategy
async def run_backtest():
# 백테스팅 환경 설정
env = BacktestEnvironment(
start_time=dtm.datetime(2024, 10, 2, 9, 0),
end_time=dtm.datetime(2024, 10, 22, 15, 30),
time_unit="minutes",
)
# 초기 자본금 설정
env.get_broker().set_initial_cash(100_000_000) # 1억원
# 전략 실행
strategy = SimpleBreakoutStrategy(env)
await strategy.run()
# 결과 분석
broker = env.get_broker()
# 1. 전체 거래 이력 분석
report = broker.show_trading_history_report(make_file=True)
print(f"- 총 거래횟수: {report['count']}")
print(f"- 총 수익률: {report['total_pnl']:.2f}%")
print(f"- 평균 수익률: {report['avg_pnl']:.2f}%")
print(f"- ROI: {report['roi']:.2f}")
# 2. 최종 포지션 확인
broker.show_positions()
if __name__ == "__main__":
asyncio.run(run_backtest())
1.3 백테스트 결과 분석#
백테스트 결과를 바탕으로 다음 사항들을 검토합니다:
수익성
총 수익률과 ROI 확인
개별 거래의 평균 수익률 검토
최대 손실폭과 수익폭 확인
리스크 관리
최대 손실 시점 분석
연속 손실 구간 확인
포지션 크기의 적절성 검토
전략 개선점 도출
매매 타이밍 최적화
손절/익절 전략 추가 검토
포지션 사이징 조정
Step 2: 실전 거래 준비 및 실행#
2.1 계좌 설정#
한국투자증권 계좌 및 API 키 발급
환경변수 설정:
# 실전 계좌
export KIS_APP_KEY="your-app-key"
export KIS_APP_SECRET="your-app-secret"
export KIS_CANO="your-account-number"
export KIS_ACNT_PRDT_CD="your-product-code"
# 모의 계좌 (선택)
export PAPER_KIS_APP_KEY="your-paper-app-key"
export PAPER_KIS_APP_SECRET="your-paper-app-secret"
export PAPER_KIS_CANO="your-paper-account-number"
export PAPER_KIS_ACNT_PRDT_CD="your-paper-product-code"
2.2 모의투자 테스트#
백테스트에서 검증된 전략을 모의투자로 먼저 테스트합니다.
# paper_trading.py
import asyncio
from pyqqq.backtest.environment import KISDomesticEnvironment
from strategy import SimpleBreakoutStrategy
async def run_paper_trading():
# 모의투자 환경 설정
env = KISDomesticEnvironment(paper_trading=True)
# 전략 실행
strategy = SimpleBreakoutStrategy(env)
await strategy.run()
if __name__ == "__main__":
asyncio.run(run_paper_trading())
2.3 실전 거래 실행#
모의투자에서 충분히 검증된 후 실전 거래를 시작합니다.
# live_trading.py
import asyncio
from pyqqq.backtest.environment import KISDomesticEnvironment
from strategy import SimpleBreakoutStrategy
async def run():
# 실전 환경 설정
env = KISDomesticEnvironment(paper_trading=False)
# 전략 실행
strategy = SimpleBreakoutStrategy(env)
await strategy.run()
if __name__ == "__main__":
asyncio.run(run())