pyfolio integration



  • Hi all,

    I am testing Pyfolio integration using codes from this blog post. It is throwing me error ValueError: 'pyfolio' is not in list. Any tips in displaying outputs w/ Pyfolio?

    Here's my code

        results = cerebro.run()
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
        cerebro.plot(style='bar')
        
        strat = results[0]
    
        pyfoliozer = strat.analyzers.getbyname('pyfolio')
        returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
        import pyfolio as pf
        pf.create_full_tear_sheet(
            returns,
            positions=positions,
            transactions=transactions,
            gross_lev=gross_lev,
            live_start_date='1950-01-01',
            round_trips=True)
    

    And here's the error its giving me:

    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-7-8697d87cea1d> in <module>()
         60 
         61 if __name__ == '__main__':
    ---> 62     runstrat()
    
    <ipython-input-7-8697d87cea1d> in runstrat()
         48     strat = results[0]
         49 
    ---> 50     pyfoliozer = strat.analyzers.getbyname('pyfolio')
         51     returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
         52     import pyfolio as pf
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\backtrader\metabase.py in getbyname(self, name)
        265 
        266     def getbyname(self, name):
    --> 267         idx = self._names.index(name)
        268         return self._items[idx]
    
    ValueError: 'pyfolio' is not in list
    

  • administrators

    Doesn't seem like you have added the pyfolio analyzer. But because the code is only partially shown it's simply an educated guess.



  • You are right. I added the analyzer but now the error message changed. Here's the full snippet.

    def runstrat():
        start = datetime.datetime(1949,12,31)
        end = datetime.datetime(2017,1,3)
        spx_monthly = web.DataReader("^GSPC", 'yahoo', start, end)
        data = bt.feeds.PandasData(dataname=spx_monthly)
        
        cerebro = bt.Cerebro()
        cerebro.addstrategy(SellInMay)      
        cerebro.adddata(data)
        cerebro.broker.setcash(10000.0)
        cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')     '<= added analyzer'
        
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
        results = cerebro.run()
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
            
        strat = results[0]
        pyfoliozer = strat.analyzers.getbyname('pyfolio')
        returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
        import pyfolio as pf
        pf.create_full_tear_sheet(
            returns,
            positions=positions,
            transactions=transactions,
            gross_lev=gross_lev,
            live_start_date='2005-05-01',
            round_trips=True)
        cerebro.plot()
    

    And the error message:

    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-7-978d7fe7977d> in <module>()
         59 
         60 if __name__ == '__main__':
    ---> 61     runstrat()
    
    <ipython-input-7-978d7fe7977d> in runstrat()
         55         gross_lev=gross_lev,
         56         live_start_date='2005-05-01',
    ---> 57         round_trips=True)
         58     cerebro.plot()
         59 
    
    TypeError: create_full_tear_sheet() got an unexpected keyword argument 'gross_lev'
    

    I tried removing gross_lev=gross_lev, but then the pyfolio only see a whole bunch of NAN:

    Entire data start date: 1950-01-03
    Entire data end date: 2017-01-03
    
    
    Out-of-Sample Months: 802
    Backtest Months: 0
    Performance statistics	All history	Backtest	Out of sample
    annual_return	0.08	nan	0.08
    cum_returns_final	127.95	nan	127.95
    annual_volatility	0.12	nan	0.12
    sharpe_ratio	0.67	nan	0.67
    calmar_ratio	0.16	nan	0.16
    stability_of_timeseries	0.99	nan	0.99
    max_drawdown	-0.48	nan	-0.48
    omega_ratio	1.18	nan	1.18
    sortino_ratio	0.95	nan	0.95
    skew	-1.02	nan	-1.02
    kurtosis	51.99	nan	51.99
    tail_ratio	1.09	nan	1.09
    common_sense_ratio	1.17	nan	1.17
    gross_leverage	0.58	nan	0.58
    information_ratio	-0.01	nan	-0.01
    alpha	0.03	nan	0.03
    beta	0.59	nan	0.59
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-8-10cafd6765c8> in <module>()
         57 
         58 if __name__ == '__main__':
    ---> 59     runstrat()
    
    <ipython-input-8-10cafd6765c8> in runstrat()
         53         transactions=transactions,
         54         live_start_date='1950-01-01',
    ---> 55         round_trips=True)
         56     cerebro.plot()
         57 
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pyfolio\tears.py in create_full_tear_sheet(returns, positions, transactions, market_data, benchmark_rets, slippage, live_start_date, sector_mappings, bayesian, round_trips, estimate_intraday, hide_positions, cone_std, bootstrap, unadjusted_returns, set_context)
        168         benchmark_rets=benchmark_rets,
        169         bootstrap=bootstrap,
    --> 170         set_context=set_context)
        171 
        172     create_interesting_times_tear_sheet(returns,
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pyfolio\plotting.py in call_w_context(*args, **kwargs)
         54         if set_context:
         55             with context():
    ---> 56                 return func(*args, **kwargs)
         57         else:
         58             return func(*args, **kwargs)
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pyfolio\tears.py in create_returns_tear_sheet(returns, positions, live_start_date, cone_std, benchmark_rets, bootstrap, return_fig)
        318         live_start_date=live_start_date,
        319         cone_std=cone_std,
    --> 320         ax=ax_rolling_returns)
        321     ax_rolling_returns.set_title(
        322         'Cumulative returns')
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pyfolio\plotting.py in plot_rolling_returns(returns, factor_returns, live_start_date, logy, cone_std, legend_loc, volatility_match, cone_function, ax, **kwargs)
        793 
        794     is_cum_returns.plot(lw=3, color='forestgreen', alpha=0.6,
    --> 795                         label='Backtest', ax=ax, **kwargs)
        796 
        797     if len(oos_cum_returns) > 0:
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pandas\tools\plotting.py in __call__(self, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
       3598                            colormap=colormap, table=table, yerr=yerr,
       3599                            xerr=xerr, label=label, secondary_y=secondary_y,
    -> 3600                            **kwds)
       3601     __call__.__doc__ = plot_series.__doc__
       3602 
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pandas\tools\plotting.py in plot_series(data, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
       2672                  yerr=yerr, xerr=xerr,
       2673                  label=label, secondary_y=secondary_y,
    -> 2674                  **kwds)
       2675 
       2676 
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pandas\tools\plotting.py in _plot(data, x, y, subplots, ax, kind, **kwds)
       2468         plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
       2469 
    -> 2470     plot_obj.generate()
       2471     plot_obj.draw()
       2472     return plot_obj.result
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pandas\tools\plotting.py in generate(self)
       1039     def generate(self):
       1040         self._args_adjust()
    -> 1041         self._compute_plot_data()
       1042         self._setup_subplots()
       1043         self._make_plot()
    
    C:\Anaconda3\envs\backtrader\lib\site-packages\pandas\tools\plotting.py in _compute_plot_data(self)
       1148         if is_empty:
       1149             raise TypeError('Empty {0!r}: no numeric data to '
    -> 1150                             'plot'.format(numeric_data.__class__.__name__))
       1151 
       1152         self.data = numeric_data
    
    TypeError: Empty 'DataFrame': no numeric data to plot
    

  • administrators

    That's not inside the backtrader api. Apparently pyfolio is redoing its APIs.

    See here for example: https://github.com/quantopian/pyfolio/blob/master/pyfolio/tears.py



  • @backtrader Thanks! Your help is much appreciated. I spent time looking into the issue and found the problem residing at Pyfolio that it couldn't pull the default benchmark SPY data starting from 1950; SPY data is available starting 1993-2-3 but ^GSPC data starts from 1950-1-1.

    The other question I have is, would it be possible to plot both index returns and portfolio value in a single plot using built-in backtrader functions?




  • administrators

    Additionally if the interest is only plotting the returns and the returns of the index, check this blog post: Blog - BTFD

    The entire plot is done with observers which plot the returns of the strategy and the asset.



  • By the way: There is a little bug in another blog post regarding this topic:

    import pyfolio
    pf.create_full_tear_sheet(
    

    should be

    import pyfolio as pf
    pf.create_full_tear_sheet(
    

    I didnt want to open a new topic for this..


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.