본문 바로가기
생활정보

[퀀트 프로그래밍 공부] 파이썬 Backtrader라이브러리를 할용한 백테스팅

by 1분유용정보 2023. 3. 13.
반응형

이 코드는 backtrader 라이브러리를 사용하여 두 개의 단순 이동 평균(SMA)을 기반으로 간단한 거래 전략을 구현하는 Python 알고리즘 소스입니다. 본 포스팅에서는 간단하게 기본적인 흐름을 볼 수 있는 오픈 소스를 활용하여  Yahoo Finance에서 삼성전자 종목 주식에 대한 과거 데이터(2020.1.1~현재)를 가져와 SMA CrossOver 전략을 적용하고 결과를 출력해 보았습니다.

퀀트 Python 백테스팅 알고리즘 소스 기본적인 구조 및 흐름 

  • Strategy : 거래를 진행하게되는 전략을 수립하는 부분
  • Data Feeds : 거래의 기초가 되는 데이터로  OHLCV 데이터 형태를 가져 온다.
  • Broker : 거래를 진행하는 주체로 자본, 수수료등 실제 거래의 요소들을 설정.
  • Cerebro : 데이터와 전략을 이용해 브로커가 거래를 진행

notify_order() 메서드는 브로커가 주문을 실행할 때 호출되며, 매수 또는 매도, 포지션 크기, 주가, 현금 및 포트폴리오 가치와 같은 주문 세부 정보를 기록합니다.

 

Data Feeds, Strategy Broker 를 조정하는 백트레이더 엔진인 'Cerebro' 인스턴스를 생성한 후, 브로커의 초기 현금과 수수료를 설정하고 'Cerebro' 인스턴스에 데이터 피드와 거래 전략을 추가합니다.

 

'Cerebro' 인스턴스를 실행한 후 스크립트는 포트폴리오의 시작 및 최종 값과 수익률을 백분율로 출력한 후, Cerebro 인스턴스의 plot() 메서드를 사용하여 과거 데이터와 거래 신호를 플로팅합니다.

 

cerebro.broker.setcash(100000)
cerebro.broker.setcommission(0.002)

cash: 초기 자본은 100,000으로 설정

매매 수수료: 0.002% 설정

 

 

퀀트 Python 알고리즘 전체 소스 코드

from datetime import datetime
import backtrader as bt
import locale

locale.setlocale(locale.LC_ALL, 'ko_KR')

# Create a subclass of Strategy to define the indicators and logic
class SmaCross(bt.Strategy):
    # list of parameters which are configurable for the strategy
    params = dict(
        pfast=5,  # period for the fast moving average
        pslow=30  # period for the slow moving average
    )

    def __init__(self):
        sma1 = bt.ind.SMA(period=self.p.pfast)  # fast moving average
        sma2 = bt.ind.SMA(period=self.p.pslow)  # slow moving average
        self.crossover = bt.ind.CrossOver(sma1, sma2)  # crossover signal

        self.holding = 0

    def next(self):
        current_stock_price = self.data.close[0]

        if not self.position:  # not in the market
            if self.crossover > 0:  # if fast crosses slow to the upside
                available_stocks = self.broker.getcash() / current_stock_price
                self.buy(size=1)

        elif self.crossover < 0:  # in the market & cross to the downside
            self.close()  # close long position

    def notify_order(self, order):
        if order.status not in [order.Completed]:
            return

        if order.isbuy():
            action = 'Buy'
        elif order.issell():
            action = 'Sell'

        stock_price = self.data.close[0]
        cash = self.broker.getcash()
        value = self.broker.getvalue()
        self.holding += order.size

        print('%s[%d] holding[%d] price[%d] cash[%.2f] value[%.2f]'
              % (action, abs(order.size), self.holding, stock_price, cash, value))

cerebro = bt.Cerebro()  # create a "Cerebro" engine instance
cerebro.broker.setcash(100000)
cerebro.broker.setcommission(0.002)

# Create a data feed
data = bt.feeds.YahooFinanceData(dataname='005930.KS',
                                 fromdate=datetime(2020, 1, 1),
                                 todate=datetime.now())

cerebro.adddata(data)  # Add the data feed

cerebro.addstrategy(SmaCross)  # Add the trading strategy

start_value = cerebro.broker.getvalue()
cerebro.run()  # run it all
final_value = cerebro.broker.getvalue()

print('* start value : %s won' % locale.format_string('%d', start_value, grouping=True))
print('* final value : %s won' % locale.format_string('%d', final_value, grouping=True))
print('* earning rate : %.2f %%' % ((final_value - start_value) / start_value * 100.0))

cerebro.plot(style='candle', barup='red', bardown='blue') # and plot it with a single command

 

결과 출력

Buy[1] holding[1] price[66708] cash[33354.76] value[100063.18]
Sell[1] holding[0] price[66414] cash[99440.24] value[99440.24]
Buy[1] holding[1] price[65531] cash[33384.76] value[98915.98]
Sell[1] holding[0] price[63961] cash[97120.55] value[97120.55]
Buy[1] holding[1] price[59713] cash[36001.65] value[95715.44]
Sell[1] holding[0] price[60207] cash[95596.01] value[95596.01]
Buy[1] holding[1] price[60108] cash[34872.72] value[94981.31]
Sell[1] holding[0] price[58233] cash[93186.54] value[93186.54]
Buy[1] holding[1] price[54857] cash[38020.65] value[92877.67]
Sell[1] holding[0] price[58832] cash[96239.25] value[96239.25]
Buy[1] holding[1] price[60500] cash[35117.25] value[95617.25]
Sell[1] holding[0] price[61300] cash[97292.65] value[97292.65]
* start value : 100,000 won
* final value : 97,292 won
* earning rate : -2.71 %

 

과거 데이터와 거래 신호를 플로팅

백테스트 결과

 

 

전반적으로 이 코드는 backtrader 라이브러리를 사용하여 기술 지표를 기반으로 거래 전략을 백테스팅하기 위한 기본 프레임워크를 알 수 있습니다. 그러나 실제 거래를 위한 위험 관리 또는 기타 중요한 기능이 포함되어 있지 않으므로 광범위한 수정 및 테스트 없이는 실시간 거래에 사용할 수는 없습니다.

 구글 미트(Google Meet) 다운로드 및 사용법 (PC버전)

교보문고 매장별 재고 확인 하는 방법

반응형

댓글