TensorBoard as a Zipline dashboard

May 15, 2016


Zipline is a Pythonic algorithmic trading library for backtesting and trading quantitative strategies. TensorBoard is a visualization tool provided with the deep learning library TensorFlow. These two can be used together to create a dashboard that monitors and compares Zipline backtests. You don’t even need to know a thing about deep learning.

The code for this can be found here: https://github.com/jimgoo/zipline-tensorboard.git.

TensorBoard Setup

If you have a working installation of Zipline, then the only thing you need to do is install TensorFlow. This can be done easility with pip, which is fleshed out in great detail here. For Python 2 it boils down to one of the following:

# Ubuntu/Linux 64-bit, CPU only:
$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.8.0-cp27-none-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled. Requires CUDA toolkit 7.5 and CuDNN v4.  For
# other versions, see "Install from sources" below.
$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.8.0-cp27-none-linux_x86_64.whl

# Mac OS X, CPU only:
$ sudo easy_install --upgrade six
$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.8.0-py2-none-any.whl

If you’re not doing any deep learning and just want to use TensorBoard, go with the CPU only option. Once TensorFlow is installed, you can start TensorBoard from the shell with:

tensorboard --logdir=/tmp/

where the --logdir argument is the parent directory to where the data for all of your backtest runs will be saved. Go to http://localhost:6006 and you should see this:

_config.yml

Using TensorBoard with Zipline

To start logging some info, run the Zipline example olmar_tensorboard.py to generate some backtests to monitor:

python olmar_tensorboard.py

This runs three parameterizations of the OLMAR example backtest on the Dow 30 from 2004 to 2016. Each one has takes a while to run, but as they run you can see the basic live stats displayed in TensorBoard, including any variables recorded with algo.record. You may have to hit refresh on occasion, but there’s a setting in tensorboard.py to control how often data is written to the log files:

flush_secs: How often, in seconds, to flush the added summaries 
            and events to disk. [default 120]

Comparing backtests

Here’s a comparison of the returns of each backtest once all have finished:

_config.yml

The regex filters let you group different stats together, so to see stats with “number” in the name:

_config.yml

You can see right away the lower values of epsilon result in lots more trading. Pretty useful for getting some quick insight.

Recorded variables

Any variable recorded with zipline.algorithm.TradingAlgorithm.record is also logged to TensorBoard. We’ve done that here with the x_bar variable in OLMAR:

_config.yml

Logging process

To use the TensorBoard logging class with a Zipline algo, all you need to do is initialize an instance of the TensorBoard class in the algo.initialize method, and add the line algo.tensorboard.log_algo(algo) to the end of your algo.handle_data function.

One could go wild adding different metrics to be logged, this was just a quick stab at it using attributes from algo.portfolio and algo.blotter. It’s as simple as passing an extra other_logs dictionary argument:

 algo.tensorboard.log_algo(algo, 
     other_logs={'number_of_short_positions': 5})

For now these are logged by default:

# add portfolio related things
logs['portfolio value'] = algo.portfolio.portfolio_value
logs['portfolio pnl'] = algo.portfolio.pnl
logs['portfolio return'] = algo.portfolio.returns
logs['portfolio cash'] = algo.portfolio.cash
logs['portfolio capital used'] = algo.portfolio.capital_used
logs['portfolio positions exposure'] = algo.portfolio.positions_exposure
logs['portfolio positions value'] = algo.portfolio.positions_value
logs['number of orders'] = len(algo.blotter.orders)
logs['number of open orders'] = len(algo.blotter.open_orders)
logs['number of open positions'] = len(algo.portfolio.positions)

# add recorded variables from `zipline.algorithm.record` method
for name, value in algo.recorded_vars.items():
    logs[name] = value

x-axis

TensorBoard expects the x-axis to be an integer epoch number, so we use the algorithm date converted to an ordinal:

epoch = datetime.date.toordinal(algo.get_datetime())

This is why the x-axis looks weird, but it allows backtests run between different time periods to line up correctly on the charts.

You can see this working here:

_config.yml