<jupyter_start><jupyter_text>From `zipline` to `pyfolio`  `pyfolio` Features* State-of-the-art portfolio and risk analytics* http://quantopian.github.io/pyfolio/* Open source and free: Apache v2 license* Can be used:   - stand alone   - with Zipline   - on Quantopian   - with PyThalesians  Installation* Use Anaconda to get a Python system with the full PyData ecosystem.* `pip install pyfolio`  Zipline + pyfolio* Open-source backtester by Quantopian Inc.* Powers Quantopian.com* Various models for transaction costs and slippage.<jupyter_code>from pathlib import Path
import warnings
import re
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from pyfolio.utils import extract_rets_pos_txn_from_zipline
from pyfolio.plotting import (plot_perf_stats,
                              show_perf_stats,
                              plot_rolling_beta,
                              plot_rolling_fama_french,
                              plot_rolling_returns,
                              plot_rolling_sharpe,
                              plot_rolling_volatility,
                              plot_drawdown_periods,
                              plot_drawdown_underwater)

from pyfolio.timeseries import perf_stats, extract_interesting_date_ranges
# from pyfolio.tears import create_returns_tear_sheet
%matplotlib inline
plt.style.use('fivethirtyeight')
warnings.filterwarnings('ignore')
with pd.HDFStore('../01_trading_zipline/backtests.h5') as store:
    backtest = store['backtest']
backtest.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 755 entries, 2015-01-02 to 2017-12-29
Data columns (total 39 columns):
algo_volatility            754 non-null float64
algorithm_period_return    755 non-null float64
alpha                      754 non-null float64
benchmark_period_return    755 non-null float64
benchmark_volatility       754 non-null float64
beta                       754 non-null float64
capital_used               755 non-null float64
ending_cash                755 non-null float64
ending_exposure            755 non-null float64
ending_value               755 non-null float64
excess_return              755 non-null float64
factor_data                755 non-null object
gross_leverage             755 non-null float64
long_exposure              755 non-null float64
long_value                 755 non-null float64
longs_count                755 non-null int64
max_drawdown               755 non-null float64
max_leverage               755 non-null float64
net_leverage   [...]<jupyter_text>Converting data from zipline to pyfolio<jupyter_code>returns, positions, transactions = extract_rets_pos_txn_from_zipline(backtest)
returns.head().append(returns.tail())
positions.columns = [c.symbol for c in positions.columns[:-1]] + ['cash']
positions.index = positions.index.normalize()
positions.info()
transactions.symbol = transactions.symbol.apply(lambda x: x.symbol)
transactions.head().append(transactions.tail())
HDF_PATH = Path('..', '00_data', 'assets.h5')<jupyter_output><empty_output><jupyter_text>Sector Map<jupyter_code>assets = positions.columns[:-1]
with pd.HDFStore(HDF_PATH) as store:
    df = store.get('us_equities/stocks')['sector'].dropna()
    df = df[~df.index.duplicated()]
sector_map = df.reindex(assets).fillna('Unknown').to_dict()<jupyter_output><empty_output><jupyter_text>Benchmark<jupyter_code>with pd.HDFStore(HDF_PATH) as store:
    benchmark_rets = store['sp500/prices'].close.pct_change()
benchmark_rets.name = 'S&P500'
benchmark_rets = benchmark_rets.tz_localize('UTC').filter(returns.index)
benchmark_rets.tail()
perf_stats(returns=returns, factor_returns=benchmark_rets, positions=positions, transactions=transactions)
plot_perf_stats(returns=returns, factor_returns=benchmark_rets)<jupyter_output><empty_output><jupyter_text>Returns Analysis<jupyter_code>oos_date = '2017-01-01'
show_perf_stats(returns=returns, 
                factor_returns=benchmark_rets, 
                positions=positions, 
                transactions=transactions, 
                live_start_date=oos_date)<jupyter_output>In-sample months: 24
Out-of-sample months: 11<jupyter_text>Rolling Returns OOS<jupyter_code>plot_rolling_returns(returns=returns, factor_returns=benchmark_rets, live_start_date=oos_date, cone_std=(1.0, 1.5, 2.0))
plt.gcf().set_size_inches(14, 8)<jupyter_output><empty_output><jupyter_text>Rolling Sharpe<jupyter_code>plot_rolling_sharpe(returns=returns)
plt.gcf().set_size_inches(14, 8);<jupyter_output><empty_output><jupyter_text>Rolling Beta<jupyter_code>plot_rolling_beta(returns=returns, factor_returns=benchmark_rets)
plt.gcf().set_size_inches(14, 8);
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(16, 10))
axes = ax.flatten()

plot_drawdown_periods(returns=returns, ax=axes[0])
plot_rolling_beta(returns=returns, factor_returns=benchmark_rets, ax=axes[1])
plot_drawdown_underwater(returns=returns, ax=axes[2])
plot_rolling_sharpe(returns=returns)
plt.tight_layout();<jupyter_output><empty_output><jupyter_text>Modeling Event Risk<jupyter_code>interesting_times = extract_interesting_date_ranges(returns=returns)
(interesting_times['Fall2015']
 .to_frame('pf').join(benchmark_rets)
 .add(1).cumprod().sub(1)
 .plot(lw=2, figsize=(14, 6), title='Post-Brexit Turmoil'))
plt.tight_layout()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09614665170220726, 'fraction_numerical': 0.03179947624392069, 'mean_word_length': 4.116746411483254, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '479816', 'license': 'MIT', 'n_tokens_mistral': 1856, 'n_tokens_neox': 1683, 'n_words': 320, 'path': 'Chapter05/02_risk_metrics_pyfolio/pyfolio_demo.ipynb', 'repo_name': 'PacktPublishing/Hands-On-Machine-Learning-for-Trading', 'size': '5346'}