No output from Optstrategy
-
There is no output from optstrategy running the example in the docs.
Running the optstrategy example in Spyder the stop method is never called.
The code below is taken from the last code example from https://www.backtrader.com/docu/quickstart/quickstart.html
which I have modified to read data from a local CSV.
When I run this example replacing
strats = cerebro.optstrategy( TestStrategy, maperiod=range(10, 31))
with
cerebro.addstrategy(TestStrategy)
I get the expected output as follows:'...018-03-23, Close, 301.54
2018-03-26, Close, 304.18
2018-03-27, Close, 279.18
2018-03-27, (MA Period 15) Ending Value 11136.18
this is stop being called'However when I replace the line
cerebro.addstrategy(TestStrategy)
withstrats = cerebro.optstrategy( TestStrategy, maperiod=range(10, 31))
I get nothing. No output. This is the only change to the code.Code reproduced below in full :
from __future__ import (absolute_import, division, print_function, unicode_literals) import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0]) # Import the backtrader platform import backtrader as bt import backtrader.feeds as btfeeds # Create a Stratey class TestStrategy(bt.Strategy): params = ( ('maperiod', 15), ('printlog', True) ) 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) 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: # Sell 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 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() def stop(self): self.log('(MA Period %2d) Ending Value %.2f' % (self.params.maperiod, self.broker.getvalue()), doprint=True) print('this is stop being called') if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro() # Add a strategy strats = cerebro.optstrategy( TestStrategy, maperiod=range(10, 31)) # cerebro.addstrategy(TestStrategy) # Datas are in a subfolder of the samples. Need to find where the script is # because it could have been called from anywhere # Create a Data Feed modpath = os.path.dirname(os.path.abspath(sys.argv[0])) fileName = os.path.join(modpath,'returnsData\\TSLA.csv') # Create a Data Feed data = btfeeds.GenericCSVData(dataname=fileName,dtformat=('%Y-%m-%d'), datetime=0, high=2, low=3, open=1, close=4, volume=5, openinterest=-1 ) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(10000.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()
Any idea why there is no output for the Optstrategy?
-
Because you are shooting yourself in the foot by using
Spyder
, Windows and not using Google. (the 1st of the 3 is the actual real culprit, no matter how much you may hate Microsoft, or not ...)See here for the last time someone asked about the same lines: https://community.backtrader.com/topic/821/problem-while-getting-started/
-
Thank you for the answer. However the Optimizer doesn't call the stop method in Ubuntu / native python either.
The output from the code below is
Do you know why the stop method isn't called?Here is the code, based on your example, modified for local data and unix filenames
from __future__ import (absolute_import, division, print_function, unicode_literals) import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0]) # Import the backtrader platform import backtrader as bt import backtrader.feeds as btfeeds # Create a Stratey class TestStrategy(bt.Strategy): params = ( ('maperiodShort', 10), ('maperiodLong', 30), ) def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = dt or self.datas[0].datetime.date(0) #print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): print ('Starting test strategy', self.params.maperiodShort, " -=- ", self.params.maperiodLong) # 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.smaS = bt.indicators.SimpleMovingAverage( self.datas[0], period=self.params.maperiodShort) self.smaL = bt.indicators.SimpleMovingAverage( self.datas[0], period=self.params.maperiodLong) 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: # Sell 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') 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]) - commented out as verbose # 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.smaS[0] > self.smaL[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.smaL[0] > self.smaS[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) if __name__ == '__main__': print ('Starting OPTIMIZER') # Create a cerebro entity cerebro = bt.Cerebro() # Add a strategy strats = cerebro.optstrategy( TestStrategy, maperiodShort=range(5, 15)) # set up paths tp csv data modpath = os.path.dirname(os.path.abspath(sys.argv[0])) fileName = os.path.join(modpath,'returnsData/TSLA.csv') # Create a Data Feed data = btfeeds.GenericCSVData(dataname=fileName,dtformat=('%Y-%m-%d'), datetime=0, high=2, low=3, open=1, close=4, volume=5, openinterest=-1 ) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(10000.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()
-
Update:
The stop method isn't called as the Python spacing/tabs is wrong (This is wrong in the example on your Quickstart page so you might want to fix it). However fixng this causes the stop method to be called which then causes another error:
<<
File "C:/Users/Delta/.spyder/optTemplate001.py", line 166, in <module>
cerebro.run()File "C:\ProgramData\Anaconda3\lib\site-packages\backtrader\cerebro.py", line 1143, in run
for r in pool.imap(self, iterstrats):File "C:\ProgramData\Anaconda3\lib\multiprocessing\pool.py", line 695, in next
raise valueTypeError: log() got an unexpected keyword argument 'doprint'>>
This error is to be expected as the self.log function doesn't have that argument.
def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = dt or self.datas[0].datetime.date(0) #print('%s, %s' % (dt.isoformat(), txt))
A workaround is to replace the log in the stop function with a print statement although this isn't ideal.
With the workaround this program works on Ubuntu/native python and windows/pycharm environments.
As you correctly pointed out Spyder on Anaconda doesn't work.
-
@mhotrx said in No output from Optstrategy:
This is wrong in the example on your Quickstart page so you might want to fix it
If you really believe to have found something wrong, you might want to give us a pointer as to where.
In any case:
- There are no tabs
- The
log
method definition for the optimization is as follows
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))
which clearly takes parameters, named and unnamed. See it for yourself: Docs - Quickstart and specifically Docs - Quickstart - Let's Optimize
Plausible explanation: You have mixed content from different files
And seeing the formatting of the code you have posted, it seems a miracle that it does something at all. Please see the top of the forum for posting code blocks and output blocks. It will make your life a lot easier.