Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    No output from Optstrategy

    General Code/Help
    2
    5
    2383
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      mhotrx last edited by

      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)
      with strats = 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?

      1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators last edited by

        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/

        1 Reply Last reply Reply Quote 0
        • M
          mhotrx last edited by

          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
          0_1523533812868_077991d2-e298-4c5a-8c39-df5574f7274e-image.png
          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()
          
          1 Reply Last reply Reply Quote 0
          • M
            mhotrx last edited by

            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 value

            TypeError: 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.

            1 Reply Last reply Reply Quote 0
            • B
              backtrader administrators last edited by backtrader

              @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.

              1 Reply Last reply Reply Quote 0
              • 1 / 1
              • First post
                Last post
              Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors