#!/usr/bin/env python # coding: utf-8 # # Zipline algorithm analysis example in pyfolio # # Here's an example where we run an algorithm with zipline, then produce tear sheets for that algorithm. # ## Imports # Import pyfolio and zipline, and ingest the pricing data for backtesting. # In[1]: import sys sys.path.append('/Users/george/Desktop/pyfolio/') # In[ ]: import pyfolio as pf get_ipython().run_line_magic('matplotlib', 'inline') # silence warnings import warnings warnings.filterwarnings('ignore') import zipline get_ipython().run_line_magic('load_ext', 'zipline') get_ipython().system('zipline ingest') # ## Run our zipline algorithm # This algorithm can also be adjusted to execute a modified, or completely different, trading strategy. # In[2]: get_ipython().run_cell_magic('zipline', '--start 2004-1-1 --end 2010-1-1 -o results.pickle', '\n# Zipline trading algorithm\n# Taken from zipline.examples.olmar\n\nimport numpy as np\n\nfrom zipline.finance import commission, slippage\n\nSTOCKS = [\'AMD\', \'CERN\', \'COST\', \'DELL\', \'GPS\', \'INTC\', \'MMM\']\n\n\n# On-Line Portfolio Moving Average Reversion\n\n# More info can be found in the corresponding paper:\n# http://icml.cc/2012/papers/168.pdf\ndef initialize(algo, eps=1, window_length=5):\n algo.stocks = STOCKS\n algo.sids = [algo.symbol(symbol) for symbol in algo.stocks]\n algo.m = len(algo.stocks)\n algo.price = {}\n algo.b_t = np.ones(algo.m) / algo.m\n algo.eps = eps\n algo.window_length = window_length\n\n algo.set_commission(commission.PerShare(cost=0))\n algo.set_slippage(slippage.FixedSlippage(spread=0))\n\n\ndef handle_data(algo, data):\n m = algo.m\n\n x_tilde = np.zeros(m)\n b = np.zeros(m)\n\n # find relative moving average price for each asset\n mavgs = data.history(algo.sids, \'price\', algo.window_length, \'1d\').mean()\n for i, sid in enumerate(algo.sids):\n price = data.current(sid, "price")\n # Relative mean deviation\n x_tilde[i] = mavgs[sid] / price\n\n ###########################\n # Inside of OLMAR (algo 2)\n x_bar = x_tilde.mean()\n\n # market relative deviation\n mark_rel_dev = x_tilde - x_bar\n\n # Expected return with current portfolio\n exp_return = np.dot(algo.b_t, x_tilde)\n weight = algo.eps - exp_return\n variability = (np.linalg.norm(mark_rel_dev)) ** 2\n\n # test for divide-by-zero case\n if variability == 0.0:\n step_size = 0\n else:\n step_size = max(0, weight / variability)\n\n b = algo.b_t + step_size * mark_rel_dev\n b_norm = simplex_projection(b)\n np.testing.assert_almost_equal(b_norm.sum(), 1)\n\n rebalance_portfolio(algo, data, b_norm)\n\n # update portfolio\n algo.b_t = b_norm\n\n\ndef rebalance_portfolio(algo, data, desired_port):\n # rebalance portfolio\n for i, sid in enumerate(algo.sids):\n algo.order_target_percent(sid, desired_port[i])\n\n\ndef simplex_projection(v, b=1):\n """Projection vectors to the simplex domain\n Implemented according to the paper: Efficient projections onto the\n l1-ball for learning in high dimensions, John Duchi, et al. ICML 2008.\n Implementation Time: 2011 June 17 by Bin@libin AT pmail.ntu.edu.sg\n Optimization Problem: min_{w}\\| w - v \\|_{2}^{2}\n s.t. sum_{i=1}^{m}=z, w_{i}\\geq 0\n Input: A vector v \\in R^{m}, and a scalar z > 0 (default=1)\n Output: Projection vector w\n :Example:\n >>> proj = simplex_projection([.4 ,.3, -.4, .5])\n >>> print(proj)\n array([ 0.33333333, 0.23333333, 0. , 0.43333333])\n >>> print(proj.sum())\n 1.0\n Original matlab implementation: John Duchi (jduchi@cs.berkeley.edu)\n Python-port: Copyright 2013 by Thomas Wiecki (thomas.wiecki@gmail.com).\n """\n\n v = np.asarray(v)\n p = len(v)\n\n # Sort v into u in descending order\n v = (v > 0) * v\n u = np.sort(v)[::-1]\n sv = np.cumsum(u)\n\n rho = np.where(u > (sv - b) / np.arange(1, p + 1))[0][-1]\n theta = np.max([0, (sv[rho] - b) / (rho + 1)])\n w = (v - theta)\n w[w < 0] = 0\n return w\n') # ## Extract metrics # Get the returns, positions, and transactions from the zipline backtest object. # In[3]: import pandas as pd results = pd.read_pickle('results.pickle') returns, positions, transactions = pf.utils.extract_rets_pos_txn_from_zipline(results) # ## Single plot example # Make one plot of the top 5 drawdown periods. # In[4]: pf.plot_drawdown_periods(returns, top=5).set_xlabel('Date') # ## Full tear sheet example # Create a full tear sheet for our algorithm. As an example, set the live start date to something arbitrary. # In[5]: pf.create_full_tear_sheet(returns, positions=positions, transactions=transactions, live_start_date='2009-10-22', round_trips=True) # ## Suppressing symbol output # # When sharing tear sheets it might be undesirable to display which symbols where used by a strategy. To suppress these in the tear sheet you can pass `hide_positions=True`. # In[6]: pf.create_full_tear_sheet(returns, positions=positions, transactions=transactions, live_start_date='2009-10-22', hide_positions=True) # In[ ]: