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/

    Test a strategy over a list of stocks (50+)

    General Code/Help
    2
    9
    89
    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
      marketwizard last edited by

      Hello,

      I'm currently triying to test a strategy over a list of stocks (30+) and then generate the results of the strategy for each stock.

      I tried to use a for loop to go through every stock and get the results, but it doesn't work.
      The code only prints the results for the first stock in the list.

      Here ist the code:

      import backtrader as bt
      import os.path
      import sys
      from datetime import datetime, timedelta
      import math
      import warnings
      
      period = 3650
      strategyResults = {}
      lastBuy = None
      optimization = True
      
      tickers =['SH', 'VXX', 'EEM', 'QQQ', 'PSQ', 'XLF', 'GDX', 'HYG', 'EFA', 'IAU', 'XOP', 'IWM', 'FXI', 'SLV', 'USO', 'XLE', 'IEMG', 'AMLP', 'EWZ', 'XLK', 'XLI', 'VWO', 'GLD', 'XLP', 'JNK', 'EWJ', 'XLU', 'VEA', 'IEFA', 'XLV', 'PFF', 'VIXY', 'TLT', 'GDXJ', 'LQD', 'XLB', 'BKLN', 'XLY', 'SMH', 'OIH', 'ASHR', 'RSX', 'MCHI', 'VTI', 'EWH', 'SPLV', 'KRE', 'IVV', 'DIA', 'IEF', 'EZU', 'EWT', 'SPDW', 'VOO', 'SCHF', 'EWY', 'MYY', 'DOG', 'EUM']
      
      data_path = r"C:\Users\XXXXX"
      
      # define the resolution(s) of the chart(s) & the strategy
      timeframes = {
          '1D': 1
      }
      
      # New Class to define the content of the strategy
      class EMAStack(bt.Strategy):
          # Define the parameters of the strategy
          params = (
              ('portfolio_expo', 0.10),  # Max 15% of the Portfolio per trade
              ('trade_risk', 0.02),  # Max 2% risk per trade (stop loss)
              ('atrdist', 3.0)  # ATR based Stop loss distance
          )
      
          def notify_order(self, order):
              if order.status == order.Completed:
                  pass
      
              if not order.alive():
                  self.order = None  # indicate no order is pending
      
          # Initialize the elements which are needed for the strategy (indicators, etc...)
          def __init__(self):
      
              # Define the indicators
              self.ema50 = bt.indicators.EMA(self.data.close, period=10)
              self.ema200 = bt.indicators.EMA(self.data.close, period=30)
              self.atr = bt.indicators.ATR(period=14)
      
              # Define the crossover signals
              self.bull_cross = bt.indicators.CrossOver(self.ema50, self.ema200)
              self.bull_cross.plotinfo.subplot = False
      
              self.bear_cross = bt.indicators.CrossOver(self.ema200, self.ema50)
              self.bear_cross.plotinfo.subplot = False
      
          def start(self):
              self.order = None  # sentinel to avoid operations on pending order
      
          def prenext(self):
              self.next()
      
          def next(self):
      
              # Get the Amount of cash in the Portfolio
              cash = self.broker.get_cash()
      
              if self.order:
                  return  # pending order execution
      
              if not self.position:  # check if we already have an open position on the stock
      
                  if self.bull_cross > 0.0:
      
                      # Calculation of the Stock Qty to buy depending on our risk strategy
                      pdist = self.atr[0] * self.p.atrdist
                      self.pstop = self.data.close[0] - pdist
                      qty = math.floor((cash * self.p.trade_risk) / pdist)
      
                      portfolio_exposure_calc = qty * self.data.close[0]
                      portfolio_exposure_strategy = cash * self.p.portfolio_expo
      
                      if portfolio_exposure_calc <= portfolio_exposure_strategy:
                          self.order = self.buy(size=qty)
                      else:
                          qty = math.floor(portfolio_exposure_strategy / self.data.close[0])
                          self.order = self.buy(size=qty)
      
                  elif self.bear_cross > 0.0:
      
                      # Calculation of the Stock Qty to buy depending on our risk strategy
                      pdist = self.atr[0] * self.p.atrdist
                      self.pstop = self.data.close[0] - pdist
                      qty = math.floor((cash * self.p.trade_risk) / pdist)
      
                      portfolio_exposure_calc = qty * self.data.close[0]
                      portfolio_exposure_strategy = cash * self.p.portfolio_expo
      
                      if portfolio_exposure_calc <= portfolio_exposure_strategy:
                          self.order = self.sell(size=qty)
                      else:
                          qty = math.floor(portfolio_exposure_strategy / self.data.close[0])
                          self.order = self.sell(size=qty)
      
      
              else:  # in the market
                  pclose = self.data.close[0]
                  pstop = self.pstop
      
                  # Add detection if we are already short or long
                  if pclose < pstop or self.bear_cross or self.bull_cross:
                      self.close()  # stop met - get out
                  else:
                      pdist = self.atr[0] * self.p.atrdist
                      # Update only if greater than
                      self.pstop = max(pstop, pclose - pdist)
          '''
          def notify_trade(self, trade):
              date = self.data.datetime.datetime()
              if trade.isclosed:
                  print('-' * 32, ' NOTIFY TRADE ', '-' * 32)
                  print('{}, Avg Price: {}, Profit, Gross {}, Net {}'.format(
                      date,
                      trade.price,
                      round(trade.pnl, 2),
                      round(trade.pnlcomm, 2)))
                      '''
      
      def printTradeAnalysis(analyzer):
          '''
          Function to print the Technical Analysis results in a nice format.
          '''
          # Get the results we are interested in
      
          total_open = analyzer.total.open
          total_closed = analyzer.total.closed
          total_won = analyzer.won.total
          total_lost = analyzer.lost.total
          win_streak = analyzer.streak.won.longest
          lose_streak = analyzer.streak.lost.longest
          pnl_net = round(analyzer.pnl.net.total, 2)
          strike_rate = round(((total_won / total_closed) * 100), 2)
          profit_factor = round((total_won / total_lost), 2)
      
          # Designate the rows
          h1 = ['Total Open', 'Total Closed', 'Total Won', 'Total Lost']
          h2 = ['Strike Rate', 'Win Streak', 'Losing Streak', 'PnL Net']
      
          r1 = [total_open, total_closed, total_won, total_lost]
          r2 = [strike_rate, win_streak, lose_streak, pnl_net]
      
          # Check which set of headers is the longest.
          if len(h1) > len(h2):
              header_length = len(h1)
          else:
              header_length = len(h2)
          # Print the rows
          print_list = [h1, r1, h2, r2]
          row_format = "{:<15}" * (header_length + 1)
          print("Trade Analysis Results:")
      
          for row in print_list:
              print(row_format.format('', *row))
      
          print('Profit Factor: {}'.format(profit_factor))
      
      
      def printSQN(analyzer):
          sqn = round(analyzer.sqn, 2)
          print('SQN: {}'.format(sqn))
      
      if __name__ == '__main__':
          cerebro = bt.Cerebro()
      
          for ticker in tickers:
      
      
              endDate = datetime.today().strftime('%Y-%m-%d')
              fromDate = (datetime.today() - timedelta(days=period))
              startDate = fromDate.strftime('%Y-%m-%d')
              filename = '%s_%s_%s.txt' % (ticker, startDate, endDate)
      
              datapath = os.path.join(data_path, filename)
              print(os.path.abspath(datapath))
      
              #'''
              if not os.path.isfile(datapath):
                  print('file: %s not found' % filename)
                  sys.exit()
                  #'''
      
              data = bt.feeds.YahooFinanceCSVData(
                  dataname=datapath,
                  # Do not pass values before this date
                  fromdate=datetime(fromDate.year, fromDate.month, fromDate.day),
                  # Do not pass values before this date
                  todate=datetime(datetime.today().year, datetime.today().month, datetime.today().day),
                  # Do not pass values after this date
                  reverse=False)
      
              cerebro.adddata(data)
              # Set the Cash for the Strategy
              cerebro.broker.setcash(10000)
              # Set the comissions
              cerebro.broker.setcommission(commission=0.005)
      
              # Add the analyzers we are interested in
              cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='ta')
              cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
              cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name="annualreturn")
              cerebro.addanalyzer(bt.analyzers.PyFolio, _name="pyfolio")
      
          cerebro.addstrategy(EMAStack)
      
          # Run over everything
          strategies = cerebro.run()
          EMAStack = strategies[0]
          #cerebro.run()
      
          # print the analyzers
          printTradeAnalysis(EMAStack.analyzers.ta.get_analysis())
          printSQN(EMAStack.analyzers.sqn.get_analysis())
      
          print("Final Portfolio Value: %.2f" % cerebro.broker.getvalue())
      

      I hope that someone can help

      1 Reply Last reply Reply Quote 0
      • vladisld
        vladisld last edited by

        @marketwizard said in Test a strategy over a list of stocks (50+):

        self.ema50 = bt.indicators.EMA(self.data.close, period=10)

        self.pstop = self.data.close[0] - pdist

        self.order = self.buy(size=qty)

        You strategy is only using the first data feed added. self.data is a shortcut for the first datafeed. self.buy(size=qty) will also create the buy order for the first data feed.

        Please take a look at the docs:

        https://www.backtrader.com/docu/concepts/#shortcuts-for-data-feeds

        explain the various shortcuts available for the strategy

        https://www.backtrader.com/docu/strategy/#reference-strategy

        shows how to pass the arbitrary data feed (and not only the first one) to the buy method.

        One more useful article explaining how to work with multiple data feeds:

        https://backtest-rookies.com/2017/08/22/backtrader-multiple-data-feeds-indicators/

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

          @vladisld thank you for your answer.

          I went through the documentations and the article from backtest-rookies and I also tested their code.

          It seems that it is the same portfolio which is investing on every FX pair

          What I'm trying to do is a bit different:

          I want to backtest my strategy on each stock in order to generate the KPI's for each stock individually (and plot them idivually).
          And in the next steps, the goal would be to generate a table / file with datas like:

          'AAPL' | strike rate = 24% | sharpe ratio = 0.36 | final portfolio value = XXX
          'JNJ' | strike rate = 35% | sharpe ratio = 0.52 | final portfolio value = XXX
          'AMZN' | strike rate = 60% | sharpe ratio = 1.236 | final portfolio value = XXX
          .....
          ...

          1 Reply Last reply Reply Quote 0
          • vladisld
            vladisld last edited by

            In this case you should have created the Cerebro instance for each ticket and call its run method in the loop. The code you've presented above just adds multiple symbols to the same Cerebro instance and runs all of them together afterwards. Please correct me if I'm wrong

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

              I modified the code in accordance to your recommandation:

              • I moved the creation of the cerebro instance, the "run" and "addstrategy" method into the loop.

              Then, when I run the code, the backtests results (and the plot) for the first stock in the loop are generated, then I receive the following error:

              Traceback (most recent call last):
                File "C:/Users/marketwizard/PycharmProjects/MW_Backtests/EMA_universeV2/main.py", line 262, in <module>
                  strategies = cerebro.run()
                File "C:\Users\marketwizard\PycharmProjects\Algotrading_libraries1\lib\site-packages\backtrader\cerebro.py", line 1127, in run
                  runstrat = self.runstrategies(iterstrat)
                File "C:\Users\marketwizard\PycharmProjects\Algotrading_libraries1\lib\site-packages\backtrader\cerebro.py", line 1238, in runstrategies
                  strat._addobserver(False, observers.Broker)
                File "C:\Users\marketwizard\PycharmProjects\Algotrading_libraries1\lib\site-packages\backtrader\lineseries.py", line 461, in __getattr__
                  return getattr(self.lines, name)
              AttributeError: 'Lines_LineSeries_LineIterator_DataAccessor_Strateg' object has no attribute '_addobserver'
              
              Process finished with exit code 1
              

              Here the code with the modifications described above

              import backtrader as bt
              import pandas as pd
              import os.path
              import sys
              from datetime import datetime, timedelta, date
              import math
              
              period = 3650
              strategyResults = {}
              lastBuy = None
              
              icap = 10000
              
              tickers =['SH', 'VXX', 'EEM', 'QQQ', 'PSQ', 'XLF', 'GDX', 'HYG', 'EFA', 'IAU', 'XOP', 'IWM', 'FXI', 'SLV', 'USO', 'XLE', 'IEMG', 'AMLP', 'EWZ', 'XLK', 'XLI', 'VWO', 'GLD', 'XLP', 'JNK', 'EWJ', 'XLU', 'VEA', 'IEFA', 'XLV', 'PFF', 'VIXY', 'TLT', 'GDXJ', 'LQD', 'XLB', 'BKLN', 'XLY', 'SMH', 'OIH', 'ASHR', 'RSX', 'MCHI', 'VTI', 'EWH', 'SPLV', 'KRE', 'IVV', 'DIA', 'IEF', 'EZU', 'EWT', 'SPDW', 'VOO', 'SCHF', 'EWY', 'MYY', 'DOG', 'EUM']
              
              data_path = r"C:\XXX"
              
              # define the resolution(s) of the chart(s) & the strategy
              timeframes = {
                  '1D': 1
              }
              
              # New Class to define the content of the strategy
              class EMAStack(bt.Strategy):
                  # Define the parameters of the strategy
                  params = (
                      ('portfolio_expo', 0.10),  # Max 15% of the Portfolio per trade
                      ('trade_risk', 0.02),  # Max 2% risk per trade (stop loss)
                      ('atrdist', 3.0)  # ATR based Stop loss distance
                  )
              
                  def notify_order(self, order):
                      if order.status == order.Completed:
                          pass
              
                      if not order.alive():
                          self.order = None  # indicate no order is pending
              
                  # Initialize the elements which are needed for the strategy (indicators, etc...)
                  def __init__(self):
              
                      # Define the indicators
                      self.ema50 = bt.indicators.EMA(self.data.close, period=50)
                      self.ema200 = bt.indicators.EMA(self.data.close, period=200)
                      self.atr = bt.indicators.ATR(period=14)
              
                      # self.log_pnl = []
              
                      # Define the crossover signals
                      self.bull_cross = bt.indicators.CrossOver(self.ema50, self.ema200)
                      self.bull_cross.plotinfo.subplot = False
              
                      self.bear_cross = bt.indicators.CrossOver(self.ema200, self.ema50)
                      self.bear_cross.plotinfo.subplot = False
              
                  def start(self):
                      self.order = None  # sentinel to avoid operations on pending order
                      self.curpos = None
              
                  def prenext(self):
                      self.next()
              
                  def next(self):
              
                      # Get the Amount of cash in the Portfolio
                      cash = self.broker.get_cash()
              
                      if self.order:
                          return  # pending order execution
              
                      if not self.position:  # check if we already have an open position on the stock
              
                          if self.bull_cross > 0.0:
              
                              # Calculation of the Stock Qty to buy depending on our risk strategy
                              pdist = self.atr[0] * self.p.atrdist
                              self.pstop = self.data.close[0] - pdist
                              qty = math.floor((cash * self.p.trade_risk) / pdist)
              
                              portfolio_exposure_calc = qty * self.data.close[0]
                              portfolio_exposure_strategy = cash * self.p.portfolio_expo
              
                              if portfolio_exposure_calc <= portfolio_exposure_strategy:
                                  self.order = self.buy(size=qty)
                              else:
                                  qty = math.floor(portfolio_exposure_strategy / self.data.close[0])
                                  self.order = self.buy(size=qty)
              
                              '''
                          elif self.bear_cross > 0.0:
              
                              # Calculation of the Stock Qty to buy depending on our risk strategy
                              pdist = self.atr[0] * self.p.atrdist
                              self.pstop = self.data.close[0] - pdist
                              qty = math.floor((cash * self.p.trade_risk) / pdist)
              
                              portfolio_exposure_calc = qty * self.data.close[0]
                              portfolio_exposure_strategy = cash * self.p.portfolio_expo
              
                              if portfolio_exposure_calc <= portfolio_exposure_strategy:
                                  self.order = self.sell(size=qty)
                              else:
                                  qty = math.floor(portfolio_exposure_strategy / self.data.close[0])
                                  self.order = self.sell(size=qty)
                              '''
              
                      else:  # in the market
                          pclose = self.data.close[0]
                          pstop = self.pstop
              
                          # Add detection if we are already short or long
                          if pclose < pstop or self.bear_cross or self.bull_cross:
                              self.close()  # stop met - get out
                          else:
                              pdist = self.atr[0] * self.p.atrdist
                              # Update only if greater than
                              self.pstop = max(pstop, pclose - pdist)
              
              '''
                  def notify_trade(self, trade):
                      date = self.data.datetime.datetime()
                      if trade.isclosed:
                          print('-' * 32, ' NOTIFY TRADE ', '-' * 32)
                          print('{}, Avg Price: {}, Profit, Gross {}, Net {}'.format(
                              date,
                              trade.price,
                              round(trade.pnl, 2),
                              round(trade.pnlcomm, 2)))
              '''
              
              def printSQN(analyzer):
                  sqn = round(analyzer.sqn, 2)
                  print('SQN: {}'.format(sqn))
              
              def pretty_print(format, *args):
                  print(format.format(*args))
              
              def exists(object, *properties):
                  for property in properties:
                      if not property in object: return False
                      object = object.get(property)
                  return True
              
              def printTradeAnalysis(cerebro, analyzers):
                  format = "  {:<24} : {:<24}"
                  NA     = '-'
              
                  print('Backtesting Results')
                  if hasattr(analyzers, 'ta'):
                      ta = analyzers.ta.get_analysis()
              
                      openTotal         = ta.total.open          if exists(ta, 'total', 'open'  ) else None
                      closedTotal       = ta.total.closed        if exists(ta, 'total', 'closed') else None
                      wonTotal          = ta.won.total           if exists(ta, 'won',   'total' ) else None
                      lostTotal         = ta.lost.total          if exists(ta, 'lost',  'total' ) else None
              
                      streakWonLongest  = ta.streak.won.longest  if exists(ta, 'streak', 'won',  'longest') else None
                      streakLostLongest = ta.streak.lost.longest if exists(ta, 'streak', 'lost', 'longest') else None
              
                      pnlNetTotal       = ta.pnl.net.total       if exists(ta, 'pnl', 'net', 'total'  ) else None
                      pnlNetAverage     = ta.pnl.net.average     if exists(ta, 'pnl', 'net', 'average') else None
              
                      pretty_print(format, 'Open Positions', openTotal   or NA)
                      pretty_print(format, 'Closed Trades',  closedTotal or NA)
                      pretty_print(format, 'Winning Trades', wonTotal    or NA)
                      pretty_print(format, 'Loosing Trades', lostTotal   or NA)
                      print('\n')
              
                      pretty_print(format, 'Longest Winning Streak',   streakWonLongest  or NA)
                      pretty_print(format, 'Longest Loosing Streak',   streakLostLongest or NA)
                      pretty_print(format, 'Strike Rate (Win/closed)', (wonTotal / closedTotal) * 100 if wonTotal and closedTotal else NA)
                      print('\n')
              
                      pretty_print(format, 'Inital Portfolio Value', '${}'.format(icap))
                      pretty_print(format, 'Final Portfolio Value',  '${}'.format(cerebro.broker.getvalue()))
                      pretty_print(format, 'Net P/L',                '${}'.format(round(pnlNetTotal,   2)) if pnlNetTotal   else NA)
                      pretty_print(format, 'P/L Average per trade',  '${}'.format(round(pnlNetAverage, 2)) if pnlNetAverage else NA)
                      print('\n')
              
                  if hasattr(analyzers, 'drawdown'):
                      pretty_print(format, 'Drawdown', '${}'.format(analyzers.drawdown.get_analysis()['drawdown']))
                  if hasattr(analyzers, 'sharpe'):
                      pretty_print(format, 'Sharpe Ratio:', analyzers.sharpe.get_analysis()['sharperatio'])
                  if hasattr(analyzers, 'vwr'):
                      pretty_print(format, 'VRW', analyzers.vwr.get_analysis()['vwr'])
                  if hasattr(analyzers, 'sqn'):
                      pretty_print(format, 'SQN', analyzers.sqn.get_analysis()['sqn'])
                  print('\n')
              
                  print('Transactions')
                  format = "  {:<24} {:<24} {:<16} {:<8} {:<8} {:<16}"
                  pretty_print(format, 'Date', 'Amount', 'Price', 'SID', 'Symbol', 'Value')
                  for key, value in analyzers.txn.get_analysis().items():
                      pretty_print(format, key.strftime("%Y/%m/%d %H:%M:%S"), value[0][0], value[0][1], value[0][2], value[0][3], value[0][4])
              
              if __name__ == '__main__':
              
                  for ticker in tickers:
                      cerebro = bt.Cerebro()
              
                      endDate = date(2021, 1, 10)
                      fromDate = (endDate - timedelta(days=period))
              
                      startDate = fromDate.strftime('%Y-%m-%d')
                      filename = '%s_%s_%s.txt' % (ticker, startDate, endDate)
              
                      datapath = os.path.join(data_path, filename)
                      print(os.path.abspath(datapath))
              
                      #'''
                      if not os.path.isfile(datapath):
                          print('file: %s not found' % filename)
                          sys.exit()
                          #'''
              
                      data = bt.feeds.YahooFinanceCSVData(
                          dataname=datapath,
                          # Do not pass values before this date
                          fromdate=datetime(fromDate.year, fromDate.month, fromDate.day),
                          # Do not pass values before this date
                          todate=datetime(datetime.today().year, datetime.today().month, datetime.today().day),
                          # Do not pass values after this date
                          reverse=False)
              
                      cerebro.adddata(data)
                      # Set the Cash for the Strategy
                      cerebro.broker.setcash(icap)
                      # Set the comissions
                      cerebro.broker.setcommission(commission=0.005)
              
              
                      # Add the analyzers we are interested in
                      cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='ta')
                      cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown')
                      cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe', riskfreerate=0.0, annualize=True, timeframe=bt.TimeFrame.Days)
                      cerebro.addanalyzer(bt.analyzers.VWR, _name='vwr')
                      cerebro.addanalyzer(bt.analyzers.SQN, _name='sqn')
                      cerebro.addanalyzer(bt.analyzers.Transactions, _name='txn')
                      cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
              
                      cerebro.addstrategy(EMAStack)
              
                      # Run over everything
                      strategies = cerebro.run()
                      EMAStack = strategies[0]
              
                      # print the analyzers
                      printTradeAnalysis(cerebro, EMAStack.analyzers)
              
                      cerebro.plot(style='candlestick', barup='green', bardown='red')
              
              
              vladisld 1 Reply Last reply Reply Quote 0
              • vladisld
                vladisld last edited by

                Could you please try to run the Cerebro engine using:

                cerebro.run(stdstats=False)
                
                1 Reply Last reply Reply Quote 0
                • M
                  marketwizard last edited by

                  I tried with

                  cerebro.run(stdstats=False)
                  

                  But I received following error:

                  Traceback (most recent call last):
                    File "C:/Users/marketwizard/PycharmProjects/MW_Backtests/EMA_universeV2/main.py", line 262, in <module>
                      strategies = cerebro.run(stdstats=False)
                    File "C:\Users\marketwizard\PycharmProjects\Algotrading_libraries1\lib\site-packages\backtrader\cerebro.py", line 1127, in run
                      runstrat = self.runstrategies(iterstrat)
                    File "C:\Users\marketwizard\PycharmProjects\Algotrading_libraries1\lib\site-packages\backtrader\cerebro.py", line 1257, in runstrategies
                      strat._addanalyzer(ancls, *anargs, **ankwargs)
                    File "C:\Users\marketwizard\PycharmProjects\Algotrading_libraries1\lib\site-packages\backtrader\lineseries.py", line 461, in __getattr__
                      return getattr(self.lines, name)
                  AttributeError: 'Lines_LineSeries_LineIterator_DataAccessor_Strateg' object has no attribute '_addanalyzer'
                  
                  1 Reply Last reply Reply Quote 0
                  • vladisld
                    vladisld @marketwizard last edited by

                    @marketwizard said in Test a strategy over a list of stocks (50+):

                    cerebro.addstrategy(EMAStack)

                        # Run over everything
                        strategies = cerebro.run()
                        EMAStack = strategies[0]
                    

                    You are overriding the EMAStack name - which should be a class of your strategy with the strategy instance returned from the Cerebro.run() method. So the next iteration in the cerebro.addstrategy(EMAStack) the strategy instance is passed instead of strategy class.

                    1 Reply Last reply Reply Quote 3
                    • M
                      marketwizard last edited by

                      @vladisld thank you, now it works !

                      1 Reply Last reply Reply Quote 1
                      • 1 / 1
                      • First post
                        Last post
                      Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                      $(document).ready(function () { app.coldLoad(); }); }