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/

    Adding multiple data feeds in a for loop gives error

    General Code/Help
    3
    4
    253
    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.
    • ?
      A Former User last edited by

      When trying to add multiple data feeds I'm getting the following error:

      ❯ python3 optimize_all_indexes.py
      Traceback (most recent call last):
        File "optimize_all_indexes.py", line 43, in <module>
          optimized_runs = cerebro.run()
        File "/home/user/.local/lib/python3.8/site-packages/backtrader/cerebro.py", line 1143, in run
          for r in pool.imap(self, iterstrats):
        File "/usr/lib/python3.8/multiprocessing/pool.py", line 868, in next
          raise value
      multiprocessing.pool.MaybeEncodingError: Error sending result: '[<strategies.strategies.EMAcrossover object at 0x7f9dda1051f0>]'. Reason: 'PicklingError("Can't pickle <class 'backtrader.metabase.AutoInfoClass_95a5b7035dfc45a8b0580d4ca9a9ac62_AXJO.csv'>: attribute lookup AutoInfoClass_95a5b7035dfc45a8b0580d4ca9a9ac62_AXJO.csv on backtrader.metabase failed")'
      

      The code works for a single data feed. This is what I've changed from the code:

          modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
          datapath = os.path.join(modpath, 'data/indexes/')
          for file in os.listdir(datapath):
              path = os.path.join(modpath, f'data/indexes/{file}')
              data = bt.feeds.YahooFinanceCSVData(
                  dataname=path,
                  name=file,
                  reverse=False
              )
              cerebro.adddata(data)
      

      The code for a single data feed:

      sizers.py

      import backtrader as bt
      
      class MaxRiskSizer(bt.Sizer):
          params = (('risk', 0.98),)
      
          def __init__(self):
              if self.p.risk > 1 or self.p.risk < 0:
                  raise ValueError('The risk parameter is a percentage which must be'
                      'entered as a float. e.g. 0.5')
      
          def _getsizing(self, comminfo, cash, data, isbuy):
              position = self.broker.getposition(data)
      
              if not position:
                  size = comminfo.getsize(data.close[0], cash * self.p.risk)
              else:
                  size = position.size
      
              return size
      

      commissions.py

      import backtrader as bt
      
      class DegiroCommission(bt.CommInfoBase):
          params = (('per_share', 0.004), ('flat', 0.5),)
      
          def _getcommission(self, size, price, pseudoexec):
              return self.p.flat + size * self.p.per_share
      

      optimize.py

      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      import datetime
      import os.path
      import sys
      import math
      
      import backtrader as bt
      
      from strategies.strategies import *
      from sizers import MaxRiskSizer
      from commissions import DegiroCommission
      
      STARTING_CASH = 1700
      
      
      if __name__ == '__main__':
          cerebro = bt.Cerebro(optreturn=False)
          cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='annual_return')
          cerebro.optstrategy(EMAcrossover, fast=range(5, 7), slow=range(10,12))
          #cerebro.optstrategy(EMAcrossover, fast=range(5, 55, 5), slow=range(60, 300, 10))
          #cerebro.optstrategy(EMAcrossover, fast=range(15, 55), slow=range(40, 60))
          cerebro.broker.set_cash(STARTING_CASH)
          cerebro.broker.set_coc(True)
      
          modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
          datapath = os.path.join(modpath, 'data/SPY.csv')
          data = bt.feeds.YahooFinanceCSVData(
              dataname=datapath,
              reverse=False
          )
          cerebro.adddata(data)
      
          cerebro.addsizer(MaxRiskSizer)
          comminfo = DegiroCommission()
          cerebro.broker.addcommissioninfo(comminfo)
      
          optimized_runs = cerebro.run()
      
          final_results_list = []
          for run in optimized_runs:
              for strategy in run:
                  PnL = round(strategy.broker.get_value() - STARTING_CASH, 2)
                  my_dict = strategy.analyzers.annual_return.get_analysis()
                  annual_returns = [v for _, v in my_dict.items() if v != 0]
                  average_annual_return = sum(annual_returns) / len(annual_returns)
                  final_results_list.append([strategy.params.fast,
                  strategy.params.slow, PnL, round(average_annual_return*100, 2)])
      
          sort_by_return = sorted(final_results_list, key=lambda x: x[3],
                                   reverse=True)
          print('\nSorted by Annualized Return:')
          for line in sort_by_return[:10]:
              print(line)
      
          sort_by_pnl = sorted(final_results_list, key=lambda x: x[2],
                                   reverse=True)
          print('\nSorted by PnL:')
          for line in sort_by_pnl[:10]:
              print(line)
      

      The indexes have different starting day for the datas. Maybe that affects the optimization somehow.

      1 Reply Last reply Reply Quote 0
      • ?
        A Former User last edited by

        The strategy was missing.

        strategies.py

        class EMAcrossover(bt.Strategy):
            params = (('fast', 20), ('slow', 50),)
        
            def log(self, txt, dt=None):
                dt = dt or self.datas[0].datetime.date(0)
                #print(f'{dt.isoformat()} {txt}') # Comment this line when running optimization
        
            def __init__(self):
                self.dataclose = self.datas[0].close
                self.order = None
        
                fast_ema, slow_ema = bt.ind.EMA(period=self.p.fast), bt.ind.EMA(period=self.p.slow)
                self.crossover = bt.indicators.CrossOver(fast_ema, slow_ema)
                #self.signal_add(bt.SIGNAL_LONGSHORT, bt.ind.CrossOver(ema1, ema2))
        
            def notify_trade(self, trade):
                if not trade.isclosed:
                    return
        
                self.log(f'GROSS {trade.pnl:.2f}, NET {trade.pnlcomm:.2f}')
        
            def notify_order(self, order):
                if order.status in [order.Submitted, order.Accepted]:
                    # An active Buy/Sell order has been submitted/accepted - 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(f'BUY EXECUTED, {order.executed.price:.2f}')
                    elif order.issell():
                        self.log(f'SELL EXECUTED, {order.executed.price:.2f}')
                    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 next(self):
                if self.order:
                    return
        
                if self.crossover > 0:
                    self.log(f'BUY CREATE {self.dataclose[0]:.2f}')
                    self.order = self.buy()
                elif self.crossover < 0:
                    self.log(f'SELL CREATE {self.dataclose[0]:.2f}')
                    self.order = self.sell()
        
        1 Reply Last reply Reply Quote 0
        • W
          willt last edited by

          Same error, any help?

          run-out 1 Reply Last reply Reply Quote 0
          • run-out
            run-out @willt last edited by

            @willt Can you please elaborate on your error and start a new thread? Thanks.

            RunBacktest.com

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