Notebook
In [9]:
import matplotlib.pyplot as plt
import numpy as np
import pyfolio as pf
import pandas as pd

from datetime import datetime

Load backtests

In [15]:
# Allocate equal weights to momentum and mean-reversion strategy. 
weights = (0.5, 0.5)
start_value = 100000

backtest_names = {
    'momentum' : '5b54db6068812144283cb9d0',
    'mean_reversion' : '5b54d542b9c76642a5e62cb6'
}

backtests = {}
for b in backtest_names:
    print b
    backtests[b] = get_backtest(backtest_names[b])
    backtests[b].cumulative_performance.ending_portfolio_value.plot(label=b)
plt.legend(loc='best')
mean_reversion
100% Time: 0:00:00|###########################################################|
momentum
100% Time: 0:00:00|###########################################################|
Out[15]:
<matplotlib.legend.Legend at 0x7f5bdf61fa10>

Check returns of individual algorithms and correlations between algorithms.

In [16]:
returns = {}
for b in backtest_names:
    bt = backtests[b]
    returns[b] = bt.daily_performance.returns
    print ('%s CAGR: %f' % (b, pf.timeseries.annual_return(returns[b])))
    
print
df = pd.DataFrame(returns)
print "Correlations"
print df.corr() # correlation coefficient
mean_reversion CAGR: 0.236432
momentum CAGR: 0.388478

Correlations
                mean_reversion  momentum
mean_reversion        1.000000 -0.213302
momentum             -0.213302  1.000000
/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:5: DeprecationWarning: Risk functions in pyfolio.timeseries are deprecated and will be removed in a future release. Please install the empyrical package instead.
  """

Get the return for the full portfolio by getting the dot product of the returns and weights.

In [12]:
df2 = df + 1
total_return = df2.dot(weights) - 1

Portfolio stats.

In [17]:
def print_some_stats(daily_return):
    print "Annual return {0:.2f}%".format(pf.timeseries.annual_return(daily_return)*100)
    print "Annual volatility {0:.2f}%".format(pf.timeseries.annual_volatility(daily_return)*100)
    print "Sharpe ratio %f" % pf.timeseries.sharpe_ratio(daily_return)
    print "Sortino ratio %f" % pf.timeseries.sortino_ratio(daily_return)
    print "Max drawdown {0:.2f}%".format(pf.timeseries.max_drawdown(daily_return)*100)
    print "Annual returns"
    print pf.timeseries.aggregate_returns(daily_return, 'yearly')

print "Before rebalancing"
total_return.name = 'Before rebalancing'
print_some_stats(total_return)
print total_return.cumulative_performance.ending_portfolio_value.plot(label=b)
Before rebalancing
Annual return 31.93%
Annual volatility 9.58%
Sharpe ratio 2.941043
Sortino ratio 6.215240
Max drawdown -4.12%
Annual returns
2016    0.183019
2017    0.250536
2018    0.209387
Name: Before rebalancing, dtype: float64
/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:2: DeprecationWarning: Risk functions in pyfolio.timeseries are deprecated and will be removed in a future release. Please install the empyrical package instead.
  
/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:3: DeprecationWarning: Risk functions in pyfolio.timeseries are deprecated and will be removed in a future release. Please install the empyrical package instead.
  This is separate from the ipykernel package so we can avoid doing imports until
/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:4: DeprecationWarning: Risk functions in pyfolio.timeseries are deprecated and will be removed in a future release. Please install the empyrical package instead.
  after removing the cwd from sys.path.
/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:5: DeprecationWarning: Risk functions in pyfolio.timeseries are deprecated and will be removed in a future release. Please install the empyrical package instead.
  """
/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:6: DeprecationWarning: Risk functions in pyfolio.timeseries are deprecated and will be removed in a future release. Please install the empyrical package instead.
  
/usr/local/lib/python2.7/dist-packages/ipykernel_launcher.py:8: DeprecationWarning: Risk functions in pyfolio.timeseries are deprecated and will be removed in a future release. Please install the empyrical package instead.
  

AttributeErrorTraceback (most recent call last)
<ipython-input-17-43ca7ccb2037> in <module>()
     11 total_return.name = 'Before rebalancing'
     12 print_some_stats(total_return)
---> 13 print total_return.cumulative_performance.ending_portfolio_value.plot(label=b)

/usr/local/lib/python2.7/dist-packages/pandas/core/generic.pyc in __getattr__(self, name)
   2670             if name in self._info_axis:
   2671                 return self[name]
-> 2672             return object.__getattribute__(self, name)
   2673 
   2674     def __setattr__(self, name, value):

AttributeError: 'Series' object has no attribute 'cumulative_performance'
In [18]:
pf.create_returns_tear_sheet(total_return)
Start date2016-07-01
End date2018-07-19
Total months25
Backtest
Annual return 31.9%
Cumulative returns 78.9%
Annual volatility 9.6%
Sharpe ratio 2.94
Calmar ratio 7.76
Stability 0.97
Max drawdown -4.1%
Omega ratio 1.76
Sortino ratio 6.22
Skew 1.41
Kurtosis 4.55
Tail ratio 1.80
Daily value at risk -1.1%
Alpha 0.29
Beta -0.00
Worst drawdown periods Net drawdown in % Peak date Valley date Recovery date Duration
0 4.12 2017-03-24 2017-04-24 2017-08-17 105
1 3.39 2016-08-08 2016-08-23 2016-09-09 25
2 2.98 2016-09-28 2016-10-10 2016-10-20 17
3 2.84 2016-09-09 2016-09-22 2016-09-28 14
4 2.27 2018-06-08 2018-06-27 2018-07-13 26
In [19]:
pf.create_full_tear_sheet(total_return)
Start date2016-07-01
End date2018-07-19
Total months25
Backtest
Annual return 31.9%
Cumulative returns 78.9%
Annual volatility 9.6%
Sharpe ratio 2.94
Calmar ratio 7.76
Stability 0.97
Max drawdown -4.1%
Omega ratio 1.76
Sortino ratio 6.22
Skew 1.41
Kurtosis 4.55
Tail ratio 1.80
Daily value at risk -1.1%
Alpha 0.29
Beta -0.00
Worst drawdown periods Net drawdown in % Peak date Valley date Recovery date Duration
0 4.12 2017-03-24 2017-04-24 2017-08-17 105
1 3.39 2016-08-08 2016-08-23 2016-09-09 25
2 2.98 2016-09-28 2016-10-10 2016-10-20 17
3 2.84 2016-09-09 2016-09-22 2016-09-28 14
4 2.27 2018-06-08 2018-06-27 2018-07-13 26
Stress Events mean min max
New Normal 0.11% -1.62% 3.92%