반응형

Backtrader에서 Indicator란 간단하게는 시가, 종가, 저가, 고가같은 가격정보나 이동평균선이나

볼린저 차트같은 지수까지를 아우르는 지표를 말한다. Strategy 클래스에서 __init__에서 정의하거나

실제 거래가 진행되는 next 메서드에서 정의 할 수 있다. 

메모리 절약을 위해서는 기본적으로 __init__ 메서드에서 정의하는것이 좋다.

 

종가가 20일 이동평균선을 상향 돌파할 때 매수를 진행하는 함수를 짜기 위해 종가를 나타내는 Indicator와

20일 이평선을 나타내는 Indicator를 __init__에 입력해보자.

lass MyStrategy(bt.Strategy):
    def __init__(self):
        self.dataclose = self.datas[0].close
        self.SMA = bt.indicators.MovingAverageSimple(period=20)

self.dataclose = self.datas[0].close에서 datas[0]은 설정한 데이터프레임에서 [0]일 전 데이터를 말하고

뒤의 .close는 종가를 의미한다. 즉 self.datas[0].close는 기준일의 종가 데이터를 의미한다.

 

 

BackTrader는 설정된 Indicator를 자동으로 Plotting한다. 한번 run 해보면 아래와 같이 20일 이동평균선이 추가된 것을 확인 할 수 있다. 

 

그럼 이제 본격적으로 next 메서드를 통해 실제로 거래를 진행해보도록 하자. 방법은 매우 간단하다.

next에서 buy 메서드나 sell 메서드를 통해 거래를 진행하게되면, order가 발생하게 된다.

이 oreder가 조건을 만족하게 되면 실제 거래가 진행되던지 거래가 거절되던지 하는 것이다.

간단하게 종가가 20일 이평선을 상향 돌파하면 매수가 진행되는 코드를 짜보도록 하자.

 

종가가 20일 이평선을 상향 돌파한다는 것은, 기준일 전일에는 종가가 20일 이평선 아래에 있고, 기준일 당일에는 종가가 20일 이평선 위에 있으면 된다. 즉 아래와 같다.

    def next(self):
        if self.dataclose[-1] < self.SMA[-1]:
            if self.dataclose[0] > self.SMA[0]:
                self.order = self.buy()

실행해보면 아래와 같이 플로팅 된다. 녹색 화살표가 매수 포인트이다.

뭔가 이상한점을 찾을 수 있다. 종가가 이평선을 돌파한 당일 매매가 이루어지는게 아니라. 그 다음날 매매가 이루어졌다. 이는 Buy에서 파라미터들을 따로 설정해주지 않았기 때문에 기본값인 시장가 매수가 진행된것으로, 매수 시그널이 발생한 다음날 시가로 매매가 이루어졌기 때문이다. 이는 buy메서드의 설정으로 변경이 가능한데, 위 plot 으로는 자세한 설정의 확인이 힘들다. 

다음장에서는 Order의 상태를 확인하는 notify_order 메서드와, 거래상태를 확인하는 log를 만들어 보도록 하자.

 

*최종코드

import backtrader as bt
import helper

class MyStrategy(bt.Strategy):
    def __init__(self):
        self.dataclose = self.datas[0].close
        self.SMA = bt.indicators.MovingAverageSimple(period=20)

    def next(self):
        if self.dataclose[-1] < self.SMA[-1]:
            if self.dataclose[0] > self.SMA[0]:
                self.order = self.buy()

if __name__ == "__main__":
    cerebro = bt.Cerebro()
    cerebro.addstrategy(MyStrategy)
    df = helper.ohlcv_data()
    data = bt.feeds.PandasData(dataname=df)
    cerebro.adddata(data)
    cerebro.broker.setcash(20000000)
    cerebro.run()
    cerebro.plot(style='candle', barup='red', bardown='blue')

 

 

 

 

반응형

+ 최근 글