본문 바로가기
  • "Backtest, backtest, backtest." - Martin Schwartz
[백테스팅] 소개

Python의 Backtesting.py 라이브러리를 사용한 백테스팅 거래 전략

by Eirene 2023. 3. 30.
반응형

Python의 Backtesting.py 라이브러리를 사용한 백테스팅 거래 전략

Python의 Backtesting.py 라이브러리를 사용하여 거래 전략을 백테스트하는 방법을 기술 합니다. 이 포괄적인 가이드는 백테스팅의 기초에 대해 간단한 예제와 함께 다루도록 하겠습니다.

 

Backtesting.py 소개

Backtesting.py는 거래 전략을 백테스트하기 위해 설계된 Python 라이브러리입니다. 오픈 소스이며 연구 및 생산 환경 모두에 사용할 수 있습니다. Backtesting.py는 벡터화 및 이벤트 기반 백테스팅을 모두 지원하며 거래 전략을 분석하기 위한 광범위한 성능 지표를 제공합니다.

백테스팅은 과거 데이터에 적용하여 거래 전략의 성과를 평가하는 프로세스입니다. 즉, 특정 시장 조건이 주어졌을 때 과거에 거래 전략이 어떻게 수행되었을 것인지에 대한 시뮬레이션입니다. 

 

Backtesting.py 기본 사용법

설치

Backtesting.py를 설치하려면 Python용 패키지 관리자인 pip를 사용할 수 있습니다. 터미널 또는 명령 프롬프트를 열고 다음 명령을 입력합니다.

!pip install backtesting

또한 기술적 분석을 위해서 TA-Lib 라이브러를 설치 합니다.

sudo apt-get install libta-lib-dev
pip install TA-Lib
만약에 Colab에서 실행 하신다면 아래 명령어를 통해서 TA-Lib 라이브러리를 설치 할 수 있습니다.
# download TA-Lib 
!wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz 
!tar xvzf ta-lib-0.4.0-src.tar.gz
import os
os.chdir('ta-lib') # Can't use !cd in co-lab
!./configure --prefix=/usr
!make
!make install
os.chdir('../')

!pip install TA-Lib​

 

라이브러리 로드 및 전략 클래스 살펴 보기

Backtesting.py를 사용하는 첫 번째 단계는 Python 코드로 가져오는 것입니다. 코드 시작 부분에 다음 줄을 추가하여 이 작업을 수행할 수 있습니다.

from backtesting import Backtest, Strategy

그런 다음 'Strategy' 클래스에서 상속되는 클래스로 거래 전략을 정의해야 합니다. 'Strategy' 클래스에는 자체 거래 논리를 구현하기 위해 재정의할 수 있는 여러 메서드가 있습니다.

 

다음은 종가가 50일 이동 평균을 넘어설 때 주식을 매수하는 간단한 거래 전략의 예입니다.

class MyStrategy(Strategy):
    def init(self):
        self.ma = self.I(talib.SMA, self.data.Close, 50)
    
    def next(self):
        if self.data.Close[-1] > self.ma[-1]:
            self.buy()

위의 코드에서는 먼저 talib.SMA 함수를 사용하여 종가의 50일 이동 평균을 계산하는 ma 변수를 정의합니다. 그 다음 next 메소드에서는 현재 종가가 50일 이동 평균보다 높은지 확인하고, 그렇다면 buy 메소드를 호출하여 주식을 매수합니다.

 

과거 주식 데이터 로드 

거래 전략을 백테스트하기 전에 과거 데이터를 Backtesting.py에 로드해야 합니다. 라이브러리는 CSV 파일, Pandas 데이터 프레임 및 사용자 지정 데이터 피드를 포함하여 데이터를 로드하는 여러 방법을 지원합니다.

다음은 CSV 파일에서 과거 주가를 로드하는 방법의 예입니다.

from backtesting import Backtest

ohlcv = pd.read_csv('AAPL.csv', index_col=0, parse_dates=True)
bt = Backtest(ohlcv, MyStrategy)
위의 코드에서는 먼저 pd.read_csv 함수를 사용하여 CSV 파일에서 Apple Inc.의 과거 주가를 로드합니다. 그런 다음 다음을 전달하여 Backtest 개체를 만듭니다. 참고로 CSV 파일은 아래와 같은 형태 입니다.
Date,Open,High,Low,Close,Volume
2022-01-01,175.54,179.82,173.73,179.81,8000000
2022-01-02,181.23,182.89,175.56,181.72,6000000
2022-01-03,182.33,185.38,181.15,183.87,7000000
2022-01-04,184.24,186.42,183.01,184.88,5000000
2022-01-05,184.87,185.92,182.65,184.24,4000000
...​

 

데이터를 CSV 파일에서 가져 올수도 있지만, yfinance 라이브러리를 통해서 가져 올수도 있습니다.

import yfinance as yf
from backtesting import Backtest, Strategy

ticker = yf.Ticker("AAPL")
start_date = "2022-01-01"
end_date = "2022-12-31"
ohlcv = ticker.history(start=start_date, end=end_date)

bt = Backtest(ohlcv, MyStrategy, cash=10000, commission=.002)

 

간단한 거래 전략 구현

과거 데이터를 불러오면 Backtest 객체를 생성하고 이를 전략 클래스에 전달하여 거래 전략을 백테스트할 수 있습니다. 다음은 Apple Inc.의 과거 주가를 사용하여 'MyStrategy' 클래스를 백테스트하는 방법의 예입니다.

import yfinance as yf
from backtesting import Backtest, Strategy

class MyStrategy(Strategy):
    def init(self):
        self.ma = self.I(talib.SMA, self.data.Close, 50)
    
    def next(self):
        if self.data.Close[-1] > self.ma[-1]:
            self.buy()

ticker = yf.Ticker("AAPL")
start_date = "2022-01-01"
end_date = "2022-12-31"
ohlcv = ticker.history(start=start_date, end=end_date)

bt = Backtest(ohlcv, MyStrategy, cash=10000, commission=.002)
results = bt.run()
위의 코드에서 먼저 yfinance 라이브러리를 가져오고 관심 주식에 대한 Ticker 개체를 생성합니다(이 예에서는 AAPL). 그런 다음 'Ticker' 개체의 'history' 메서드를 사용하여 주식의 과거 주가를 로드합니다. start 및 end 인수는 로드할 데이터의 시간 범위를 지정하며 "2022-01-01" 및 "2022-12-31"은 2022년에 사용할 수 있는 전체 기록 데이터를 나타냅니다.
그런 다음 talib 라이브러리를 사용하여 종가의 50일 단순 이동 평균(SMA)을 계산하는 MyStrategy라는 간단한 거래 전략을 정의합니다. 현재 종가가 이동 평균보다 높으면 주식을 매수합니다.로드된 과거 주가(ohlcv), 거래 전략 클래스(MyStrategy), 초기 현금 $10,000, 수수료율 0.2%로 Backtest 개체를 만듭니다. 전략을 백테스트하기 위해 run 메서드를 호출하고 결과를 results 변수에 저장합니다.

 

거래 전략의 성과 분석

Backtesting.py는 거래 전략의 성과를 분석하기 위한 광범위한 성과 지표를 제공합니다. 가장 일반적으로 사용되는 메트릭은 다음과 같습니다.

  • 누적 수익률: 백테스팅 기간 동안 거래 전략의 총 수익률
  • 샤프 비율: 거래 전략의 수익을 무위험 투자의 수익과 비교하는 위험 조정 성과 측정
  • 최대 드로다운: 고점에서 저점까지 거래 전략 가치의 최대 백분율 하락
  • 손익(PnL) 분포: 가장 수익성이 높은 거래와 가장 수익성이 낮은 거래를 식별하는 데 도움이 되는 거래 전략의 손익 히스토그램

다음은 Backtesting.py의 성능 메트릭을 사용하여 MyStrategy 클래스의 성능을 분석하는 방법의 예입니다.

import yfinance as yf
from backtesting import Backtest, Strategy

class MyStrategy(Strategy):
    def init(self):
        self.ma = self.I(talib.SMA, self.data.Close, 50)
    
    def next(self):
        if self.data.Close[-1] > self.ma[-1]:
            self.buy()

ticker = yf.Ticker("AAPL")
start_date = "2022-01-01"
end_date = "2022-12-31"
ohlcv = ticker.history(start=start_date, end=end_date)

bt = Backtest(ohlcv, MyStrategy, cash=10000, commission=.002)
results = bt.run()

# Print all performance metrics
print(results)

# Plot backtesting result
bt.plot()

위의 코드에서 먼저 이전과 같이 Apple Inc.의 과거 주가를 사용하여 'MyStrategy' 클래스를 백테스트합니다. 그런 다음 results 변수에서 print 함수를 호출하여 모든 성능 메트릭을 인쇄합니다.

 

results 변수의 get_analysis 메서드를 호출하여 요약 성능 메트릭을 인쇄합니다.

Start                     2022-01-03 00:00...
End                       2022-12-30 00:00...
Duration                    361 days 00:00:00
Exposure Time [%]                   78.087649
Equity Final [$]                  7693.205534
Equity Peak [$]                  10623.630222
Return [%]                         -23.067945
Buy & Hold Return [%]              -28.199508
Return (Ann.) [%]                  -23.148282
Volatility (Ann.) [%]               25.437453
Sharpe Ratio                              0.0
Sortino Ratio                             0.0
Calmar Ratio                              0.0
Max. Drawdown [%]                  -28.898237
Avg. Drawdown [%]                  -28.898237
Max. Drawdown Duration      277 days 00:00:00
Avg. Drawdown Duration      277 days 00:00:00
# Trades                                    1
Win Rate [%]                              0.0
Best Trade [%]                      -23.36838
Worst Trade [%]                     -23.36838
Avg. Trade [%]                      -23.36838
Max. Trade Duration         283 days 00:00:00
Avg. Trade Duration         283 days 00:00:00
Profit Factor                             0.0
Expectancy [%]                      -23.36838
SQN                                       NaN
_strategy                          MyStrategy
_equity_curve                             ...
_trades                      Size  EntryBa...
dtype: object

 

다음은 print(results)에 의해 인쇄된 각 성능 메트릭에 대한 간략한 설명입니다.

  • Start : 시작 - 백테스트 기간의 시작 날짜
  • End : 종료 - 백테스트 기간의 종료일
  • Duration : 백테스트 기간
  • Exposure Time [%] : 노출 시간[%] - 백테스트 기간 동안 전략이 시장에 노출된 시간의 비율
  • Equity Final [$] : 백테스트의 최종 에퀴티(달러)
  • Equity Peak [$] : 백테스트 동안 도달한 최고 자산(달러)
  • Return [%] : 수익률[%] - 백테스트의 총 수익률을 백분율로 나타냄
  • Buy & Hold Return [%]: 같은 기간 동안 Buy & Hold 전략의 수익률을 백분율로 나타냄
  • Return (Ann.) [%]: 백테스트의 연간 수익률을 백분율로 나타냄
  • Volatility (Ann.) [%]: 백분율로 나타낸 백테스트의 연간 변동성
  • Sharpe Ratio: 백테스트의 샤프 비율
  • Sortino Ratio: 백테스트의 Sortino 비율
  • Calmar Ratio: 백테스트의 Calmar 비율
  • Max. Drawdown [%] : 최대. 드로다운[%] - 백테스트의 최대 드로다운을 백분율로 나타냄
  • Avg. Drawdown [%] : 평균. 드로다운[%] - 백테스트의 평균 드로다운을 백분율로 나타냄
  • Max. Drawdown Duration : 최대. 드로다운 기간 - 최대 드로다운 기간
  • Avg. Drawdown Duration : 평균. 드로다운 기간 - 드로다운의 평균 기간
  • # Trades: 백 테스트 동안 이루어진 총 거래 개수
  • Win Rate [%] : 승률[%] - 이익이 발생한 거래의 비율
  • Best Trade [%] : 베스트 트레이드[%] - 베스트 트레이드의 수익률
  • Worst Trade [%] : 최악의 거래[%] - 최악의 거래의 수익률
  • Avg. Trade [%] : 평균. 거래 [%] - 거래당 평균 수익률
  • Max. Trade Duration : 최대. 거래 기간 - 가장 긴 거래 기간
  • Avg. Trade Duration : 평균. 거래 기간: 거래의 평균 기간
  • Profit Factor : 백테스트의 이익 계수
  • Expectancy [%] : 기대 [%] - 거래당 평균 수익률로 승률을 조정
  • SQN: 백테스트의 시스템 품질 번호
  • _strategy: 백테스트에 사용된 전략의 이름
  • _equity_curve: 백테스트의 에퀴티 커브
  • _trades: 백테스트 동안 이루어진 각 거래의 세부 정보

 

또한 bt.plot() 함수를 통해 아래와 같이 상호작용이 가능한 차트도 출력 합니다.

Backtesting.py 라이브러리 기반 백테스팅 결과 화면

 

Backtest() 클래스 상세 작성

backtesting.py 라이브러리의 Backtest 클래스 생성자는 백테스트를 초기화하는 데 사용됩니다. 'data'와 'strategy'라는 두 가지 인수가 필요합니다.  백테스트에 사용되는 데이터 형식 및 시간대를 사용자 정의할 수 있는 data_format, datetime_format, time_delta 및 timezone과 같이 생성자에 전달할 수 있는 몇 가지 선택적 인수도 있습니다.

'data'는 백테스트되는 보안 또는 자산에 대한 과거 OHLCV(Open, High, Low, Close 및 Volume) 가격 데이터를 포함하는 pd.DataFrame 객체입니다. DataFrame의 인덱스는 날짜/시간 인덱스 또는 단순 범위 인덱스일 수 있습니다.

전략은 backtesting.backtesting.Strategy의 하위 클래스입니다. 이것은 제공된 과거 데이터에서 테스트할 거래 전략입니다.

 

다음을 포함하여 Backtest 생성자에 전달할 수 있는 몇 가지 선택적 매개변수가 있습니다.

  • cash: 백테스트를 시작할 초기 현금 금액입니다..
  • commission: 백테스트 동안 이루어진 거래에 대한 수수료 비율입니다.
  • margin: 레버리지 계정에 필요한 증거금(비율)입니다.
  • trade_on_close: True인 경우 시장가 주문은 다음 바의 시가 대신 현재 바의 종가를 기준으로 체결됩니다.
  • hedging: 참인 경우 백 테스트를 통해 양방향으로 동시에 거래가 이루어질 수 있습니다. 'False'인 경우 반대편 주문은 먼저 FIFO 방식으로 기존 거래를 청산합니다.
  • exclusive_orders: True인 경우 각각의 새 주문은 이전 거래 또는 포지션을 자동으로 청산하여 주어진 시간에 기껏해야 단일 거래(롱 또는 숏)가 열릴 수 있습니다.

기본적으로 Backtest는 성능 분석 및 시각화를 위해 Pyfolio를 사용하지 않습니다. 그러나 pyfolio 매개변수를 True로 설정하여 Pyfolio 통합을 활성화할 수 있습니다.

Backtest() 클래스 생성자에서 이러한 인수를 지정하여 거래 전략 및 과거 데이터에 맞게 백테스트의 매개변수를 사용자 정의할 수 있습니다.

 

 

728x90
반응형

댓글