# Create a Stratey
class TestStrategy(bt.Strategy):
params = (
('exitbars', 5),
)
""
def next(self):
# Simply log the closing price of the series from the reference
self.log('Close, %.2f' % self.dataclose[0])
# Check if an order is pending ... if yes, we cannot send a 2nd one
if self.order:
return
# Check if we are in the market
if not self.position:
# Not yet ... we MIGHT BUY if ...
if self.dataclose[0] < self.dataclose[-1]:
# current close less than previous close
if self.dataclose[-1] < self.dataclose[-2]:
# previous close less than the previous close
# BUY, BUY, BUY!!! (with default parameters)
self.log('BUY CREATE, %.2f' % self.dataclose[0])
# Keep track of the created order to avoid a 2nd order
self.order = self.buy()
else:
# Already in the market ... we might sell
if len(self) >= (self.bar_executed + self.params.exitbars):
# SELL, SELL, SELL!!! (with all possible default parameters)
self.log('SELL CREATE, %.2f' % self.dataclose[0])
""
# Add a FixedSize sizer according to the stake
cerebro.addsizer(bt.sizers.FixedSize, stake=10)
""
매개변수를 통해 self.params.exitbars를 사용하였습니다. addsizer를 통해 매매단위를 추가하여 주었습니다. 매매단위는 기본적으로 1로 설정되어 있으며 10으로 변경한 결과 수익이 10배 늘어난것을 확인할 수 있습니다.
# Create a Stratey
class TestStrategy(bt.Strategy):
params = (
('maperiod', 15),
)
def __init__(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataclose = self.datas[0].close
# To keep track of pending orders and buy price/commission
self.order = None
self.buyprice = None
self.buycomm = None
# Add a MovingAverageSimple indicator
self.sma = bt.indicators.SimpleMovingAverage(
self.datas[0], period=self.params.maperiod)
""
def next(self):
# Simply log the closing price of the series from the reference
self.log('Close, %.2f' % self.dataclose[0])
# Check if an order is pending ... if yes, we cannot send a 2nd one
if self.order:
return
# Check if we are in the market
if not self.position:
# Not yet ... we MIGHT BUY if ...
if self.dataclose[0] > self.sma[0]:
# BUY, BUY, BUY!!! (with all possible default parameters)
self.log('BUY CREATE, %.2f' % self.dataclose[0])
# Keep track of the created order to avoid a 2nd order
self.order = self.buy()
else:
if self.dataclose[0] < self.sma[0]:
# SELL, SELL, SELL!!! (with all possible default parameters)
self.log('SELL CREATE, %.2f' % self.dataclose[0])
# Keep track of the created order to avoid a 2nd order
self.order = self.sell()
""
로그를 보면 24일전에 기록이 없는데 기본적으로 15일 이동평균을 활용하였기때문에 16일부터 매매가 시작됩니다.
Backtrader 그래프를 통한 매매확인
cerebro.plot()
아래와 같이 지표를 추가할 수 있습니다.
def __init__(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataclose = self.datas[0].close
# To keep track of pending orders and buy price/commission
self.order = None
self.buyprice = None
self.buycomm = None
# Add a MovingAverageSimple indicator
self.sma = bt.indicators.SimpleMovingAverage(
self.datas[0], period=self.params.maperiod)
# Indicators for the plotting show
bt.indicators.ExponentialMovingAverage(self.datas[0], period=25)
bt.indicators.WeightedMovingAverage(self.datas[0], period=25,
subplot=True)
bt.indicators.StochasticSlow(self.datas[0])
bt.indicators.MACDHisto(self.datas[0])
rsi = bt.indicators.RSI(self.datas[0])
bt.indicators.SmoothedMovingAverage(rsi, period=10)
bt.indicators.ATR(self.datas[0], plot=False)
plot = False를 준다면 화면에 지표가 표시되지는 않습니다. 또 rsi처럼 변수에 넣어준다면 따로 화면에 표시되지 않으며 다른지표(SmootedMovingAverage)에 활용할 수 있습니다.
또 전략은 같은데 이전과 다르게 결과가 나오는것을 볼 수 있는데 추가지표가 모두 생성된 지점부터 매매가 시작되는것을 알 수 있습니다.
Backtrader 최적화
이동평균선의 기간을 변경해가며 결과를 확인할 수 있습니다. 이때 하나의 종목에 과적화 되지 않도록 주의해야하며 여러 전략을 합쳐서 사용할 수 있습니다.
""
# Create a Stratey
class TestStrategy(bt.Strategy):
params = (
('maperiod', 15),
('printlog', False),
)
def __init__(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataclose = self.datas[0].close
# To keep track of pending orders and buy price/commission
self.order = None
self.buyprice = None
self.buycomm = None
# Add a MovingAverageSimple indicator
self.sma = bt.indicators.SimpleMovingAverage(
self.datas[0], period=self.params.maperiod)
""
def stop(self):
self.log('(MA Period %2d) Ending Value %.2f' %
(self.params.maperiod, self.broker.getvalue()), doprint=True)
if __name__ == '__main__':
# Create a cerebro entity
cerebro = bt.Cerebro()
# Add a strategy
strats = cerebro.optstrategy(
TestStrategy,
maperiod=range(10, 31))
# Datas are in a subfolder of the samples. Need to find where the script is
# because it could have been called from anywhere
modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
datapath = os.path.join(modpath, 'orcl-1995-2014.txt')
""
# Run over everything
cerebro.run(maxcpus=1)
cerebro.optstrategy를 통해 파라미터를 변경해 가며 최적화값을 확인해 볼 수 있습니다.
run 옵션에 maxcpus옵션은 cpu코어를 제어합니다.
maxcpus를 사용하지 않을시 모든 cpu사용
maxcpus=1 인경우 멀티코어 사용금지
maxcpus=2 인경우 표시된 코어수를 사용
결과를 살펴보면 18~25 구간의 이동평균선을 사용시 수익이 나는것을 확인 할 수 있습니다.
이제 다양한 데이터를 이용하여 전략을 세우고 최적화하여 자신만의 매매방법을 찾으시면 됩니다.