Backtrader TestStrategy Output Repeating
-
Hi,
I've read a lot here but this is my first post.
I've been tring the backtrader quickstart guide.
The code and source data are all the same with website like copy/paste but the output is not the same and on the other hand my output is repeating the "maperiod=15" after every line in the loop and I couldn't find it why. Any ideas?Here is my code which is no different than the tutorial..
import backtrader as bt # Create a Stratey class TestStrategy(bt.Strategy): params = ( ('maperiod', 15), ('printlog', False), ) def log(self, txt, dt=None, doprint=False): ''' Logging function fot this strategy''' if self.params.printlog or doprint: dt = dt or self.datas[0].datetime.date(0) print('%s, %s' % (dt.isoformat(), txt)) 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) def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: # Buy/Sell order submitted/accepted to/by broker - Nothing to do return # Check if an order has been completed # Attention: broker could reject order if not enough cash if order.status in [order.Completed]: if order.isbuy(): self.log( 'BUY EXECUTED, Price: %.2f, Cost: %.2f Comm: %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') # Write down: no pending order self.order = None def notify_trade(self, trade): if not trade.isclosed: return self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) 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 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 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() def stop(self): self.log('(MA Period %2d) Ending Value %.2f' % (self.params.maperiod, self.broker.getvalue()), doprint=True)
This is my main.py
from __future__ import (absolute_import, division, print_function, unicode_literals) import backtrader as bt import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0]) from TestStrategy import TestStrategy if __name__ == '__main__': cerebro = bt.Cerebro() # Add a strategy strats = cerebro.optstrategy( TestStrategy, maperiod=range(10, 31)) cerebro.addstrategy(TestStrategy) modpath = os.path.dirname(os.path.abspath(sys.argv[0])) datapath = os.path.join(modpath, 'datas/orcl-1995-2014.txt') # Create a Data Feed data = bt.feeds.YahooFinanceCSVData( dataname=datapath, # Do not pass values before this date fromdate=datetime.datetime(2000, 1, 1), # Do not pass values after this date todate=datetime.datetime(2000, 12, 31), reverse=False) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(1000.0) # Add a FixedSize sizer according to the stake cerebro.addsizer(bt.sizers.FixedSize, stake=10) # Set the commission cerebro.broker.setcommission(commission=0.0) # Run over everything cerebro.run(maxcpus=1) # print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) #cerebro.plot(style='candlestick')
Here is the output..
2000-12-29, (MA Period 10) Ending Value 10807.80
2000-12-29, (MA Period 15) Ending Value 10807.80
2000-12-29, (MA Period 11) Ending Value 10731.00
2000-12-29, (MA Period 15) Ending Value 10731.00
2000-12-29, (MA Period 12) Ending Value 10811.00
2000-12-29, (MA Period 15) Ending Value 10811.00
2000-12-29, (MA Period 13) Ending Value 10637.90
2000-12-29, (MA Period 15) Ending Value 10637.90
2000-12-29, (MA Period 14) Ending Value 10557.30
2000-12-29, (MA Period 15) Ending Value 10557.30
2000-12-29, (MA Period 15) Ending Value 953.40
2000-12-29, (MA Period 15) Ending Value 953.40
2000-12-29, (MA Period 16) Ending Value 6922.80
2000-12-29, (MA Period 15) Ending Value 6922.80
2000-12-29, (MA Period 17) Ending Value 10443.70
2000-12-29, (MA Period 15) Ending Value 10443.70
2000-12-29, (MA Period 18) Ending Value 10686.00
2000-12-29, (MA Period 15) Ending Value 10686.00
2000-12-29, (MA Period 19) Ending Value 9572.00
2000-12-29, (MA Period 15) Ending Value 9572.00
2000-12-29, (MA Period 20) Ending Value 9615.10
2000-12-29, (MA Period 15) Ending Value 9615.10
2000-12-29, (MA Period 21) Ending Value 11161.50
2000-12-29, (MA Period 15) Ending Value 11161.50
2000-12-29, (MA Period 22) Ending Value 11220.80
2000-12-29, (MA Period 15) Ending Value 11220.80
2000-12-29, (MA Period 23) Ending Value 9844.60
2000-12-29, (MA Period 15) Ending Value 9844.60
2000-12-29, (MA Period 24) Ending Value 9882.70
2000-12-29, (MA Period 15) Ending Value 9882.70
2000-12-29, (MA Period 25) Ending Value 9882.70
2000-12-29, (MA Period 15) Ending Value 9882.70
2000-12-29, (MA Period 26) Ending Value 11160.70
2000-12-29, (MA Period 15) Ending Value 11160.70
2000-12-29, (MA Period 27) Ending Value 11161.00
2000-12-29, (MA Period 15) Ending Value 11161.00
2000-12-29, (MA Period 28) Ending Value 9851.50
2000-12-29, (MA Period 15) Ending Value 9851.50
2000-12-29, (MA Period 29) Ending Value 9851.50
2000-12-29, (MA Period 15) Ending Value 9851.50
2000-12-29, (MA Period 30) Ending Value 9851.50
2000-12-29, (MA Period 15) Ending Value 9851.50Process finished with exit code 0
-
The problem is that in addition to using
optstrategy
call you are adding yet another instance of the stragegy to the pull by usingaddstrategy
( probably copy/paste error ). It means that during the optimization run, two strategies will always be instantiated for each permutation of parameters ( in your case for each value ofmaperiod
from 10 to 31 ) - one added throughoptstrategy
and the other throughaddstrategy
.So since the '(MA Perios XX)
is printed inside your
stopstrategy's method - each time some strategy instance will complete, its
stop` method will be called and the above log will be printed. -
@vladisld Thank you very much..
your recomendation solved the issue perfectly..