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/

    AttributeError: 'ItemCollection' object has no attribute 'sharpe_ratio'

    General Code/Help
    2
    2
    27
    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.
    • Q
      quake004 last edited by

      Following the example from Backtrader for Backtesting (Python) – A Complete Guide, I've had an error which I can't resolve in the following line:

      sharpe = strategy.analyzers.sharpe_ratio.get_analysis()
      

      That's line 119 from the following code:

      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      import datetime
      import os.path
      import sys
      import math
      
      import backtrader as bt
      
      STARTING_CASH = 1700
      
      class maxRiskSizer(bt.Sizer):
          params = (('risk', 0.95),)
      
          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
      
      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
      
      class SMAcrossover(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_sma, slow_sma = bt.ind.SMA(period=self.p.fast), bt.ind.SMA(period=self.p.slow)
              self.crossover = bt.indicators.CrossOver(fast_sma, slow_sma)
              #self.signal_add(bt.SIGNAL_LONGSHORT, bt.ind.CrossOver(sma1, sma2))
      
          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')
      
              # Reset orders
              self.order = None
      
          def next(self):
              # Check for open orders
              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()
      
      if __name__ == '__main__':
          cerebro = bt.Cerebro(optreturn=False)
          cerebro.optstrategy(SMAcrossover, fast=range(5,7), slow=range(50,52))
          #cerebro.optstrategy(SMAcrossover, fast=range(5,55,5), slow=range(60,310,10))
          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, 'datas/CPE.csv')
          data = bt.feeds.YahooFinanceCSVData(
              dataname=datapath,
              # Do not pass values before this date
              fromdate=datetime.datetime(1990, 10, 1),
              # Do not pass values after this date
              todate=datetime.datetime(2020, 10, 15),
              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)
                  sharpe = strategy.analyzers.sharpe_ratio.get_analysis()
                  final_results_list.append([strategy.params.fast, 
                      strategy.params.slow, PnL, sharpe['sharperatio']])
      
          sort_by_sharpe = sorted(final_results_list, key=lambda x: x[3], 
                                   reverse=True)
          for line in sort_by_sharpe[:5]:
              print(line)
      
      1 Reply Last reply Reply Quote 0
      • vladisld
        vladisld last edited by

        your code is missing adding the actual analyzer (it appears in the original article):

        cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe_ratio')
        
        1 Reply Last reply Reply Quote 2
        • 1 / 1
        • First post
          Last post
        Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
        $(document).ready(function () { app.coldLoad(); }); }