For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Perfomance of specific strategy in cerebro



  • Hello,
    my code like this

        cerebro = bt.Cerebro()
        cerebro.broker.set_cash(100000.0)
        cerebro.broker.set_coc(True)
        cerebro.broker.addcommissioninfo(CommDivFrance())
    
        # --- Adding some data feeds ---
       
        # --- Observers ---
        cerebro.addobserver(bt.observers.Broker)
        cerebro.addobservermulti(bt.observers.BuySell)
        cerebro.addobserver(bt.observers.Benchmark,
                            data=benchdata,
                            _doprenext=True,
                            timeframe=TimeFrame.NoTimeFrame)
    
        # --- Analyzers ---
        cerebro.addanalyzer(bt.analyzers.SharpeRatio, timeframe=TimeFrame.Years)
        cerebro.addanalyzer(bt.analyzers.Calmar, timeframe=TimeFrame.Years)
        cerebro.addanalyzer(bt.analyzers.DrawDown)
        cerebro.addanalyzer(bt.analyzers.AnnualReturn)
        cerebro.addanalyzer(bt.analyzers.PyFolio, timeframe=TimeFrame.Days, compression=1)
        cerebro.addanalyzer(bt.analyzers.Transactions)
        cerebro.addanalyzer(bt.analyzers.Returns)
    
        # --- Strategies ---
        cerebro.addstrategy(strategy=ValueBasket)
        cerebro.addstrategy(strategy=ValueBasket2)
    
        results = cerebro.run()
    
        for strat in results:
            print('='*79)
            print(strat.__class__.__name__)
    
            # Analyzers results
            strat.analyzers.annualreturn.print()
            strat.analyzers.drawdown.print()
            strat.analyzers.sharperatio.print()
            strat.analyzers.returns.print()
    
            # pyfolio
            pyfoliozer = strat.analyzers.getbyname('pyfolio')
            returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
    
            # Perfomance
            pf.show_perf_stats(returns=returns)
    
        # 
        cerebro.plot(plotter=PlotterZoomed())
    

    I added 2 strategies, and would like to extract performance of each ones. But for each strat I get same perfomance (annualreturn, drawdown, profit, sharpe and so on), which comes from backtasting together (printing in section # Analyzers results). There are some capital allocation logic between strategies and they are related to each other.

    1. Is there any method to get perfomance of each strategies separate after finishing backtesting?
    2. Is there any way to get single strategy returns for past 6 months in next() method?

  • administrators

    @oalexandere said in Perfomance of specific strategy in cerebro:

    1. Is there any method to get perfomance of each strategies separate after finishing backtesting?

    The performance is for the account you have in the broker.



  • @backtrader ok. After much thought, one version (for example for calc pnl for each strategy) may be like this:

        def notify_order(self, order):
    
            if order.status in [order.Completed]:
                if hasattr(self, 'total_pnl'):
                    self.total_pnl += order.executed.pnl - order.executed.comm
                else:
                    self.total_pnl = order.executed.pnl - order.executed.comm
    


  • Solution: using analyzer.
    Maybe will be usefull for somebody: next analyzer calculate and save realized pnl and opened positions for each strategy date to date:

    import backtrader as bt
    from collections import OrderedDict
    
    
    class TotalReturns(bt.Analyzer):
        '''This analyzer reports the total pnl for strategy
    
        Params:
    
          - timeframe (default: ``None``)
            If ``None`` then the timeframe of the 1st data of the system will be
            used
    
          - compression (default: ``None``)
    
            Only used for sub-day timeframes to for example work on an hourly
            timeframe by specifying "TimeFrame.Minutes" and 60 as compression
    
            If ``None`` then the compression of the 1st data of the system will be
            used
    
        Methods:
    
          - get_analysis
    
            Returns a dictionary with returns as values and the datetime points for
            each return as keys
        '''
    
        def __init__(self):
            self.total_pnl = 0  
            self.unrealized = 0  # Unrealized pnl for all positions all strategies
            self.positions = OrderedDict.fromkeys([d._name or 'Data%d' % i 
                                                   for i, d in enumerate(self.datas)], 0)  # Current strategy positions
    
        def start(self):
            tf = min(d._timeframe for d in self.datas)
            self._usedate = tf >= bt.TimeFrame.Days
    
        def notify_order(self, order):
    
            if order.status in [order.Completed, order.Partial]:
                self.total_pnl += order.executed.pnl - order.executed.comm
    
                self.positions[order.data._name] += order.executed.size
    
        def next(self):
            if self._usedate:
                self.rets[self.strategy.datetime.date()] = self.total_pnl
            else:
                self.rets[self.strategy.datetime.datetime()] = self.total_pnl
    
        def stop(self):
    
            for dname in self.positions:
                self.unrealized += (self.strategy.dnames[dname].close[0] - 
                                    self.strategy.positionsbyname[dname].price) * \
                                   self.strategy.positionsbyname[dname].size