Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
packtpublishing
GitHub Repository: packtpublishing/machine-learning-for-algorithmic-trading-second-edition
Path: blob/master/05_strategy_evaluation/01_backtest_with_trades.ipynb
2923 views
Kernel: Python 3

zipline MeanReversion Backtest

In the chapter 04, we introduced Zipline to simulate the computation of alpha factors from trailing cross-sectional market, fundamental, and alternative data.

Now we will exploit the alpha factors to derive and act on buy and sell signals using the custom MeanReversion factor developed in the last chapter.

Imports

import warnings warnings.filterwarnings('ignore')
import sys import numpy as np import pandas as pd from pytz import UTC from logbook import (NestedSetup, NullHandler, Logger, StreamHandler, StderrHandler, INFO, WARNING, DEBUG, ERROR) from zipline import run_algorithm from zipline.api import (attach_pipeline, date_rules, time_rules, get_datetime, order_target_percent, pipeline_output, record, schedule_function, get_open_orders, calendars, set_commission, set_slippage) from zipline.finance import commission, slippage from zipline.pipeline import Pipeline, CustomFactor from zipline.pipeline.factors import Returns, AverageDollarVolume from pyfolio.utils import extract_rets_pos_txn_from_zipline import matplotlib.pyplot as plt import seaborn as sns
sns.set_style('whitegrid')

Logging Setup

# setup stdout logging format_string = '[{record.time: %H:%M:%S.%f}]: {record.level_name}: {record.message}' zipline_logging = NestedSetup([NullHandler(level=DEBUG), StreamHandler(sys.stdout, format_string=format_string, level=INFO), StreamHandler(sys.stderr, level=ERROR)]) zipline_logging.push_application() log = Logger('Algorithm')

Algo Settings

# Settings MONTH = 21 YEAR = 12 * MONTH N_LONGS = 50 N_SHORTS = 50 VOL_SCREEN = 500
start = pd.Timestamp('2013-01-01', tz=UTC) end = pd.Timestamp('2017-01-01', tz=UTC) capital_base = 1e7

Mean Reversion Factor

class MeanReversion(CustomFactor): """Compute ratio of latest monthly return to 12m average, normalized by std dev of monthly returns""" inputs = [Returns(window_length=MONTH)] window_length = YEAR def compute(self, today, assets, out, monthly_returns): df = pd.DataFrame(monthly_returns) out[:] = df.iloc[-1].sub(df.mean()).div(df.std())

Create Pipeline

The Pipeline created by the compute_factors() method returns a table with a long and a short column for the 25 stocks with the largest negative and positive deviations of their last monthly return from its annual average, normalized by the standard deviation. It also limited the universe to the 500 stocks with the highest average trading volume over the last 30 trading days.

def compute_factors(): """Create factor pipeline incl. mean reversion, filtered by 30d Dollar Volume; capture factor ranks""" mean_reversion = MeanReversion() dollar_volume = AverageDollarVolume(window_length=30) return Pipeline(columns={'longs' : mean_reversion.bottom(N_LONGS), 'shorts' : mean_reversion.top(N_SHORTS), 'ranking': mean_reversion.rank(ascending=False)}, screen=dollar_volume.top(VOL_SCREEN))

Before_trading_start() ensures the daily execution of the pipeline and the recording of the results, including the current prices.

def before_trading_start(context, data): """Run factor pipeline""" context.factor_data = pipeline_output('factor_pipeline') record(factor_data=context.factor_data.ranking) assets = context.factor_data.index record(prices=data.current(assets, 'price'))

Set up Rebalancing

The new rebalance() method submits trade orders to the exec_trades() method for the assets flagged for long and short positions by the pipeline with equal positive and negative weights. It also divests any current holdings that are no longer included in the factor signals:

def rebalance(context, data): """Compute long, short and obsolete holdings; place trade orders""" factor_data = context.factor_data assets = factor_data.index longs = assets[factor_data.longs] shorts = assets[factor_data.shorts] divest = context.portfolio.positions.keys() - longs.union(shorts) log.info('{} | Longs: {:2.0f} | Shorts: {:2.0f} | {:,.2f}'.format(get_datetime().date(), len(longs), len(shorts), context.portfolio.portfolio_value)) exec_trades(data, assets=divest, target_percent=0) exec_trades(data, assets=longs, target_percent=1 / N_LONGS if N_LONGS else 0) exec_trades(data, assets=shorts, target_percent=-1 / N_SHORTS if N_SHORTS else 0)
def exec_trades(data, assets, target_percent): """Place orders for assets using target portfolio percentage""" for asset in assets: if data.can_trade(asset) and not get_open_orders(asset): order_target_percent(asset, target_percent)

Initialize Backtest

The rebalance() method runs according to date_rules and time_rules set by the schedule_function() utility at the beginning of the week, right after market_open as stipulated by the built-in US_EQUITIES calendar (see docs for details on rules).

You can also specify a trade commission both in relative terms and as a minimum amount. There is also an option to define slippage, which is the cost of an adverse change in price between trade decision and execution

def initialize(context): """Setup: register pipeline, schedule rebalancing, and set trading params""" attach_pipeline(compute_factors(), 'factor_pipeline') schedule_function(rebalance, date_rules.week_start(), time_rules.market_open(), calendar=calendars.US_EQUITIES) set_commission(us_equities=commission.PerShare(cost=0.00075, min_trade_cost=.01)) set_slippage(us_equities=slippage.VolumeShareSlippage(volume_limit=0.0025, price_impact=0.01))

Run Algorithm

The algorithm executes upon calling the run_algorithm() function and returns the backtest performance DataFrame.

backtest = run_algorithm(start=start, end=end, initialize=initialize, before_trading_start=before_trading_start, bundle='quandl', capital_base=capital_base)
[ 19:45:47.847522]: INFO: 2013-01-07 | Longs: 10 | Shorts: 2 | 10,000,000.00 [ 19:45:52.095417]: INFO: 2013-01-14 | Longs: 13 | Shorts: 3 | 10,027,422.36 [ 19:45:52.700469]: INFO: 2013-01-22 | Longs: 8 | Shorts: 5 | 10,097,663.57 [ 19:45:53.190897]: INFO: 2013-01-28 | Longs: 5 | Shorts: 14 | 10,106,150.06 [ 19:45:53.810739]: INFO: 2013-02-04 | Longs: 12 | Shorts: 11 | 10,135,417.26 [ 19:45:54.448141]: INFO: 2013-02-11 | Longs: 11 | Shorts: 13 | 10,182,644.42 [ 19:45:55.093475]: INFO: 2013-02-19 | Longs: 21 | Shorts: 11 | 10,127,755.45 [ 19:45:55.646754]: INFO: 2013-02-25 | Longs: 16 | Shorts: 8 | 10,180,357.23 [ 19:45:56.316751]: INFO: 2013-03-04 | Longs: 10 | Shorts: 10 | 10,200,300.19 [ 19:45:56.942645]: INFO: 2013-03-11 | Longs: 12 | Shorts: 7 | 10,240,453.13 [ 19:45:57.560857]: INFO: 2013-03-18 | Longs: 7 | Shorts: 7 | 10,150,394.01 [ 19:45:58.174192]: INFO: 2013-03-25 | Longs: 8 | Shorts: 7 | 10,149,029.25 [ 19:45:58.673395]: INFO: 2013-04-01 | Longs: 4 | Shorts: 6 | 10,178,638.39 [ 19:45:59.255032]: INFO: 2013-04-08 | Longs: 6 | Shorts: 13 | 10,188,518.05 [ 19:45:59.870276]: INFO: 2013-04-15 | Longs: 5 | Shorts: 14 | 10,185,696.44 [ 19:46:00.499841]: INFO: 2013-04-22 | Longs: 5 | Shorts: 24 | 10,154,587.17 [ 19:46:01.161558]: INFO: 2013-04-29 | Longs: 5 | Shorts: 10 | 10,189,194.78 [ 19:46:01.801803]: INFO: 2013-05-06 | Longs: 2 | Shorts: 10 | 10,166,211.32 [ 19:46:02.402998]: INFO: 2013-05-13 | Longs: 4 | Shorts: 8 | 9,981,220.24 [ 19:46:02.981176]: INFO: 2013-05-20 | Longs: 8 | Shorts: 9 | 9,943,518.58 [ 19:46:03.574252]: INFO: 2013-05-28 | Longs: 13 | Shorts: 5 | 9,905,180.12 [ 19:46:04.081390]: INFO: 2013-06-03 | Longs: 19 | Shorts: 6 | 9,962,705.11 [ 19:46:04.716038]: INFO: 2013-06-10 | Longs: 10 | Shorts: 3 | 9,953,403.78 [ 19:46:05.341995]: INFO: 2013-06-17 | Longs: 9 | Shorts: 6 | 9,978,043.58 [ 19:46:05.935565]: INFO: 2013-06-24 | Longs: 9 | Shorts: 2 | 9,875,082.86 [ 19:46:06.521659]: INFO: 2013-07-01 | Longs: 15 | Shorts: 3 | 9,932,122.01 [ 19:46:07.025303]: INFO: 2013-07-08 | Longs: 13 | Shorts: 3 | 9,976,143.93 [ 19:46:09.239819]: INFO: 2013-07-15 | Longs: 11 | Shorts: 4 | 10,094,240.18 [ 19:46:09.846010]: INFO: 2013-07-22 | Longs: 6 | Shorts: 2 | 10,056,638.95 [ 19:46:10.440213]: INFO: 2013-07-29 | Longs: 12 | Shorts: 3 | 10,051,076.70 [ 19:46:11.025538]: INFO: 2013-08-05 | Longs: 8 | Shorts: 12 | 10,138,418.95 [ 19:46:11.643550]: INFO: 2013-08-12 | Longs: 7 | Shorts: 10 | 10,146,586.21 [ 19:46:12.256360]: INFO: 2013-08-19 | Longs: 7 | Shorts: 9 | 10,181,590.85 [ 19:46:12.861775]: INFO: 2013-08-26 | Longs: 7 | Shorts: 2 | 10,178,592.71 [ 19:46:13.450842]: INFO: 2013-09-03 | Longs: 5 | Shorts: 2 | 10,226,884.83 [ 19:46:13.908184]: INFO: 2013-09-09 | Longs: 6 | Shorts: 4 | 10,210,627.07 [ 19:46:14.476657]: INFO: 2013-09-16 | Longs: 6 | Shorts: 5 | 10,266,501.96 [ 19:46:15.061177]: INFO: 2013-09-23 | Longs: 6 | Shorts: 3 | 10,258,815.75 [ 19:46:15.636866]: INFO: 2013-09-30 | Longs: 10 | Shorts: 8 | 10,233,855.17 [ 19:46:16.234862]: INFO: 2013-10-07 | Longs: 13 | Shorts: 7 | 10,227,149.62 [ 19:46:16.852245]: INFO: 2013-10-14 | Longs: 14 | Shorts: 3 | 10,278,149.27 [ 19:46:17.465788]: INFO: 2013-10-21 | Longs: 15 | Shorts: 8 | 10,187,013.14 [ 19:46:18.096059]: INFO: 2013-10-28 | Longs: 11 | Shorts: 6 | 10,323,170.17 [ 19:46:18.717588]: INFO: 2013-11-04 | Longs: 6 | Shorts: 10 | 10,214,759.93 [ 19:46:19.327792]: INFO: 2013-11-11 | Longs: 2 | Shorts: 5 | 10,257,347.04 [ 19:46:19.915615]: INFO: 2013-11-18 | Longs: 4 | Shorts: 9 | 10,245,333.87 [ 19:46:20.502456]: INFO: 2013-11-25 | Longs: 4 | Shorts: 8 | 10,279,469.50 [ 19:46:20.988722]: INFO: 2013-12-02 | Longs: 7 | Shorts: 2 | 10,302,532.04 [ 19:46:21.572209]: INFO: 2013-12-09 | Longs: 10 | Shorts: 3 | 10,320,355.73 [ 19:46:22.162478]: INFO: 2013-12-16 | Longs: 17 | Shorts: 2 | 10,353,234.81 [ 19:46:22.828759]: INFO: 2013-12-23 | Longs: 11 | Shorts: 4 | 10,269,888.43 [ 19:46:23.341442]: INFO: 2013-12-30 | Longs: 10 | Shorts: 6 | 10,293,416.34 [ 19:46:23.831108]: INFO: 2014-01-06 | Longs: 12 | Shorts: 5 | 10,300,370.23 [ 19:46:24.431977]: INFO: 2014-01-13 | Longs: 8 | Shorts: 3 | 10,321,419.65 [ 19:46:26.736086]: INFO: 2014-01-21 | Longs: 14 | Shorts: 4 | 10,301,321.23 [ 19:46:27.234386]: INFO: 2014-01-27 | Longs: 16 | Shorts: 4 | 10,272,301.28 [ 19:46:27.854221]: INFO: 2014-02-03 | Longs: 16 | Shorts: 7 | 10,190,046.47 [ 19:46:28.477219]: INFO: 2014-02-10 | Longs: 10 | Shorts: 8 | 10,173,544.07 [ 19:46:29.093780]: INFO: 2014-02-18 | Longs: 8 | Shorts: 11 | 10,146,175.51 [ 19:46:29.588348]: INFO: 2014-02-24 | Longs: 8 | Shorts: 11 | 10,135,284.41 [ 19:46:30.193018]: INFO: 2014-03-03 | Longs: 5 | Shorts: 10 | 10,206,465.49 [ 19:46:30.794267]: INFO: 2014-03-10 | Longs: 8 | Shorts: 5 | 10,193,416.12 [ 19:46:31.376171]: INFO: 2014-03-17 | Longs: 6 | Shorts: 4 | 10,150,092.53 [ 19:46:31.945393]: INFO: 2014-03-24 | Longs: 7 | Shorts: 3 | 10,157,127.09 [ 19:46:32.519026]: INFO: 2014-03-31 | Longs: 10 | Shorts: 3 | 10,127,717.05 [ 19:46:33.112206]: INFO: 2014-04-07 | Longs: 10 | Shorts: 10 | 9,940,554.60 [ 19:46:33.719175]: INFO: 2014-04-14 | Longs: 10 | Shorts: 12 | 9,922,172.04 [ 19:46:34.231646]: INFO: 2014-04-21 | Longs: 9 | Shorts: 16 | 9,977,695.73 [ 19:46:34.878499]: INFO: 2014-04-28 | Longs: 8 | Shorts: 11 | 9,925,818.81 [ 19:46:35.505814]: INFO: 2014-05-05 | Longs: 6 | Shorts: 8 | 9,994,098.05 [ 19:46:36.106871]: INFO: 2014-05-12 | Longs: 3 | Shorts: 9 | 9,959,988.27 [ 19:46:36.694084]: INFO: 2014-05-19 | Longs: 2 | Shorts: 6 | 9,952,316.59 [ 19:46:37.255650]: INFO: 2014-05-27 | Longs: 5 | Shorts: 5 | 9,975,477.08 [ 19:46:37.725009]: INFO: 2014-06-02 | Longs: 6 | Shorts: 3 | 9,987,026.35 [ 19:46:38.297596]: INFO: 2014-06-09 | Longs: 8 | Shorts: 5 | 10,024,385.61 [ 19:46:38.889416]: INFO: 2014-06-16 | Longs: 13 | Shorts: 13 | 9,983,402.35 [ 19:46:39.531742]: INFO: 2014-06-23 | Longs: 8 | Shorts: 15 | 9,996,939.06 [ 19:46:40.176475]: INFO: 2014-06-30 | Longs: 12 | Shorts: 15 | 10,037,014.26 [ 19:46:40.712931]: INFO: 2014-07-07 | Longs: 14 | Shorts: 12 | 10,082,385.12 [ 19:46:41.360016]: INFO: 2014-07-14 | Longs: 5 | Shorts: 14 | 10,089,176.51 [ 19:46:43.605913]: INFO: 2014-07-21 | Longs: 13 | Shorts: 11 | 10,128,809.09 [ 19:46:44.252207]: INFO: 2014-07-28 | Longs: 11 | Shorts: 11 | 10,119,893.60 [ 19:46:44.887652]: INFO: 2014-08-04 | Longs: 11 | Shorts: 19 | 10,110,604.81 [ 19:46:45.559208]: INFO: 2014-08-11 | Longs: 14 | Shorts: 11 | 10,259,687.80 [ 19:46:46.223072]: INFO: 2014-08-18 | Longs: 11 | Shorts: 14 | 10,204,032.36 [ 19:46:46.865650]: INFO: 2014-08-25 | Longs: 12 | Shorts: 14 | 10,211,914.68 [ 19:46:47.532028]: INFO: 2014-09-02 | Longs: 7 | Shorts: 9 | 10,176,282.96 [ 19:46:48.087475]: INFO: 2014-09-08 | Longs: 2 | Shorts: 13 | 10,227,375.20 [ 19:46:48.690214]: INFO: 2014-09-15 | Longs: 5 | Shorts: 4 | 10,232,017.60 [ 19:46:49.278901]: INFO: 2014-09-22 | Longs: 6 | Shorts: 8 | 10,188,352.29 [ 19:46:49.864395]: INFO: 2014-09-29 | Longs: 4 | Shorts: 13 | 10,153,790.76 [ 19:46:50.465842]: INFO: 2014-10-06 | Longs: 12 | Shorts: 9 | 10,137,941.09 [ 19:46:51.088348]: INFO: 2014-10-13 | Longs: 12 | Shorts: 17 | 10,008,763.46 [ 19:46:51.789845]: INFO: 2014-10-20 | Longs: 21 | Shorts: 6 | 10,132,979.74 [ 19:46:52.464740]: INFO: 2014-10-27 | Longs: 13 | Shorts: 7 | 10,130,508.74 [ 19:46:53.109743]: INFO: 2014-11-03 | Longs: 6 | Shorts: 0 | 10,202,585.17 [ 19:46:53.696345]: INFO: 2014-11-10 | Longs: 7 | Shorts: 6 | 10,112,658.72 [ 19:46:54.281286]: INFO: 2014-11-17 | Longs: 6 | Shorts: 10 | 10,149,797.97 [ 19:46:54.880329]: INFO: 2014-11-24 | Longs: 6 | Shorts: 7 | 10,159,664.13 [ 19:46:55.363560]: INFO: 2014-12-01 | Longs: 12 | Shorts: 13 | 10,112,949.01 [ 19:46:56.008206]: INFO: 2014-12-08 | Longs: 11 | Shorts: 4 | 9,883,877.18 [ 19:46:56.621757]: INFO: 2014-12-15 | Longs: 13 | Shorts: 3 | 9,748,742.24 [ 19:46:57.211873]: INFO: 2014-12-22 | Longs: 7 | Shorts: 4 | 10,162,433.56 [ 19:46:57.700293]: INFO: 2014-12-29 | Longs: 10 | Shorts: 8 | 10,153,178.89 [ 19:46:58.195367]: INFO: 2015-01-05 | Longs: 6 | Shorts: 3 | 10,058,855.77 [ 19:46:58.779960]: INFO: 2015-01-12 | Longs: 7 | Shorts: 6 | 10,013,742.96 [ 19:47:00.983066]: INFO: 2015-01-20 | Longs: 12 | Shorts: 7 | 9,911,930.16 [ 19:47:01.477727]: INFO: 2015-01-26 | Longs: 11 | Shorts: 8 | 9,933,179.35 [ 19:47:02.097079]: INFO: 2015-02-02 | Longs: 18 | Shorts: 7 | 9,874,894.91 [ 19:47:02.753928]: INFO: 2015-02-09 | Longs: 15 | Shorts: 6 | 10,026,955.51 [ 19:47:03.391743]: INFO: 2015-02-17 | Longs: 12 | Shorts: 11 | 10,080,570.15 [ 19:47:03.912410]: INFO: 2015-02-23 | Longs: 13 | Shorts: 7 | 10,087,564.34 [ 19:47:04.539404]: INFO: 2015-03-02 | Longs: 16 | Shorts: 7 | 10,042,612.79 [ 19:47:05.185830]: INFO: 2015-03-09 | Longs: 12 | Shorts: 5 | 9,963,112.34 [ 19:47:05.953729]: INFO: 2015-03-16 | Longs: 15 | Shorts: 2 | 10,023,732.49 [ 19:47:06.644113]: INFO: 2015-03-23 | Longs: 10 | Shorts: 2 | 10,078,627.34 [ 19:47:07.381910]: INFO: 2015-03-30 | Longs: 13 | Shorts: 4 | 10,072,282.97 [ 19:47:07.875927]: INFO: 2015-04-06 | Longs: 12 | Shorts: 3 | 10,123,357.71 [ 19:47:08.473323]: INFO: 2015-04-13 | Longs: 5 | Shorts: 8 | 10,165,443.63 [ 19:47:09.071872]: INFO: 2015-04-20 | Longs: 14 | Shorts: 11 | 10,161,371.72 [ 19:47:09.718897]: INFO: 2015-04-27 | Longs: 12 | Shorts: 9 | 10,114,674.77 [ 19:47:10.361190]: INFO: 2015-05-04 | Longs: 8 | Shorts: 13 | 10,111,362.19 [ 19:47:11.004516]: INFO: 2015-05-11 | Longs: 7 | Shorts: 8 | 10,117,885.18 [ 19:47:11.623698]: INFO: 2015-05-18 | Longs: 5 | Shorts: 7 | 10,118,338.65 [ 19:47:12.214493]: INFO: 2015-05-26 | Longs: 3 | Shorts: 5 | 10,125,037.38 [ 19:47:12.687940]: INFO: 2015-06-01 | Longs: 5 | Shorts: 8 | 10,140,937.50 [ 19:47:13.273093]: INFO: 2015-06-08 | Longs: 10 | Shorts: 6 | 10,160,546.75 [ 19:47:13.875858]: INFO: 2015-06-15 | Longs: 14 | Shorts: 6 | 10,135,990.35 [ 19:47:14.507273]: INFO: 2015-06-22 | Longs: 10 | Shorts: 4 | 10,244,177.64 [ 19:47:15.125479]: INFO: 2015-06-29 | Longs: 18 | Shorts: 5 | 10,137,986.21 [ 19:47:15.639425]: INFO: 2015-07-06 | Longs: 12 | Shorts: 10 | 10,170,113.59 [ 19:47:16.274104]: INFO: 2015-07-13 | Longs: 7 | Shorts: 7 | 10,244,091.21 [ 19:47:16.890872]: INFO: 2015-07-20 | Longs: 5 | Shorts: 11 | 10,240,223.17 [ 19:47:19.076221]: INFO: 2015-07-27 | Longs: 7 | Shorts: 13 | 10,311,588.77 [ 19:47:19.685814]: INFO: 2015-08-03 | Longs: 5 | Shorts: 12 | 10,277,581.93 [ 19:47:20.300030]: INFO: 2015-08-10 | Longs: 3 | Shorts: 11 | 10,308,010.70 [ 19:47:20.899285]: INFO: 2015-08-17 | Longs: 5 | Shorts: 8 | 10,274,866.69 [ 19:47:21.515497]: INFO: 2015-08-24 | Longs: 17 | Shorts: 7 | 10,262,054.06 [ 19:47:22.140685]: INFO: 2015-08-31 | Longs: 14 | Shorts: 5 | 10,388,393.11 [ 19:47:22.759612]: INFO: 2015-09-08 | Longs: 21 | Shorts: 5 | 10,453,422.88 [ 19:47:23.291611]: INFO: 2015-09-14 | Longs: 11 | Shorts: 8 | 10,407,866.97 [ 19:47:23.924105]: INFO: 2015-09-21 | Longs: 12 | Shorts: 9 | 10,461,020.10 [ 19:47:24.550563]: INFO: 2015-09-28 | Longs: 15 | Shorts: 7 | 10,413,522.87 [ 19:47:25.186792]: INFO: 2015-10-05 | Longs: 2 | Shorts: 7 | 10,684,535.25 [ 19:47:25.788689]: INFO: 2015-10-12 | Longs: 10 | Shorts: 7 | 10,677,559.63 [ 19:47:26.398941]: INFO: 2015-10-19 | Longs: 6 | Shorts: 8 | 10,720,533.14 [ 19:47:26.999715]: INFO: 2015-10-26 | Longs: 11 | Shorts: 12 | 10,585,301.22 [ 19:47:27.629153]: INFO: 2015-11-02 | Longs: 14 | Shorts: 6 | 10,594,718.88 [ 19:47:28.262618]: INFO: 2015-11-09 | Longs: 10 | Shorts: 5 | 10,402,671.77 [ 19:47:28.875914]: INFO: 2015-11-16 | Longs: 13 | Shorts: 5 | 10,375,441.10 [ 19:47:29.040622]: INFO: after split: asset: Equity(406 [BOFI]), amount: 1616, cost_basis: 23.48, last_sale_price: 83.29 [ 19:47:29.041061]: INFO: returning cash: 0.0 [ 19:47:29.496124]: INFO: 2015-11-23 | Longs: 9 | Shorts: 7 | 10,449,719.61 [ 19:47:30.007682]: INFO: 2015-11-30 | Longs: 11 | Shorts: 6 | 10,496,308.50 [ 19:47:30.625996]: INFO: 2015-12-07 | Longs: 12 | Shorts: 8 | 10,513,409.39 [ 19:47:31.246652]: INFO: 2015-12-14 | Longs: 9 | Shorts: 14 | 10,400,063.33 [ 19:47:31.895426]: INFO: 2015-12-21 | Longs: 10 | Shorts: 12 | 10,336,091.55 [ 19:47:32.429951]: INFO: 2015-12-28 | Longs: 9 | Shorts: 8 | 10,373,369.95 [ 19:47:32.955684]: INFO: 2016-01-04 | Longs: 5 | Shorts: 11 | 10,377,997.16 [ 19:47:33.561514]: INFO: 2016-01-11 | Longs: 8 | Shorts: 7 | 10,413,318.21 [ 19:47:34.178342]: INFO: 2016-01-19 | Longs: 8 | Shorts: 6 | 10,454,666.31 [ 19:47:36.204941]: INFO: 2016-01-25 | Longs: 9 | Shorts: 9 | 10,477,454.93 [ 19:47:36.814962]: INFO: 2016-02-01 | Longs: 14 | Shorts: 14 | 10,420,206.34 [ 19:47:37.475246]: INFO: 2016-02-08 | Longs: 18 | Shorts: 16 | 10,182,460.84 [ 19:47:38.176049]: INFO: 2016-02-16 | Longs: 12 | Shorts: 10 | 10,452,919.06 [ 19:47:38.732747]: INFO: 2016-02-22 | Longs: 6 | Shorts: 7 | 10,585,928.85 [ 19:47:39.358521]: INFO: 2016-02-29 | Longs: 4 | Shorts: 9 | 10,622,313.10 [ 19:47:39.966348]: INFO: 2016-03-07 | Longs: 9 | Shorts: 8 | 10,558,809.60 [ 19:47:40.598327]: INFO: 2016-03-14 | Longs: 4 | Shorts: 4 | 10,554,090.86 [ 19:47:41.203249]: INFO: 2016-03-21 | Longs: 5 | Shorts: 10 | 10,327,145.78 [ 19:47:41.708528]: INFO: 2016-03-28 | Longs: 5 | Shorts: 4 | 10,457,227.91 [ 19:47:42.303564]: INFO: 2016-04-04 | Longs: 3 | Shorts: 2 | 10,406,360.98 [ 19:47:42.892175]: INFO: 2016-04-11 | Longs: 7 | Shorts: 9 | 10,409,222.16 [ 19:47:43.538288]: INFO: 2016-04-18 | Longs: 15 | Shorts: 6 | 10,400,049.03 [ 19:47:44.236621]: INFO: 2016-04-25 | Longs: 19 | Shorts: 2 | 10,404,515.45 [ 19:47:44.933809]: INFO: 2016-05-02 | Longs: 13 | Shorts: 9 | 10,431,469.55 [ 19:47:45.595158]: INFO: 2016-05-09 | Longs: 10 | Shorts: 2 | 10,524,765.67 [ 19:47:46.229593]: INFO: 2016-05-16 | Longs: 14 | Shorts: 6 | 10,468,602.90 [ 19:47:46.868840]: INFO: 2016-05-23 | Longs: 11 | Shorts: 7 | 10,485,867.14 [ 19:47:47.519156]: INFO: 2016-05-31 | Longs: 7 | Shorts: 7 | 10,535,395.41 [ 19:47:48.047921]: INFO: 2016-06-06 | Longs: 9 | Shorts: 9 | 10,549,440.76 [ 19:47:48.653117]: INFO: 2016-06-13 | Longs: 13 | Shorts: 6 | 10,605,810.71 [ 19:47:49.275752]: INFO: 2016-06-20 | Longs: 8 | Shorts: 6 | 10,589,211.73 [ 19:47:49.892499]: INFO: 2016-06-27 | Longs: 17 | Shorts: 4 | 10,483,875.66 [ 19:47:50.512126]: INFO: 2016-07-05 | Longs: 6 | Shorts: 12 | 10,575,846.46 [ 19:47:51.019847]: INFO: 2016-07-11 | Longs: 7 | Shorts: 11 | 10,662,656.13 [ 19:47:51.637688]: INFO: 2016-07-18 | Longs: 3 | Shorts: 5 | 10,683,919.69 [ 19:47:55.667261]: INFO: 2016-07-25 | Longs: 7 | Shorts: 13 | 10,707,303.42 [ 19:47:56.270324]: INFO: 2016-08-01 | Longs: 14 | Shorts: 8 | 10,718,980.24 [ 19:47:56.909125]: INFO: 2016-08-08 | Longs: 12 | Shorts: 7 | 10,660,895.86 [ 19:47:57.548971]: INFO: 2016-08-15 | Longs: 7 | Shorts: 8 | 10,665,800.53 [ 19:47:58.199619]: INFO: 2016-08-22 | Longs: 8 | Shorts: 6 | 10,650,245.31 [ 19:47:58.815117]: INFO: 2016-08-29 | Longs: 11 | Shorts: 3 | 10,649,100.18 [ 19:47:59.414821]: INFO: 2016-09-06 | Longs: 14 | Shorts: 5 | 10,654,268.58 [ 19:47:59.924402]: INFO: 2016-09-12 | Longs: 29 | Shorts: 3 | 10,636,322.37 [ 19:48:00.616401]: INFO: 2016-09-19 | Longs: 19 | Shorts: 5 | 10,675,288.81 [ 19:48:01.315263]: INFO: 2016-09-26 | Longs: 14 | Shorts: 5 | 10,680,478.84 [ 19:48:01.967420]: INFO: 2016-10-03 | Longs: 10 | Shorts: 5 | 10,723,923.98 [ 19:48:02.577480]: INFO: 2016-10-10 | Longs: 5 | Shorts: 5 | 10,708,120.44 [ 19:48:03.178193]: INFO: 2016-10-17 | Longs: 6 | Shorts: 6 | 10,748,231.24 [ 19:48:03.759245]: INFO: 2016-10-24 | Longs: 5 | Shorts: 11 | 10,743,221.29 [ 19:48:04.365393]: INFO: 2016-10-31 | Longs: 7 | Shorts: 15 | 10,761,910.49 [ 19:48:04.987985]: INFO: 2016-11-07 | Longs: 11 | Shorts: 11 | 10,739,304.47 [ 19:48:05.620129]: INFO: 2016-11-14 | Longs: 18 | Shorts: 4 | 10,691,323.41 [ 19:48:06.263074]: INFO: 2016-11-21 | Longs: 18 | Shorts: 1 | 10,734,499.53 [ 19:48:06.763776]: INFO: 2016-11-28 | Longs: 20 | Shorts: 0 | 10,724,702.90 [ 19:48:07.384120]: INFO: 2016-12-05 | Longs: 25 | Shorts: 3 | 10,679,618.01 [ 19:48:08.027829]: INFO: 2016-12-12 | Longs: 21 | Shorts: 1 | 10,835,582.73 [ 19:48:08.682182]: INFO: 2016-12-19 | Longs: 13 | Shorts: 2 | 10,871,411.67 [ 19:48:09.296106]: INFO: 2016-12-27 | Longs: 12 | Shorts: 1 | 10,815,943.67 [ 19:48:09.677636]: INFO: Simulated 1008 trading days first open: 2013-01-02 14:31:00+00:00 last close: 2016-12-30 21:00:00+00:00

Extract pyfolio Inputs

The extract_rets_pos_txn_from_zipline utility provided by pyfolio extracts the data used to compute performance metrics.

returns, positions, transactions = extract_rets_pos_txn_from_zipline(backtest)

Persist Results for use with pyfolio

with pd.HDFStore('backtests.h5') as store: store.put('backtest/equal_weight', backtest) store.put('returns/equal_weight', returns) store.put('positions/equal_weight', positions) store.put('transactions/equal_weight', transactions)

Plot Results

fig, axes= plt.subplots(nrows=2, figsize=(14,6)) returns.add(1).cumprod().sub(1).plot(ax=axes[0], title='Cumulative Returns') transactions.groupby(transactions.dt.dt.day).txn_dollars.sum().cumsum().plot(ax=axes[1], title='Cumulative Transactions') fig.tight_layout() sns.despine();
Image in a Jupyter notebook
positions.index = positions.index.date
fig, ax = plt.subplots(figsize=(15, 8)) sns.heatmap(positions.replace(0, np.nan).dropna(how='all', axis=1).T, cmap=sns.diverging_palette(h_neg=20, h_pos=200), ax=ax, center=0);
Image in a Jupyter notebook
positions.head()
transactions.info()
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 6505 entries, 2013-01-08 21:00:00+00:00 to 2016-12-30 21:00:00+00:00 Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 sid 6505 non-null object 1 symbol 6505 non-null object 2 price 6505 non-null float64 3 order_id 6502 non-null object 4 amount 6505 non-null int64 5 commission 0 non-null object 6 dt 6505 non-null datetime64[ns, UTC] 7 txn_dollars 6505 non-null float64 dtypes: datetime64[ns, UTC](1), float64(2), int64(1), object(4) memory usage: 457.4+ KB