From 627bca78c7d6f8eec3ffc76f0923fa82eec94c4d Mon Sep 17 00:00:00 2001
From: Victor Grau Serrat
Date: Tue, 28 Nov 2017 12:45:21 -0700
Subject: [PATCH] DOC: documented 4 example algorithms
---
_sources/beginner-tutorial.txt | 1 +
_sources/example-algos.txt | 973 ++++++++++++++++++++++-----------
appendix.html | 3 +
beginner-tutorial.html | 5 +-
example-algos.html | 390 +++++++++++--
genindex.html | 5 +-
index.html | 3 +
objects.inv | Bin 502 -> 600 bytes
releases.html | 3 +
search.html | 5 +-
searchindex.js | 2 +-
11 files changed, 999 insertions(+), 391 deletions(-)
diff --git a/_sources/beginner-tutorial.txt b/_sources/beginner-tutorial.txt
index 6743f82d..38603888 100644
--- a/_sources/beginner-tutorial.txt
+++ b/_sources/beginner-tutorial.txt
@@ -546,6 +546,7 @@ only bought bitcoin every chance it got.
sudo apt install python-tk
+.. _history:
Access to previous prices using ``history``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/_sources/example-algos.txt b/_sources/example-algos.txt
index e341f331..002dc46b 100644
--- a/_sources/example-algos.txt
+++ b/_sources/example-algos.txt
@@ -2,28 +2,102 @@
Example Algorithms
==================
-This section documents a small number of example algorithms to complement the
+This section documents a number of example algorithms to complement the
beginner tutorial, and show how other trading algorithms can be implemented
-using Catalyst:
+using Catalyst.
+
+Overview
+~~~~~~~~
+
+- :ref:`Buy BTC Simple`: The simplest algorithm that introduces
+ the ``initialize()`` and ``handle_data()`` functions, and is used in the
+ :doc:`beginner tutorial` to show how to run catalyst
+ for the first time.
+
+- :ref:`Buy and Hodl `: A very straightforward *buy and hold* that
+ makes one single buy at the very beginning. Introduces the notions of
+ ``cash``, management of outstanding ``orders``, and ``order_target_value``
+ to place orders. It also introduces the ``analyze()`` function to visualize
+ the performance of our strategy using the external library ``matplotlib``.
+
+- :ref:`Dual Moving Average Crossover`: A classic momentum
+ strategy used in the second part of the
+ `beginner tutorial `_ to introduce the
+ ``data.history()`` function. It makes a heavy use of ``matplotlib`` library
+ in the ``analyze()`` function to chart the performance of the algorithm.
+
+- :ref:`Mean Reversion Algorithm `: Another simple momentum
+ strategy that is used in our
+ `two-part video tutorial `_ to show how
+ to get started in backtesting and live trading with Catalyst.
+
+
+.. _buy_btc_simple:
+
+Buy BTC Simple Algorithm
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Source code: `examples/buy_btc_simple.py `_
+
+.. code-block:: python
+
+ '''
+ Run this example, by executing the following from your terminal:
+ catalyst ingest-exchange -x bitfinex -f daily -i btc_usdt
+ catalyst run -f buy_btc_simple.py -x bitfinex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle
+
+ If you want to run this code using another exchange, make sure that
+ the asset is available on that exchange. For example, if you were to run
+ it for exchange Poloniex, you would need to edit the following line:
+
+ context.asset = symbol('btc_usdt') # note 'usdt' instead of 'usd'
+
+ and specify exchange poloniex as follows:
+ catalyst ingest-exchange -x poloniex -f daily -i btc_usdt
+ catalyst run -f buy_btc_simple.py -x poloniex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle
+
+ To see which assets are available on each exchange, visit:
+ https://www.enigma.co/catalyst/status
+ '''
+
+ from catalyst.api import order, record, symbol
+
+ def initialize(context):
+ context.asset = symbol('btc_usd')
+
+ def handle_data(context, data):
+ order(context.asset, 1)
+ record(btc = data.current(context.asset, 'price'))
+
+This simple algorithm does not produce any output nor displays any chart.
+
.. _buy_and_hodl:
Buy and Hodl Algorithm
~~~~~~~~~~~~~~~~~~~~~~
-source: `examples/buy_and_hodl.py `_
+Source code: `examples/buy_and_hodl.py `_
First ingest the historical pricing data needed to run this algorithm:
.. code-block:: bash
- catalyst ingest-exchange -x poloniex -f daily -i btc_usdt
+ catalyst ingest-exchange -x bitfinex -f daily -i btc_usd
Then, you can run the code below with the following command:
.. code-block:: bash
- catalyst run -f buy_and_hodl.py --start 2015-3-1 --end 2017-10-31 --capital-base 100000 -x poloniex -c btc -o bah.pickle
+ catalyst run -f buy_and_hodl.py --start 2015-3-1 --end 2017-10-31 --capital-base 100000 -x bitfinex -c btc -o bah.pickle
+
+or using the same parameters specified in the run_algorithm() function at the
+end of the file:
+
+.. code-block:: bash
+
+ python buy_and_hodl.py
+
This command will run the trading algorithm in the specified time range and
plot the resulting performance using the matplotlib library. You can choose any
@@ -35,156 +109,340 @@ one day prior to the current date.
.. code-block:: python
- #!/usr/bin/env python
- #
- # Copyright 2017 Enigma MPC, Inc.
- # Copyright 2015 Quantopian, Inc.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import pandas as pd
+ #!/usr/bin/env python
+ #
+ # Copyright 2017 Enigma MPC, Inc.
+ # Copyright 2015 Quantopian, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+ import pandas as pd
+ import matplotlib.pyplot as plt
- from catalyst.api import (
- order_target_value,
- symbol,
- record,
- cancel_order,
- get_open_orders,
- )
+ from catalyst import run_algorithm
+ from catalyst.api import (order_target_value, symbol, record,
+ cancel_order, get_open_orders, )
- def initialize(context):
- context.ASSET_NAME = 'btc_usdt'
- context.TARGET_HODL_RATIO = 0.8
- context.RESERVE_RATIO = 1.0 - context.TARGET_HODL_RATIO
+ def initialize(context):
+ context.ASSET_NAME = 'btc_usd'
+ context.TARGET_HODL_RATIO = 0.8
+ context.RESERVE_RATIO = 1.0 - context.TARGET_HODL_RATIO
- context.is_buying = True
- context.asset = symbol(context.ASSET_NAME)
+ context.is_buying = True
+ context.asset = symbol(context.ASSET_NAME)
- context.i = 0
+ context.i = 0
- def handle_data(context, data):
- context.i += 1
+ def handle_data(context, data):
+ context.i += 1
- starting_cash = context.portfolio.starting_cash
- target_hodl_value = context.TARGET_HODL_RATIO * starting_cash
- reserve_value = context.RESERVE_RATIO * starting_cash
+ starting_cash = context.portfolio.starting_cash
+ target_hodl_value = context.TARGET_HODL_RATIO * starting_cash
+ reserve_value = context.RESERVE_RATIO * starting_cash
- # Cancel any outstanding orders
- orders = get_open_orders(context.asset) or []
- for order in orders:
- cancel_order(order)
+ # Cancel any outstanding orders
+ orders = get_open_orders(context.asset) or []
+ for order in orders:
+ cancel_order(order)
- # Stop buying after passing the reserve threshold
- cash = context.portfolio.cash
- if cash <= reserve_value:
- context.is_buying = False
+ # Stop buying after passing the reserve threshold
+ cash = context.portfolio.cash
+ if cash <= reserve_value:
+ context.is_buying = False
- # Retrieve current asset price from pricing data
- price = data.current(context.asset, 'price')
+ # Retrieve current asset price from pricing data
+ price = data.current(context.asset, 'price')
- # Check if still buying and could (approximately) afford another purchase
- if context.is_buying and cash > price:
- # Place order to make position in asset equal to target_hodl_value
- order_target_value(
- context.asset,
- target_hodl_value,
- limit_price=price * 1.1,
- stop_price=price * 0.9,
- )
+ # Check if still buying and could (approximately) afford another purchase
+ if context.is_buying and cash > price:
+ print('buying')
+ # Place order to make position in asset equal to target_hodl_value
+ order_target_value(
+ context.asset,
+ target_hodl_value,
+ limit_price=price * 1.1,
+ stop_price=price * 0.9,
+ )
- record(
- price=price,
- volume=data.current(context.asset, 'volume'),
- cash=cash,
- starting_cash=context.portfolio.starting_cash,
- leverage=context.account.leverage,
- )
+ record(
+ price=price,
+ volume=data.current(context.asset, 'volume'),
+ cash=cash,
+ starting_cash=context.portfolio.starting_cash,
+ leverage=context.account.leverage,
+ )
- def analyze(context=None, results=None):
- import matplotlib.pyplot as plt
+ def analyze(context=None, results=None):
- # Plot the portfolio and asset data.
- ax1 = plt.subplot(611)
- results[['portfolio_value']].plot(ax=ax1)
- ax1.set_ylabel('Portfolio Value (USD)')
+ # Plot the portfolio and asset data.
+ ax1 = plt.subplot(611)
+ results[['portfolio_value']].plot(ax=ax1)
+ ax1.set_ylabel('Portfolio Value (USD)')
- ax2 = plt.subplot(612, sharex=ax1)
- ax2.set_ylabel('{asset} (USD)'.format(asset=context.ASSET_NAME))
- results[['price']].plot(ax=ax2)
+ ax2 = plt.subplot(612, sharex=ax1)
+ ax2.set_ylabel('{asset} (USD)'.format(asset=context.ASSET_NAME))
+ results[['price']].plot(ax=ax2)
- trans = results.ix[[t != [] for t in results.transactions]]
- buys = trans.ix[
- [t[0]['amount'] > 0 for t in trans.transactions]
- ]
- ax2.plot(
- buys.index,
- results.price[buys.index],
- '^',
- markersize=10,
- color='g',
- )
+ trans = results.ix[[t != [] for t in results.transactions]]
+ buys = trans.ix[
+ [t[0]['amount'] > 0 for t in trans.transactions]
+ ]
+ ax2.scatter(
+ buys.index.to_pydatetime(),
+ results.price[buys.index],
+ marker='^',
+ s=100,
+ c='g',
+ label=''
+ )
- ax3 = plt.subplot(613, sharex=ax1)
- results[['leverage', 'alpha', 'beta']].plot(ax=ax3)
- ax3.set_ylabel('Leverage ')
+ ax3 = plt.subplot(613, sharex=ax1)
+ results[['leverage', 'alpha', 'beta']].plot(ax=ax3)
+ ax3.set_ylabel('Leverage ')
- ax4 = plt.subplot(614, sharex=ax1)
- results[['starting_cash', 'cash']].plot(ax=ax4)
- ax4.set_ylabel('Cash (USD)')
+ ax4 = plt.subplot(614, sharex=ax1)
+ results[['starting_cash', 'cash']].plot(ax=ax4)
+ ax4.set_ylabel('Cash (USD)')
- results[[
- 'treasury',
- 'algorithm',
- 'benchmark',
- ]] = results[[
- 'treasury_period_return',
- 'algorithm_period_return',
- 'benchmark_period_return',
- ]]
+ results[[
+ 'treasury',
+ 'algorithm',
+ 'benchmark',
+ ]] = results[[
+ 'treasury_period_return',
+ 'algorithm_period_return',
+ 'benchmark_period_return',
+ ]]
- ax5 = plt.subplot(615, sharex=ax1)
- results[[
- 'treasury',
- 'algorithm',
- 'benchmark',
- ]].plot(ax=ax5)
- ax5.set_ylabel('Percent Change')
+ ax5 = plt.subplot(615, sharex=ax1)
+ results[[
+ 'treasury',
+ 'algorithm',
+ 'benchmark',
+ ]].plot(ax=ax5)
+ ax5.set_ylabel('Percent Change')
- ax6 = plt.subplot(616, sharex=ax1)
- results[['volume']].plot(ax=ax6)
- ax6.set_ylabel('Volume (mCoins/5min)')
+ ax6 = plt.subplot(616, sharex=ax1)
+ results[['volume']].plot(ax=ax6)
+ ax6.set_ylabel('Volume (mCoins/5min)')
- plt.legend(loc=3)
+ plt.legend(loc=3)
+
+ # Show the plot.
+ plt.gcf().set_size_inches(18, 8)
+ plt.show()
+
+
+ if __name__ == '__main__':
+ run_algorithm(
+ capital_base=10000,
+ data_frequency='daily',
+ initialize=initialize,
+ handle_data=handle_data,
+ analyze=analyze,
+ exchange_name='bitfinex',
+ algo_namespace='buy_and_hodl',
+ base_currency='usd',
+ start=pd.to_datetime('2015-03-01', utc=True),
+ end=pd.to_datetime('2017-10-31', utc=True),
+ )
+
+.. image:: https://s3.amazonaws.com/enigmaco-docs/github.io/example_buy_and_hodl.png
+
+.. _dual_moving_average:
+
+Dual Moving Average Crossover
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Source Code: `examples/dual_moving_average.py `_
+
+This strategy is covered in detail in the last part of
+`this tutorial `_.
+
+.. code-block:: python
+
+ import numpy as np
+ import pandas as pd
+ from logbook import Logger
+ import matplotlib.pyplot as plt
+
+ from catalyst import run_algorithm
+ from catalyst.api import (order, record, symbol, order_target_percent,
+ get_open_orders)
+ from catalyst.exchange.stats_utils import extract_transactions
+
+ NAMESPACE = 'dual_moving_average'
+ log = Logger(NAMESPACE)
+
+ def initialize(context):
+ context.i = 0
+ context.asset = symbol('ltc_usd')
+ context.base_price = None
+
+
+ def handle_data(context, data):
+ # define the windows for the moving averages
+ short_window = 50
+ long_window = 200
+
+ # Skip as many bars as long_window to properly compute the average
+ context.i += 1
+ if context.i < long_window:
+ return
+
+ # Compute moving averages calling data.history() for each
+ # moving average with the appropriate parameters. We choose to use
+ # minute bars for this simulation -> freq="1m"
+ # Returns a pandas dataframe.
+ short_mavg = data.history(context.asset, 'price',
+ bar_count=short_window, frequency="1m").mean()
+ long_mavg = data.history(context.asset, 'price',
+ bar_count=long_window, frequency="1m").mean()
+
+ # Let's keep the price of our asset in a more handy variable
+ price = data.current(context.asset, 'price')
+
+ # If base_price is not set, we use the current value. This is the
+ # price at the first bar which we reference to calculate price_change.
+ if context.base_price is None:
+ context.base_price = price
+ price_change = (price - context.base_price) / context.base_price
+
+ # Save values for later inspection
+ record(price=price,
+ cash=context.portfolio.cash,
+ price_change=price_change,
+ short_mavg=short_mavg,
+ long_mavg=long_mavg)
+
+ # Since we are using limit orders, some orders may not execute immediately
+ # we wait until all orders are executed before considering more trades.
+ orders = get_open_orders(context.asset)
+ if len(orders) > 0:
+ return
+
+ # Exit if we cannot trade
+ if not data.can_trade(context.asset):
+ return
+
+ # We check what's our position on our portfolio and trade accordingly
+ pos_amount = context.portfolio.positions[context.asset].amount
+
+ # Trading logic
+ if short_mavg > long_mavg and pos_amount == 0:
+ # we buy 100% of our portfolio for this asset
+ order_target_percent(context.asset, 1)
+ elif short_mavg < long_mavg and pos_amount > 0:
+ # we sell all our positions for this asset
+ order_target_percent(context.asset, 0)
+
+
+ def analyze(context, perf):
+
+ # Get the base_currency that was passed as a parameter to the simulation
+ base_currency = context.exchanges.values()[0].base_currency.upper()
+
+ # First chart: Plot portfolio value using base_currency
+ ax1 = plt.subplot(411)
+ perf.loc[:, ['portfolio_value']].plot(ax=ax1)
+ ax1.legend_.remove()
+ ax1.set_ylabel('Portfolio Value\n({})'.format(base_currency))
+ start, end = ax1.get_ylim()
+ ax1.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
+
+ # Second chart: Plot asset price, moving averages and buys/sells
+ ax2 = plt.subplot(412, sharex=ax1)
+ perf.loc[:, ['price','short_mavg','long_mavg']].plot(ax=ax2, label='Price')
+ ax2.legend_.remove()
+ ax2.set_ylabel('{asset}\n({base})'.format(
+ asset = context.asset.symbol,
+ base = base_currency
+ ))
+ start, end = ax2.get_ylim()
+ ax2.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
+
+ transaction_df = extract_transactions(perf)
+ if not transaction_df.empty:
+ buy_df = transaction_df[transaction_df['amount'] > 0]
+ sell_df = transaction_df[transaction_df['amount'] < 0]
+ ax2.scatter(
+ buy_df.index.to_pydatetime(),
+ perf.loc[buy_df.index, 'price'],
+ marker='^',
+ s=100,
+ c='green',
+ label=''
+ )
+ ax2.scatter(
+ sell_df.index.to_pydatetime(),
+ perf.loc[sell_df.index, 'price'],
+ marker='v',
+ s=100,
+ c='red',
+ label=''
+ )
+
+ # Third chart: Compare percentage change between our portfolio
+ # and the price of the asset
+ ax3 = plt.subplot(413, sharex=ax1)
+ perf.loc[:, ['algorithm_period_return', 'price_change']].plot(ax=ax3)
+ ax3.legend_.remove()
+ ax3.set_ylabel('Percent Change')
+ start, end = ax3.get_ylim()
+ ax3.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
+
+ # Fourth chart: Plot our cash
+ ax4 = plt.subplot(414, sharex=ax1)
+ perf.cash.plot(ax=ax4)
+ ax4.set_ylabel('Cash\n({})'.format(base_currency))
+ start, end = ax4.get_ylim()
+ ax4.yaxis.set_ticks(np.arange(0, end, end/5))
+
+ plt.show()
+
+
+ if __name__ == '__main__':
+ run_algorithm(
+ capital_base=1000,
+ data_frequency='minute',
+ initialize=initialize,
+ handle_data=handle_data,
+ analyze=analyze,
+ exchange_name='bitfinex',
+ algo_namespace=NAMESPACE,
+ base_currency='usd',
+ start=pd.to_datetime('2017-9-22', utc=True),
+ end=pd.to_datetime('2017-9-23', utc=True),
+ )
+
+.. image:: https://s3.amazonaws.com/enigmaco-docs/github.io/tutorial_dual_moving_average.png
- # Show the plot.
- plt.gcf().set_size_inches(18, 8)
- plt.show()
.. _mean_reversion:
Mean Reversion Algorithm
~~~~~~~~~~~~~~~~~~~~~~~~
-source: `examples/mean_reversion_simple.py `_
+Source code: `examples/mean_reversion_simple.py `_
This algorithm is based on a simple momentum strategy. When the cryptoasset goes
up quickly, we're going to buy; when it goes down quickly, we're going to sell.
Hopefully, we'll ride the waves.
-We are choosing to run this trading algorithm with the ``neo_usd`` currency pair
-on the ``Bitfinex`` exchange. Thus, first ingest the historical pricing data
+We are choosing to backtest this trading algorithm with the ``neo_usd`` currency
+pairon the ``Bitfinex`` exchange. Thus, first ingest the historical pricing data
that we need, with minute resolution:
.. code-block:: bash
@@ -201,244 +459,291 @@ lines 218-245, so in order to run the algorithm we just type:
.. code-block:: python
- import pandas as pd
- import talib
- from logbook import Logger
+ import os
+ import tempfile
+ import time
- from catalyst import run_algorithm
- from catalyst.api import symbol, record, order_target_percent, get_open_orders
- from catalyst.exchange.stats_utils import extract_transactions
+ import numpy as np
+ import pandas as pd
+ import talib
+ from logbook import Logger
- # We give a name to the algorithm which Catalyst will use to persist its state.
- # In this example, Catalyst will create the `.catalyst/data/live_algos`
- # directory. If we stop and start the algorithm, Catalyst will resume its
- # state using the files included in the folder.
- NAMESPACE = 'mean_reversion_simple'
- log = Logger(NAMESPACE)
+ from catalyst import run_algorithm
+ from catalyst.api import symbol, record, order_target_percent, get_open_orders
+ from catalyst.exchange.stats_utils import extract_transactions
+ # We give a name to the algorithm which Catalyst will use to persist its state.
+ # In this example, Catalyst will create the `.catalyst/data/live_algos`
+ # directory. If we stop and start the algorithm, Catalyst will resume its
+ # state using the files included in the folder.
+ from catalyst.utils.paths import ensure_directory
- # To run an algorithm in Catalyst, you need two functions: initialize and
- # handle_data.
-
- def initialize(context):
- # This initialize function sets any data or variables that you'll use in
- # your algorithm. For instance, you'll want to define the trading pair (or
- # trading pairs) you want to backtest. You'll also want to define any
- # parameters or values you're going to use.
-
- # In our example, we're looking at Ether in USD Tether.
- context.neo_usd = symbol('neo_usd')
- context.base_price = None
- context.current_day = None
+ NAMESPACE = 'mean_reversion_simple'
+ log = Logger(NAMESPACE)
- def handle_data(context, data):
- # This handle_data function is where the real work is done. Our data is
- # minute-level tick data, and each minute is called a frame. This function
- # runs on each frame of the data.
+ # To run an algorithm in Catalyst, you need two functions: initialize and
+ # handle_data.
- # We flag the first period of each day.
- # Since cryptocurrencies trade 24/7 the `before_trading_starts` handle
- # would only execute once. This method works with minute and daily
- # frequencies.
- today = data.current_dt.floor('1D')
- if today != context.current_day:
- context.traded_today = False
- context.current_day = today
+ def initialize(context):
+ # This initialize function sets any data or variables that you'll use in
+ # your algorithm. For instance, you'll want to define the trading pair (or
+ # trading pairs) you want to backtest. You'll also want to define any
+ # parameters or values you're going to use.
- # We're computing the volume-weighted-average-price of the security
- # defined above, in the context.neo_usd variable. For this example, we're
- # using three bars on the 15 min bars.
+ # In our example, we're looking at Neo in USD.
+ context.neo_eth = symbol('neo_usd')
+ context.base_price = None
+ context.current_day = None
- # The frequency attribute determine the bar size. We use this convention
- # for the frequency alias:
- # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
- prices = data.history(
- context.neo_usd,
- fields='close',
- bar_count=50,
- frequency='15T'
- )
+ context.RSI_OVERSOLD = 30
+ context.RSI_OVERBOUGHT = 80
+ context.CANDLE_SIZE = '15T'
- # Ta-lib calculates various technical indicator based on price and
- # volume arrays.
-
- # In this example, we are comp
- rsi = talib.RSI(prices.values, timeperiod=14)
-
- # We need a variable for the current price of the security to compare to
- # the average. Since we are requesting two fields, data.current()
- # returns a DataFrame with
- current = data.current(context.neo_usd, fields=['close', 'volume'])
- price = current['close']
-
- # If base_price is not set, we use the current value. This is the
- # price at the first bar which we reference to calculate price_change.
- if context.base_price is None:
- context.base_price = price
-
- price_change = (price - context.base_price) / context.base_price
- cash = context.portfolio.cash
-
- # Now that we've collected all current data for this frame, we use
- # the record() method to save it. This data will be available as
- # a parameter of the analyze() function for further analysis.
- record(
- price=price,
- volume=current['volume'],
- price_change=price_change,
- rsi=rsi[-1],
- cash=cash
- )
-
- # We are trying to avoid over-trading by limiting our trades to
- # one per day.
- if context.traded_today:
- return
-
- # Since we are using limit orders, some orders may not execute immediately
- # we wait until all orders are executed before considering more trades.
- orders = get_open_orders(context.neo_usd)
- if len(orders) > 0:
- return
-
- # Exit if we cannot trade
- if not data.can_trade(context.neo_usd):
- return
-
- # Another powerful built-in feature of the Catalyst backtester is the
- # portfolio object. The portfolio object tracks your positions, cash,
- # cost basis of specific holdings, and more. In this line, we calculate
- # how long or short our position is at this minute.
- pos_amount = context.portfolio.positions[context.neo_usd].amount
-
- if rsi[-1] <= 30 and pos_amount == 0:
- log.info(
- '{}: buying - price: {}, rsi: {}'.format(
- data.current_dt, price, rsi[-1]
- )
- )
- order_target_percent(context.neo_usd, 1)
- context.traded_today = True
-
- elif rsi[-1] >= 80 and pos_amount > 0:
- log.info(
- '{}: selling - price: {}, rsi: {}'.format(
- data.current_dt, price, rsi[-1]
- )
- )
- order_target_percent(context.neo_usd, 0)
- context.traded_today = True
+ context.start_time = time.time()
- def analyze(context=None, perf=None):
- import matplotlib.pyplot as plt
+ def handle_data(context, data):
+ # This handle_data function is where the real work is done. Our data is
+ # minute-level tick data, and each minute is called a frame. This function
+ # runs on each frame of the data.
- # The base currency of the algo exchange
- base_currency = context.exchanges.values()[0].base_currency.upper()
+ # We flag the first period of each day.
+ # Since cryptocurrencies trade 24/7 the `before_trading_starts` handle
+ # would only execute once. This method works with minute and daily
+ # frequencies.
+ today = data.current_dt.floor('1D')
+ if today != context.current_day:
+ context.traded_today = False
+ context.current_day = today
- # Plot the portfolio value over time.
- ax1 = plt.subplot(611)
- perf.loc[:, 'portfolio_value'].plot(ax=ax1)
- ax1.set_ylabel('Portfolio Value ({})'.format(base_currency))
+ # We're computing the volume-weighted-average-price of the security
+ # defined above, in the context.neo_eth variable. For this example, we're
+ # using three bars on the 15 min bars.
- # Plot the price increase or decrease over time.
- ax2 = plt.subplot(612, sharex=ax1)
- perf.loc[:, 'price'].plot(ax=ax2, label='Price')
+ # The frequency attribute determine the bar size. We use this convention
+ # for the frequency alias:
+ # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
+ prices = data.history(
+ context.neo_eth,
+ fields='close',
+ bar_count=50,
+ frequency=context.CANDLE_SIZE
+ )
- ax2.set_ylabel('{asset} ({base})'.format(
- asset=context.neo_usd.symbol, base=base_currency
- ))
+ # Ta-lib calculates various technical indicator based on price and
+ # volume arrays.
- transaction_df = extract_transactions(perf)
- if not transaction_df.empty:
- buy_df = transaction_df[transaction_df['amount'] > 0]
- sell_df = transaction_df[transaction_df['amount'] < 0]
- ax2.scatter(
- buy_df.index.to_pydatetime(),
- perf.loc[buy_df.index, 'price'],
- marker='^',
- s=100,
- c='green',
- label=''
- )
- ax2.scatter(
- sell_df.index.to_pydatetime(),
- perf.loc[sell_df.index, 'price'],
- marker='v',
- s=100,
- c='red',
- label=''
- )
+ # In this example, we are comp
+ rsi = talib.RSI(prices.values, timeperiod=14)
- ax4 = plt.subplot(613, sharex=ax1)
- perf.loc[:, 'cash'].plot(
- ax=ax4, label='Base Currency ({})'.format(base_currency)
- )
- ax4.set_ylabel('Cash ({})'.format(base_currency))
+ # We need a variable for the current price of the security to compare to
+ # the average. Since we are requesting two fields, data.current()
+ # returns a DataFrame with
+ current = data.current(context.neo_eth, fields=['close', 'volume'])
+ price = current['close']
- perf['algorithm'] = perf.loc[:, 'algorithm_period_return']
+ # If base_price is not set, we use the current value. This is the
+ # price at the first bar which we reference to calculate price_change.
+ if context.base_price is None:
+ context.base_price = price
- ax5 = plt.subplot(614, sharex=ax1)
- perf.loc[:, ['algorithm', 'price_change']].plot(ax=ax5)
- ax5.set_ylabel('Percent Change')
+ price_change = (price - context.base_price) / context.base_price
+ cash = context.portfolio.cash
- ax6 = plt.subplot(615, sharex=ax1)
- perf.loc[:, 'rsi'].plot(ax=ax6, label='RSI')
- ax6.axhline(70, color='darkgoldenrod')
- ax6.axhline(30, color='darkgoldenrod')
+ # Now that we've collected all current data for this frame, we use
+ # the record() method to save it. This data will be available as
+ # a parameter of the analyze() function for further analysis.
+ record(
+ price=price,
+ volume=current['volume'],
+ price_change=price_change,
+ rsi=rsi[-1],
+ cash=cash
+ )
- if not transaction_df.empty:
- ax6.scatter(
- buy_df.index.to_pydatetime(),
- perf.loc[buy_df.index, 'rsi'],
- marker='^',
- s=100,
- c='green',
- label=''
- )
- ax6.scatter(
- sell_df.index.to_pydatetime(),
- perf.loc[sell_df.index, 'rsi'],
- marker='v',
- s=100,
- c='red',
- label=''
- )
- plt.legend(loc=3)
+ # We are trying to avoid over-trading by limiting our trades to
+ # one per day.
+ if context.traded_today:
+ return
- # Show the plot.
- plt.gcf().set_size_inches(18, 8)
- plt.show()
- pass
+ # Since we are using limit orders, some orders may not execute immediately
+ # we wait until all orders are executed before considering more trades.
+ orders = get_open_orders(context.neo_eth)
+ if len(orders) > 0:
+ return
+
+ # Exit if we cannot trade
+ if not data.can_trade(context.neo_eth):
+ return
+
+ # Another powerful built-in feature of the Catalyst backtester is the
+ # portfolio object. The portfolio object tracks your positions, cash,
+ # cost basis of specific holdings, and more. In this line, we calculate
+ # how long or short our position is at this minute.
+ pos_amount = context.portfolio.positions[context.neo_eth].amount
+
+ if rsi[-1] <= context.RSI_OVERSOLD and pos_amount == 0:
+ log.info(
+ '{}: buying - price: {}, rsi: {}'.format(
+ data.current_dt, price, rsi[-1]
+ )
+ )
+ # Set a style for limit orders,
+ limit_price = price * 1.005
+ order_target_percent(
+ context.neo_eth, 1, limit_price=limit_price
+ )
+ context.traded_today = True
+
+ elif rsi[-1] >= context.RSI_OVERBOUGHT and pos_amount > 0:
+ log.info(
+ '{}: selling - price: {}, rsi: {}'.format(
+ data.current_dt, price, rsi[-1]
+ )
+ )
+ limit_price = price * 0.995
+ order_target_percent(
+ context.neo_eth, 0, limit_price=limit_price
+ )
+ context.traded_today = True
- if __name__ == '__main__':
- # The execution mode: backtest or live
- MODE = 'backtest'
+ def analyze(context=None, perf=None):
+ end = time.time()
+ log.info('elapsed time: {}'.format(end - context.start_time))
+
+ import matplotlib.pyplot as plt
+ # The base currency of the algo exchange
+ base_currency = context.exchanges.values()[0].base_currency.upper()
+
+ # Plot the portfolio value over time.
+ ax1 = plt.subplot(611)
+ perf.loc[:, 'portfolio_value'].plot(ax=ax1)
+ ax1.set_ylabel('Portfolio\nValue\n({})'.format(base_currency))
+
+ # Plot the price increase or decrease over time.
+ ax2 = plt.subplot(612, sharex=ax1)
+ perf.loc[:, 'price'].plot(ax=ax2, label='Price')
+
+ ax2.set_ylabel('{asset}\n({base})'.format(
+ asset=context.neo_eth.symbol, base=base_currency
+ ))
+
+ transaction_df = extract_transactions(perf)
+ if not transaction_df.empty:
+ buy_df = transaction_df[transaction_df['amount'] > 0]
+ sell_df = transaction_df[transaction_df['amount'] < 0]
+ ax2.scatter(
+ buy_df.index.to_pydatetime(),
+ perf.loc[buy_df.index.floor('1 min'), 'price'],
+ marker='^',
+ s=100,
+ c='green',
+ label=''
+ )
+ ax2.scatter(
+ sell_df.index.to_pydatetime(),
+ perf.loc[sell_df.index.floor('1 min'), 'price'],
+ marker='v',
+ s=100,
+ c='red',
+ label=''
+ )
+
+ ax4 = plt.subplot(613, sharex=ax1)
+ perf.loc[:, 'cash'].plot(
+ ax=ax4, label='Base Currency ({})'.format(base_currency)
+ )
+ ax4.set_ylabel('Cash\n({})'.format(base_currency))
+
+ perf['algorithm'] = perf.loc[:, 'algorithm_period_return']
+
+ ax5 = plt.subplot(614, sharex=ax1)
+ perf.loc[:, ['algorithm', 'price_change']].plot(ax=ax5)
+ ax5.set_ylabel('Percent\nChange')
+
+ ax6 = plt.subplot(615, sharex=ax1)
+ perf.loc[:, 'rsi'].plot(ax=ax6, label='RSI')
+ ax6.set_ylabel('RSI')
+ ax6.axhline(context.RSI_OVERBOUGHT, color='darkgoldenrod')
+ ax6.axhline(context.RSI_OVERSOLD, color='darkgoldenrod')
+
+ if not transaction_df.empty:
+ ax6.scatter(
+ buy_df.index.to_pydatetime(),
+ perf.loc[buy_df.index.floor('1 min'), 'rsi'],
+ marker='^',
+ s=100,
+ c='green',
+ label=''
+ )
+ ax6.scatter(
+ sell_df.index.to_pydatetime(),
+ perf.loc[sell_df.index.floor('1 min'), 'rsi'],
+ marker='v',
+ s=100,
+ c='red',
+ label=''
+ )
+ plt.legend(loc=3)
+ start, end = ax6.get_ylim()
+ ax6.yaxis.set_ticks(np.arange(0, end, end/5))
+
+ # Show the plot.
+ plt.gcf().set_size_inches(18, 8)
+ plt.show()
+ pass
+
+
+ if __name__ == '__main__':
+ # The execution mode: backtest or live
+ MODE = 'backtest'
+
+ if MODE == 'backtest':
+ folder = os.path.join(
+ tempfile.gettempdir(), 'catalyst', NAMESPACE
+ )
+ ensure_directory(folder)
+
+ timestr = time.strftime('%Y%m%d-%H%M%S')
+ out = os.path.join(folder, '{}.p'.format(timestr))
+ # catalyst run -f catalyst/examples/mean_reversion_simple.py -x bitfinex -s 2017-10-1 -e 2017-11-10 -c usdt -n mean-reversion --data-frequency minute --capital-base 10000
+ run_algorithm(
+ capital_base=10000,
+ data_frequency='minute',
+ initialize=initialize,
+ handle_data=handle_data,
+ analyze=analyze,
+ exchange_name='bitfinex',
+ algo_namespace=NAMESPACE,
+ base_currency='usd',
+ start=pd.to_datetime('2017-10-01', utc=True),
+ end=pd.to_datetime('2017-11-10', utc=True),
+ output=out
+ )
+ log.info('saved perf stats: {}'.format(out))
+
+ elif MODE == 'live':
+ run_algorithm(
+ capital_base=0.5,
+ initialize=initialize,
+ handle_data=handle_data,
+ analyze=analyze,
+ exchange_name='bittrex',
+ live=True,
+ algo_namespace=NAMESPACE,
+ base_currency='usd',
+ live_graph=False
+ )
+
+.. image:: https://s3.amazonaws.com/enigmaco-docs/github.io/example_mean_reversion_simple.png
+
+Notice the difference in performance between the charts above and those seen on
+`this video tutorial `_ at
+minute 8:10. The buy and sell orders are triggered at the same exact times, but
+the differences result from a more realistic slippage model
+implemented after the video was recorded, which executes the orders at slighlty
+different prices, but resulting in significant changes in performance of our
+strategy.
- if MODE == 'backtest':
- # catalyst run -f catalyst/examples/mean_reversion_simple.py -x poloniex -s 2017-10-1 -e 2017-11-10 -c usdt -n mean-reversion --data-frequency minute --capital-base 10000
- run_algorithm(
- capital_base=10000,
- data_frequency='minute',
- initialize=initialize,
- handle_data=handle_data,
- analyze=analyze,
- exchange_name='bitfinex',
- algo_namespace=NAMESPACE,
- base_currency='usd',
- start=pd.to_datetime('2017-10-1', utc=True),
- end=pd.to_datetime('2017-11-10', utc=True),
- )
- elif MODE == 'live':
- run_algorithm(
- initialize=initialize,
- handle_data=handle_data,
- analyze=analyze,
- exchange_name='bitfinex',
- live=True,
- algo_namespace=NAMESPACE,
- base_currency='usd',
- live_graph=True
- )
diff --git a/appendix.html b/appendix.html
index b3b8b437..6455bbe7 100644
--- a/appendix.html
+++ b/appendix.html
@@ -120,7 +120,10 @@
Naming Convention
Example Algorithms
diff --git a/beginner-tutorial.html b/beginner-tutorial.html
index fef54173..89783713 100644
--- a/beginner-tutorial.html
+++ b/beginner-tutorial.html
@@ -122,7 +122,10 @@
Naming Convention
Example Algorithms
@@ -725,7 +728,7 @@ in a Linux environment:
-
Access to previous prices using history
+
Access to previous prices using history
Working example: Dual Moving Average Cross-Over
The Dual Moving Average (DMA) is a classic momentum strategy. It’s
diff --git a/example-algos.html b/example-algos.html
index 50b00e09..395a5779 100644
--- a/example-algos.html
+++ b/example-algos.html
@@ -122,7 +122,10 @@
Naming Convention
Example Algorithms
@@ -250,18 +253,80 @@
Example Algorithms
-
This section documents a small number of example algorithms to complement the
+
This section documents a number of example algorithms to complement the
beginner tutorial, and show how other trading algorithms can be implemented
-using Catalyst:
+using Catalyst.
+
+
Overview
+
+- Buy BTC Simple: The simplest algorithm that introduces
+the
initialize() and handle_data() functions, and is used in the
+beginner tutorial to show how to run catalyst
+for the first time.
+- Buy and Hodl: A very straightforward buy and hold that
+makes one single buy at the very beginning. Introduces the notions of
+
cash, management of outstanding orders, and order_target_value
+to place orders. It also introduces the analyze() function to visualize
+the performance of our strategy using the external library matplotlib.
+- Dual Moving Average Crossover: A classic momentum
+strategy used in the second part of the
+beginner tutorial to introduce the
+
data.history() function. It makes a heavy use of matplotlib library
+in the analyze() function to chart the performance of the algorithm.
+- Mean Reversion Algorithm: Another simple momentum
+strategy that is used in our
+two-part video tutorial to show how
+to get started in backtesting and live trading with Catalyst.
+
+
+
+
Buy BTC Simple Algorithm
+
Source code: examples/buy_btc_simple.py
+
'''
+ Run this example, by executing the following from your terminal:
+ catalyst ingest-exchange -x bitfinex -f daily -i btc_usdt
+ catalyst run -f buy_btc_simple.py -x bitfinex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle
+
+ If you want to run this code using another exchange, make sure that
+ the asset is available on that exchange. For example, if you were to run
+ it for exchange Poloniex, you would need to edit the following line:
+
+ context.asset = symbol('btc_usdt') # note 'usdt' instead of 'usd'
+
+ and specify exchange poloniex as follows:
+ catalyst ingest-exchange -x poloniex -f daily -i btc_usdt
+ catalyst run -f buy_btc_simple.py -x poloniex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle
+
+ To see which assets are available on each exchange, visit:
+ https://www.enigma.co/catalyst/status
+'''
+
+from catalyst.api import order, record, symbol
+
+def initialize(context):
+ context.asset = symbol('btc_usd')
+
+def handle_data(context, data):
+ order(context.asset, 1)
+ record(btc = data.current(context.asset, 'price'))
+
+
+
This simple algorithm does not produce any output nor displays any chart.
+
Buy and Hodl Algorithm
-
source: examples/buy_and_hodl.py
+
Source code: examples/buy_and_hodl.py
First ingest the historical pricing data needed to run this algorithm:
-
catalyst ingest-exchange -x poloniex -f daily -i btc_usdt
+catalyst ingest-exchange -x bitfinex -f daily -i btc_usd
Then, you can run the code below with the following command:
-catalyst run -f buy_and_hodl.py --start 2015-3-1 --end 2017-10-31 --capital-base 100000 -x poloniex -c btc -o bah.pickle
+catalyst run -f buy_and_hodl.py --start 2015-3-1 --end 2017-10-31 --capital-base 100000 -x bitfinex -c btc -o bah.pickle
+
+
+or using the same parameters specified in the run_algorithm() function at the
+end of the file:
+
This command will run the trading algorithm in the specified time range and
@@ -287,18 +352,15 @@ one day prior to the current date.
# See the License for the specific language governing permissions and
# limitations under the License.
import pandas as pd
+import matplotlib.pyplot as plt
-from catalyst.api import (
- order_target_value,
- symbol,
- record,
- cancel_order,
- get_open_orders,
-)
+from catalyst import run_algorithm
+from catalyst.api import (order_target_value, symbol, record,
+ cancel_order, get_open_orders, )
def initialize(context):
- context.ASSET_NAME = 'btc_usdt'
+ context.ASSET_NAME = 'btc_usd'
context.TARGET_HODL_RATIO = 0.8
context.RESERVE_RATIO = 1.0 - context.TARGET_HODL_RATIO
@@ -330,6 +392,7 @@ one day prior to the current date.
# Check if still buying and could (approximately) afford another purchase
if context.is_buying and cash > price:
+ print('buying')
# Place order to make position in asset equal to target_hodl_value
order_target_value(
context.asset,
@@ -348,7 +411,6 @@ one day prior to the current date.
def analyze(context=None, results=None):
- import matplotlib.pyplot as plt
# Plot the portfolio and asset data.
ax1 = plt.subplot(611)
@@ -363,12 +425,13 @@ one day prior to the current date.
buys = trans.ix[
[t[0]['amount'] > 0 for t in trans.transactions]
]
- ax2.plot(
- buys.index,
+ ax2.scatter(
+ buys.index.to_pydatetime(),
results.price[buys.index],
- '^',
- markersize=10,
- color='g',
+ marker='^',
+ s=100,
+ c='g',
+ label=''
)
ax3 = plt.subplot(613, sharex=ax1)
@@ -406,17 +469,195 @@ one day prior to the current date.
# Show the plot.
plt.gcf().set_size_inches(18, 8)
plt.show()
+
+
+if __name__ == '__main__':
+ run_algorithm(
+ capital_base=10000,
+ data_frequency='daily',
+ initialize=initialize,
+ handle_data=handle_data,
+ analyze=analyze,
+ exchange_name='bitfinex',
+ algo_namespace='buy_and_hodl',
+ base_currency='usd',
+ start=pd.to_datetime('2015-03-01', utc=True),
+ end=pd.to_datetime('2017-10-31', utc=True),
+ )
+
+
+
+
Dual Moving Average Crossover
+
Source Code: examples/dual_moving_average.py
+
This strategy is covered in detail in the last part of
+this tutorial.
+
import numpy as np
+import pandas as pd
+from logbook import Logger
+import matplotlib.pyplot as plt
+
+from catalyst import run_algorithm
+from catalyst.api import (order, record, symbol, order_target_percent,
+ get_open_orders)
+from catalyst.exchange.stats_utils import extract_transactions
+
+NAMESPACE = 'dual_moving_average'
+log = Logger(NAMESPACE)
+
+def initialize(context):
+ context.i = 0
+ context.asset = symbol('ltc_usd')
+ context.base_price = None
+
+
+def handle_data(context, data):
+ # define the windows for the moving averages
+ short_window = 50
+ long_window = 200
+
+ # Skip as many bars as long_window to properly compute the average
+ context.i += 1
+ if context.i < long_window:
+ return
+
+ # Compute moving averages calling data.history() for each
+ # moving average with the appropriate parameters. We choose to use
+ # minute bars for this simulation -> freq="1m"
+ # Returns a pandas dataframe.
+ short_mavg = data.history(context.asset, 'price',
+ bar_count=short_window, frequency="1m").mean()
+ long_mavg = data.history(context.asset, 'price',
+ bar_count=long_window, frequency="1m").mean()
+
+ # Let's keep the price of our asset in a more handy variable
+ price = data.current(context.asset, 'price')
+
+ # If base_price is not set, we use the current value. This is the
+ # price at the first bar which we reference to calculate price_change.
+ if context.base_price is None:
+ context.base_price = price
+ price_change = (price - context.base_price) / context.base_price
+
+ # Save values for later inspection
+ record(price=price,
+ cash=context.portfolio.cash,
+ price_change=price_change,
+ short_mavg=short_mavg,
+ long_mavg=long_mavg)
+
+ # Since we are using limit orders, some orders may not execute immediately
+ # we wait until all orders are executed before considering more trades.
+ orders = get_open_orders(context.asset)
+ if len(orders) > 0:
+ return
+
+ # Exit if we cannot trade
+ if not data.can_trade(context.asset):
+ return
+
+ # We check what's our position on our portfolio and trade accordingly
+ pos_amount = context.portfolio.positions[context.asset].amount
+
+ # Trading logic
+ if short_mavg > long_mavg and pos_amount == 0:
+ # we buy 100% of our portfolio for this asset
+ order_target_percent(context.asset, 1)
+ elif short_mavg < long_mavg and pos_amount > 0:
+ # we sell all our positions for this asset
+ order_target_percent(context.asset, 0)
+
+
+def analyze(context, perf):
+
+ # Get the base_currency that was passed as a parameter to the simulation
+ base_currency = context.exchanges.values()[0].base_currency.upper()
+
+ # First chart: Plot portfolio value using base_currency
+ ax1 = plt.subplot(411)
+ perf.loc[:, ['portfolio_value']].plot(ax=ax1)
+ ax1.legend_.remove()
+ ax1.set_ylabel('Portfolio Value\n({})'.format(base_currency))
+ start, end = ax1.get_ylim()
+ ax1.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
+
+ # Second chart: Plot asset price, moving averages and buys/sells
+ ax2 = plt.subplot(412, sharex=ax1)
+ perf.loc[:, ['price','short_mavg','long_mavg']].plot(ax=ax2, label='Price')
+ ax2.legend_.remove()
+ ax2.set_ylabel('{asset}\n({base})'.format(
+ asset = context.asset.symbol,
+ base = base_currency
+ ))
+ start, end = ax2.get_ylim()
+ ax2.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
+
+ transaction_df = extract_transactions(perf)
+ if not transaction_df.empty:
+ buy_df = transaction_df[transaction_df['amount'] > 0]
+ sell_df = transaction_df[transaction_df['amount'] < 0]
+ ax2.scatter(
+ buy_df.index.to_pydatetime(),
+ perf.loc[buy_df.index, 'price'],
+ marker='^',
+ s=100,
+ c='green',
+ label=''
+ )
+ ax2.scatter(
+ sell_df.index.to_pydatetime(),
+ perf.loc[sell_df.index, 'price'],
+ marker='v',
+ s=100,
+ c='red',
+ label=''
+ )
+
+ # Third chart: Compare percentage change between our portfolio
+ # and the price of the asset
+ ax3 = plt.subplot(413, sharex=ax1)
+ perf.loc[:, ['algorithm_period_return', 'price_change']].plot(ax=ax3)
+ ax3.legend_.remove()
+ ax3.set_ylabel('Percent Change')
+ start, end = ax3.get_ylim()
+ ax3.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
+
+ # Fourth chart: Plot our cash
+ ax4 = plt.subplot(414, sharex=ax1)
+ perf.cash.plot(ax=ax4)
+ ax4.set_ylabel('Cash\n({})'.format(base_currency))
+ start, end = ax4.get_ylim()
+ ax4.yaxis.set_ticks(np.arange(0, end, end/5))
+
+ plt.show()
+
+
+if __name__ == '__main__':
+ run_algorithm(
+ capital_base=1000,
+ data_frequency='minute',
+ initialize=initialize,
+ handle_data=handle_data,
+ analyze=analyze,
+ exchange_name='bitfinex',
+ algo_namespace=NAMESPACE,
+ base_currency='usd',
+ start=pd.to_datetime('2017-9-22', utc=True),
+ end=pd.to_datetime('2017-9-23', utc=True),
+ )
+
+
+
Mean Reversion Algorithm
-
source: examples/mean_reversion_simple.py
+
Source code: examples/mean_reversion_simple.py
This algorithm is based on a simple momentum strategy. When the cryptoasset goes
up quickly, we’re going to buy; when it goes down quickly, we’re going to sell.
Hopefully, we’ll ride the waves.
-
We are choosing to run this trading algorithm with the neo_usd currency pair
-on the Bitfinex exchange. Thus, first ingest the historical pricing data
+
We are choosing to backtest this trading algorithm with the neo_usd currency
+pairon the Bitfinex exchange. Thus, first ingest the historical pricing data
that we need, with minute resolution:
catalyst ingest-exchange -x bitfinex -f minute -i neo_usd
@@ -427,21 +668,28 @@ lines 218-245, so in order to run the algorithm we just type:
python mean_reversion_simple.py
-
import pandas as pd
+import os
+import tempfile
+import time
+
+import numpy as np
+import pandas as pd
import talib
from logbook import Logger
from catalyst import run_algorithm
from catalyst.api import symbol, record, order_target_percent, get_open_orders
from catalyst.exchange.stats_utils import extract_transactions
-
# We give a name to the algorithm which Catalyst will use to persist its state.
# In this example, Catalyst will create the `.catalyst/data/live_algos`
# directory. If we stop and start the algorithm, Catalyst will resume its
# state using the files included in the folder.
+from catalyst.utils.paths import ensure_directory
+
NAMESPACE = 'mean_reversion_simple'
log = Logger(NAMESPACE)
+
# To run an algorithm in Catalyst, you need two functions: initialize and
# handle_data.
@@ -451,11 +699,17 @@ lines 218-245, so in order to run the algorithm we just type:
# trading pairs) you want to backtest. You'll also want to define any
# parameters or values you're going to use.
- # In our example, we're looking at Ether in USD Tether.
- context.neo_usd = symbol('neo_usd')
+ # In our example, we're looking at Neo in USD.
+ context.neo_eth = symbol('neo_usd')
context.base_price = None
context.current_day = None
+ context.RSI_OVERSOLD = 30
+ context.RSI_OVERBOUGHT = 80
+ context.CANDLE_SIZE = '15T'
+
+ context.start_time = time.time()
+
def handle_data(context, data):
# This handle_data function is where the real work is done. Our data is
@@ -472,17 +726,17 @@ lines 218-245, so in order to run the algorithm we just type:
context.current_day = today
# We're computing the volume-weighted-average-price of the security
- # defined above, in the context.neo_usd variable. For this example, we're
+ # defined above, in the context.neo_eth variable. For this example, we're
# using three bars on the 15 min bars.
# The frequency attribute determine the bar size. We use this convention
# for the frequency alias:
# http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
prices = data.history(
- context.neo_usd,
+ context.neo_eth,
fields='close',
bar_count=50,
- frequency='15T'
+ frequency=context.CANDLE_SIZE
)
# Ta-lib calculates various technical indicator based on price and
@@ -494,7 +748,7 @@ lines 218-245, so in order to run the algorithm we just type:
# We need a variable for the current price of the security to compare to
# the average. Since we are requesting two fields, data.current()
# returns a DataFrame with
- current = data.current(context.neo_usd, fields=['close', 'volume'])
+ current = data.current(context.neo_eth, fields=['close', 'volume'])
price = current['close']
# If base_price is not set, we use the current value. This is the
@@ -523,56 +777,65 @@ lines 218-245, so in order to run the algorithm we just type:
# Since we are using limit orders, some orders may not execute immediately
# we wait until all orders are executed before considering more trades.
- orders = get_open_orders(context.neo_usd)
+ orders = get_open_orders(context.neo_eth)
if len(orders) > 0:
return
# Exit if we cannot trade
- if not data.can_trade(context.neo_usd):
+ if not data.can_trade(context.neo_eth):
return
# Another powerful built-in feature of the Catalyst backtester is the
# portfolio object. The portfolio object tracks your positions, cash,
# cost basis of specific holdings, and more. In this line, we calculate
# how long or short our position is at this minute.
- pos_amount = context.portfolio.positions[context.neo_usd].amount
+ pos_amount = context.portfolio.positions[context.neo_eth].amount
- if rsi[-1] <= 30 and pos_amount == 0:
+ if rsi[-1] <= context.RSI_OVERSOLD and pos_amount == 0:
log.info(
'{}: buying - price: {}, rsi: {}'.format(
data.current_dt, price, rsi[-1]
)
)
- order_target_percent(context.neo_usd, 1)
+ # Set a style for limit orders,
+ limit_price = price * 1.005
+ order_target_percent(
+ context.neo_eth, 1, limit_price=limit_price
+ )
context.traded_today = True
- elif rsi[-1] >= 80 and pos_amount > 0:
+ elif rsi[-1] >= context.RSI_OVERBOUGHT and pos_amount > 0:
log.info(
'{}: selling - price: {}, rsi: {}'.format(
data.current_dt, price, rsi[-1]
)
)
- order_target_percent(context.neo_usd, 0)
+ limit_price = price * 0.995
+ order_target_percent(
+ context.neo_eth, 0, limit_price=limit_price
+ )
context.traded_today = True
def analyze(context=None, perf=None):
- import matplotlib.pyplot as plt
+ end = time.time()
+ log.info('elapsed time: {}'.format(end - context.start_time))
+ import matplotlib.pyplot as plt
# The base currency of the algo exchange
base_currency = context.exchanges.values()[0].base_currency.upper()
# Plot the portfolio value over time.
ax1 = plt.subplot(611)
perf.loc[:, 'portfolio_value'].plot(ax=ax1)
- ax1.set_ylabel('Portfolio Value ({})'.format(base_currency))
+ ax1.set_ylabel('Portfolio\nValue\n({})'.format(base_currency))
# Plot the price increase or decrease over time.
ax2 = plt.subplot(612, sharex=ax1)
perf.loc[:, 'price'].plot(ax=ax2, label='Price')
- ax2.set_ylabel('{asset} ({base})'.format(
- asset=context.neo_usd.symbol, base=base_currency
+ ax2.set_ylabel('{asset}\n({base})'.format(
+ asset=context.neo_eth.symbol, base=base_currency
))
transaction_df = extract_transactions(perf)
@@ -581,7 +844,7 @@ lines 218-245, so in order to run the algorithm we just type:
sell_df = transaction_df[transaction_df['amount'] < 0]
ax2.scatter(
buy_df.index.to_pydatetime(),
- perf.loc[buy_df.index, 'price'],
+ perf.loc[buy_df.index.floor('1 min'), 'price'],
marker='^',
s=100,
c='green',
@@ -589,7 +852,7 @@ lines 218-245, so in order to run the algorithm we just type:
)
ax2.scatter(
sell_df.index.to_pydatetime(),
- perf.loc[sell_df.index, 'price'],
+ perf.loc[sell_df.index.floor('1 min'), 'price'],
marker='v',
s=100,
c='red',
@@ -600,23 +863,24 @@ lines 218-245, so in order to run the algorithm we just type:
perf.loc[:, 'cash'].plot(
ax=ax4, label='Base Currency ({})'.format(base_currency)
)
- ax4.set_ylabel('Cash ({})'.format(base_currency))
+ ax4.set_ylabel('Cash\n({})'.format(base_currency))
perf['algorithm'] = perf.loc[:, 'algorithm_period_return']
ax5 = plt.subplot(614, sharex=ax1)
perf.loc[:, ['algorithm', 'price_change']].plot(ax=ax5)
- ax5.set_ylabel('Percent Change')
+ ax5.set_ylabel('Percent\nChange')
ax6 = plt.subplot(615, sharex=ax1)
perf.loc[:, 'rsi'].plot(ax=ax6, label='RSI')
- ax6.axhline(70, color='darkgoldenrod')
- ax6.axhline(30, color='darkgoldenrod')
+ ax6.set_ylabel('RSI')
+ ax6.axhline(context.RSI_OVERBOUGHT, color='darkgoldenrod')
+ ax6.axhline(context.RSI_OVERSOLD, color='darkgoldenrod')
if not transaction_df.empty:
ax6.scatter(
buy_df.index.to_pydatetime(),
- perf.loc[buy_df.index, 'rsi'],
+ perf.loc[buy_df.index.floor('1 min'), 'rsi'],
marker='^',
s=100,
c='green',
@@ -624,13 +888,15 @@ lines 218-245, so in order to run the algorithm we just type:
)
ax6.scatter(
sell_df.index.to_pydatetime(),
- perf.loc[sell_df.index, 'rsi'],
+ perf.loc[sell_df.index.floor('1 min'), 'rsi'],
marker='v',
s=100,
c='red',
label=''
)
plt.legend(loc=3)
+ start, end = ax6.get_ylim()
+ ax6.yaxis.set_ticks(np.arange(0, end, end/5))
# Show the plot.
plt.gcf().set_size_inches(18, 8)
@@ -643,7 +909,14 @@ lines 218-245, so in order to run the algorithm we just type:
MODE = 'backtest'
if MODE == 'backtest':
- # catalyst run -f catalyst/examples/mean_reversion_simple.py -x poloniex -s 2017-10-1 -e 2017-11-10 -c usdt -n mean-reversion --data-frequency minute --capital-base 10000
+ folder = os.path.join(
+ tempfile.gettempdir(), 'catalyst', NAMESPACE
+ )
+ ensure_directory(folder)
+
+ timestr = time.strftime('%Y%m%d-%H%M%S')
+ out = os.path.join(folder, '{}.p'.format(timestr))
+ # catalyst run -f catalyst/examples/mean_reversion_simple.py -x bitfinex -s 2017-10-1 -e 2017-11-10 -c usdt -n mean-reversion --data-frequency minute --capital-base 10000
run_algorithm(
capital_base=10000,
data_frequency='minute',
@@ -653,23 +926,34 @@ lines 218-245, so in order to run the algorithm we just type:
exchange_name='bitfinex',
algo_namespace=NAMESPACE,
base_currency='usd',
- start=pd.to_datetime('2017-10-1', utc=True),
+ start=pd.to_datetime('2017-10-01', utc=True),
end=pd.to_datetime('2017-11-10', utc=True),
+ output=out
)
+ log.info('saved perf stats: {}'.format(out))
elif MODE == 'live':
run_algorithm(
+ capital_base=0.5,
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
- exchange_name='bitfinex',
+ exchange_name='bittrex',
live=True,
algo_namespace=NAMESPACE,
base_currency='usd',
- live_graph=True
+ live_graph=False
)
+
+Notice the difference in performance between the charts above and those seen on
+this video tutorial at
+minute 8:10. The buy and sell orders are triggered at the same exact times, but
+the differences result from a more realistic slippage model
+implemented after the video was recorded, which executes the orders at slighlty
+different prices, but resulting in significant changes in performance of our
+strategy.
diff --git a/genindex.html b/genindex.html
index 1e8ea3d3..9158892a 100644
--- a/genindex.html
+++ b/genindex.html
@@ -121,7 +121,10 @@
Naming Convention
Example Algorithms
@@ -231,7 +234,7 @@
- Docs »
-
+ - Index
-
diff --git a/index.html b/index.html
index 8c63f67b..1b92f02a 100644
--- a/index.html
+++ b/index.html
@@ -121,7 +121,10 @@
- Naming Convention
- Example Algorithms
diff --git a/objects.inv b/objects.inv
index ded63fcdf3207ffd49ce64b905ec738b546cb3f6..4848afe715dc1b482ae1d8161e594b9ebd36d36c 100644
GIT binary patch
delta 491
zcmVKf~$+T?ycRGAc8=lpgl%zJW4D%w$~qR!>?x?
zJ6p1gQn-1>@4a~5n;fGS3OsAgFmNrX58_VoBPhz=(__Be^kGnM-qHu@TXO;@bw{@+
zE)l1I?lOoR`B
ziTzKK2xkSJM0Y>#=^>X_+16;mmugb`z?GWkta6#gJR^lp3?g{otT?i669S)I5s|BA
zFeemiIC{ss+mj>?%N#ay942g(ITTn^r-*<
delta 393
zcmV;40e1e_1oi`vcYl*jPs1<_hVS_mk>HvkuDfkQf(iLiV?
zxl&_6NgsxKPAH*KK?JWk8%m$Q4}xFi7ht3j&`uTOX)nQq_)ah%_!^%qq?%2UjA%?o
zu+*lVz0&>j`^{6N-r&&43N)D76U}q$XN4)xU$#F)z|Fn_oS2u^T%1Y3*%?nUM87dS
z&qZ7DN2grJ#(xh(vr;P>+>gFzPP%`M68WG3Ji#KJoQk<~V1#T(^=2UHYLk#dgUh7Y
zw>6j@(QCx%E_qCbWrz;7brSnAm}yy6wz}xkizb$7R1y!o%FC%ie>QY$+XEY306AeB
n?P-4AyMdWZ{6o6XhDEshVytic6
- Naming Convention
- Example Algorithms
diff --git a/search.html b/search.html
index 6b0cf20c..8da6d5d9 100644
--- a/search.html
+++ b/search.html
@@ -120,7 +120,10 @@
- Naming Convention
- Example Algorithms
@@ -230,7 +233,7 @@
- Docs »
-
+ - Search
-
diff --git a/searchindex.js b/searchindex.js
index 844706f4..15c239fb 100644
--- a/searchindex.js
+++ b/searchindex.js
@@ -1 +1 @@
-Search.setIndex({envversion:46,filenames:["appendix","beginner-tutorial","bundles","development-guidelines","example-algos","index","install","jupyter","live-trading","naming-convention","release-process","releases","resources","utilities","videos","welcome"],objects:{"zipline.data.bundles":{bundles:[0,0,1,""]}},objnames:{"0":["py","data","Python data"]},objtypes:{"0":"py:data"},terms:{"000000e":1,"1000th":7,"15t":4,"1st":1,"328842e":1,"340mb":11,"380954e":1,"40mb":11,"460mb":11,"505275d6646a41f3856b22b16678d":1,"536708e":1,"5min":[4,7],"650729e":1,"7869f7828fa140328eb40477bb7d":1,"998236e":1,"998677e":1,"999120e":1,"999558e":1,"99mb":11,"__file__":13,"__main__":[1,4],"__name__":[1,4],"__wrapped__":10,"_tkinter":1,"boolean":[2,8],"case":[1,2,3,6,13],"class":[3,10],"default":1,"export":10,"final":[1,2,3],"float":[1,11],"import":[1,2,4,7,10,13],"int":2,"long":[1,2,4],"new":1,"public":11,"return":[1,4,8,10,11,12],"short":[1,3,4],"static":10,"throw":11,"true":[1,4,7,8],"try":[4,6],"var":1,"while":[6,10,11],aapl:2,abil:2,abl:[1,2,6],about:[1,2,5,6,15],abov:[1,3,4,6,8,9,10],accept:[2,6,10],accord:10,accordingli:1,account:[2,4,5,7,11,15],acquir:[2,6],across:[5,9,11,15],activ:[6,10],actual:7,add:[1,2,3,6,10,13],addit:[1,3,5,6,11,15],address:10,adjust:[2,11],administr:6,advantag:6,afford:[4,7],aforement:1,after:[1,2,4,6,7,10],again:1,against:[1,5,8,11,15],agre:4,ahead:1,aim:12,algebra:6,algo:[1,2,4,11],algo_namespac:[1,4,8],algo_volatil:[1,7],algofil:[1,2],algorith:1,algorithm_period_return:[1,4,7],algotext:1,alia:4,alias:4,all:[0,1,2,3,4,5,6,7,8,9,10,11,15],allow:[1,2,5,6,15],along:2,alongsid:1,alpha:[1,4,6,7],alreadi:[1,2,3,6,7],also:[1,2,3,4,5,6,7,8,10,15],altern:[1,6,9],although:1,alwai:[2,8,9,10],amount:[1,4,7,11],amp_btc:9,anaconda:[1,6,10],analog:1,analysi:[1,4,5,10,11,12,15],analyst:12,analyt:[5,6,15],analyz:[1,4,7,8,11,13],ani:[1,2,4,6,7,9,10,13],anonym:2,anoth:[1,2,4,7],anymor:1,anyth:[1,6,10],apach:4,appar:1,appear:[2,10],append:10,appli:1,applic:[1,4],appropri:[1,3],approxim:[4,7],appveyor:10,apt:[1,6],arang:1,arbitrari:8,arbitrarili:1,arch:6,architectur:1,ardr_btc:9,arg:[1,10],argument:[0,1,2,7,8,10],argv:13,around:[5,10,15],arrai:[4,6],art:[5,15],articl:3,ask:[1,3],assess:1,asset_nam:[4,7],assetdbwrit:2,assign:[1,8],assimil:1,assist:6,assum:[1,3,6],atla:6,attempt:[2,8],attribut:[4,10],auth:[8,11],auto:11,avail:1,avoid:[1,2,4],awar:10,ax1:[1,4,7],ax2:[1,4,7],ax3:[1,4,7],ax4:[1,4,7],ax5:[4,7],ax6:[4,7],axhlin:4,back:[3,6,9],backend:6,bah:4,bar:[1,4,11],bar_count:[1,4],base:[1,2,4,5,6,7,8,14,15],base_curr:[1,4,8,9,13],base_pric:[1,4],basenam:13,basi:[4,11],batch:6,batteri:1,bch_btc:9,bch_eth:9,bch_usdt:9,bcn_btc:9,bcn_xmr:9,bcolz:2,bcolzdailybarread:2,bcolzdailybarwrit:2,bcolzminutebarread:2,bcolzminutebarwrit:2,bcy_btc:9,be62ff77760c4599abaac43be9cc9:1,bear:[1,4],beautifi:1,becaus:[6,7,10,11],been:[0,1,2,6,10],befor:[1,2,4,6,8,11],before_trading_start:[0,4],begin:[1,6],behavior:0,bela_btc:9,believ:1,below:[1,4,6,7,13],benchmark:[4,5,7,11,15],benchmark_period_return:[1,4,7],benchmark_volatil:[1,7],benefit:1,best:[3,5,6,15],beta:[1,4,7],better:1,between:[1,3,5,9,15],bia:1,big:6,bin:[4,6],binari:[6,10],bit:[3,6],bitcoin:[1,5,8,9,13,15],bitcoin_usd_asset:8,bitfinex:[1,4,5,7,8,11,15],bittrex:[1,5,8,11,15],bld:3,blk_btc:9,blk_xmr:9,blockchain:9,blotter:13,blue:1,bodi:3,book:1,both:[1,3,8,9,10],bought:1,bound:1,breakdown:8,brew:6,brother:6,brows:6,browser:[3,7,10],btc:[1,4,8,11],btc_usd:[1,7,8,9],btc_usdt:[4,5,9,13,15],btcd_btc:9,btcd_xmr:9,btm_btc:9,bts_btc:9,bug:[2,3],bui:1,build:[1,3,6,10],build_ext:3,burst_btc:9,button:[6,10],buy_and_hodl:[4,11],buy_btc_simpl:1,buy_btc_simple_out:1,buy_df:[1,4],buy_low_sell_high:11,calcul:[1,3,4,8],call:[1,2,3,4],can:[1,2,3,4,5,6,8,9,10,11,13,15],can_trad:[1,4,11],cancel_ord:[4,7],candl:[1,9,11],cannot:[1,4,6],canon:3,capit:[1,4,7],capital_bas:[1,4,11,13],capital_us:[1,7],captur:1,cash:[1,2,3,4,7,11],catalyst_dev:[1,5,6,15],caus:[0,1,2,3],cell:7,cert:11,certian:0,chanc:1,chang:[1,3,4,5,6,7,10,11,15],channel:[1,5,6,15],charact:3,charg:1,chart:[1,6],check:[1,2,3,4,6,7,8,9],checker:10,checkout:[3,10],choic:10,choos:[1,4,6,9,10,13],chosen:[1,13],chunk:[1,11],circumv:6,clam_btc:9,classic:1,classifi:1,clean:[2,6,10,11],clear:2,cli:[1,4,7,11,13],click:[6,10],client:8,clone:3,close:[1,4,7,13],cmd:[1,6],code:[1,4,6,10,11,13],codebas:3,coin:[7,11],collect:[1,2,4],color:[4,7],column:[1,2,7],com:[1,2,3,8],combin:[6,8],come:[2,6],comment:1,common:1,commonli:1,commun:[6,12],comp:4,compar:[1,4,5,15],comparison:11,compat:[5,11,15],compil:[6,10,11],complement:4,complet:8,complex:[1,6],complianc:4,complimentari:13,comprehens:11,compress:[1,11],comput:[1,4,6,11,12],concept:1,conda:1,conda_build_matrix:10,condit:4,config:6,configur:[1,6,11],congratul:6,consid:[1,4],consist:[1,9],constant:7,constraint:2,consum:10,contain:[1,2,3,6,7],content:1,context:[1,4,7,13],continu:1,continuum:6,conveni:1,convent:[4,8],convers:2,convert:2,copi:[1,2,3,4,10],copyright:4,core:6,correct:[2,6,8,10],correctli:[1,6,10],correctwai:6,correspond:[1,6,8,13],cost:[1,4],could:[0,1,2,4,6,7,13],count:2,coupl:1,cover:[1,13],coverag:[5,8,9,15],cpython:6,crash:2,creat:[1,2],creation:11,crossov:1,crowd:12,crypto:[1,5,11,15],cryptoasset:[1,4,13,14],cryptocurr:[4,9],csv:[7,11],csvfile:13,csvwriter:13,cumul:11,cumulative_capital_us:3,curat:[1,5,15],currenc:[1,4],current:[0,1,2,4,6,7,8,10,11,13],current_dai:4,current_dt:[4,13],custom:[1,2,13],cvc_btc:9,cvc_eth:9,cython:10,d6dca79513214346a646079213526:1,dai:[1,2,4,7,10],daili:[1,2,4,5,9,11,13,15],darkgoldenrod:4,dash:8,dash_btc:9,dash_usdt:9,dash_xmr:9,data_frequ:[1,4,13],databas:2,datafram:[1,2,4,5,7,12,13,15],dataframe_cach:2,dataset:[1,2],date:[1,2,4,6,10,11,13],datetim:13,dcr_btc:9,debian:[1,6],debug:10,decid:10,decim:11,decor:10,decreas:4,def:[1,4,7,13],defin:[1,4,7,8],delai:1,delet:2,demonstr:1,denomin:7,dep:3,depend:[1,3,6,10,11,13],deploi:10,deprec:3,deriv:6,descript:[3,6],desir:[7,13],desktop:9,detail:[5,15],determin:4,dev1:6,dev2:6,dev3:6,dev4:6,dev5:6,dev6:6,dev8:6,dev9:6,dev:[3,6,9],devel:6,develop:1,devis:1,dgb_btc:9,dictionari:11,did:[5,15],didn:6,differ:[1,2,6,8,9,10,13],dir:6,directli:[1,2,6,11,13],directori:[1,2,3,4,6,8,10],disabl:11,disablemsi:6,discord:[1,3,5,6,15],discuss:1,disk:11,dismiss:1,displai:[1,6,7,10,11],dist:10,distribut:[4,6,10],distutil:10,divid:3,dividend:2,dma:1,dname:1,dnf:6,doc:2,docker:3,dockerfil:3,document:[3,4,6,8],doe:[2,6,7,9],doesn:2,doge_btc:9,dollar:9,don:[1,3,7,14],done:[1,4,7,10],down:[1,4,14],download:[1,2,6,7,11],draft:10,drawback:2,drive:1,driven:[1,5,15],dropbox:11,dual_moving_averag:1,dword:6,each:[1,2,3,4,5,6,8,9,11,13,15],earlier:[1,2,3,4],earliest:4,eas:[5,15],easi:[1,2,7,12],easier:[1,2,9],easiest:6,easili:[1,5,6,15],echo:6,eco:[5,15],edit:[3,6,10],editor:6,educ:1,educt:1,either:[1,4,6],elif:[1,4],els:6,emc2_btc:9,empow:[1,5,15],empti:[1,2,3,4,8,10,11],enabl:8,encount:6,end:[1,4,7,11,13],end_dat:1,ending_cash:[1,7],ending_exposur:[1,7],enh:3,enhanc:3,enigma:[1,4,5,6,8,9,15],enigmampc:[1,3],enough:[1,6],ensur:[0,6,8,10],enter:[1,6],entir:3,entri:[1,6],env:[4,6],enviorn:2,enviro:6,environ:1,environemnt:[6,7],equal:[2,4,7,13],equiti:2,error:[1,3,4,6,7,8,9,11],especi:1,establish:[5,15],estim:1,etc:[3,10,11],etc_btc:9,etc_eth:9,etc_usdt:9,eth:[1,8],eth_btc:[8,9],eth_usdt:9,ether:4,ethereum_bitcoin_asset:8,evalu:1,even:[2,6],event:1,eventu:1,everi:[1,6,7],everyth:[1,2],exact:13,examin:1,excel:6,except:[1,4],exchang:[1,2,4],exchange_algorithm:1,exchange_nam:[1,4,8,13],execut:[0,1,4,7,8,11],exist:[2,3,5,6,15],exit:[1,4,10],exit_success:10,exp_btc:9,expect:[0,2,6,7,9,10],experi:6,experienc:6,explain:[6,8],explicitli:10,explictili:6,express:[1,4,5,15],extend:1,extens:[2,3,6],extern:[1,6],extra:10,extract_transact:[1,4],facto:7,fail:[2,6,7],failur:2,fairli:[1,3],fals:[4,7],familiar:3,fantast:1,far:2,fast:2,fatal:6,fct_btc:9,featur:[1,4],fedora:6,feedback:2,feel:[1,7],fetch:[2,9,11],few:[1,2,10],fewer:6,field:[2,4,10],file:[1,2,3,4,6,7,8],filenam:[1,13],fill:1,filter:11,financ:7,financi:[1,11],find:[1,2,6,10],fine:10,finish:1,fix:3,flag:[1,4,6,8,10],flake8:3,fldc_btc:9,flo_btc:9,floor:4,focu:[1,5,15],folder:[4,6,11],follow:[0,1,2,3,4,6,7,8,9,10,13],footprint:6,fork:12,form:[1,9],format:[1,2],fortran:6,forward:2,foster:12,found:[1,3,6,9],fourth:1,fraction:11,frame:[1,4],free:[1,7],freelanc:12,freetyp:6,freq:1,frequenc:[1,4,11],fresh:10,from:[0,1,2,3,4,6,7,9,10,11,13],full:[1,7,13],fund:12,fundament:12,further:[1,4,5,15],futur:[1,2],game_btc:9,gas_btc:9,gas_eth:9,gave:1,gcc:6,gcf:[4,7],gen_type_stub:10,gener:[2,3,5,6,8,10,11,13,15],get:[1,2,3,4],get_open_ord:[1,4,7],get_ylim:1,gfortran:6,github:[1,3,6,10],give:4,given:[1,2,9,13],global:1,gno_btc:9,gno_eth:9,gnt_btc:9,gnt_eth:9,goe:[4,8,14],good:[1,10],goog:2,got:1,govern:4,grain:10,graph:7,grc_btc:9,green:[1,4],group:[1,3],grow:2,guid:[3,6,11],gzip:10,hand:3,handi:[1,6],handl:[3,4,11],handle_data:[0,1,4,7,8,13],hang:6,happen:[1,2],happi:10,hard:1,hash:11,have:[0,1,2,3,5,6,7,10,15],haven:1,head:[1,6,7],header:[6,10],heavi:1,heavili:12,hedg:12,held:9,help:[1,2],henc:1,here:[1,2,6,7,8],hidden:10,high:[1,8,12,13],highest:10,hint:[6,10],histor:[1,4,5,11,15],hit:[1,11],hitchhik:6,hkey_local_machin:6,hold:[4,8],home:11,homebrew:6,hope:1,hopefulli:[4,14],how:[1,2,4,6,7,8],howev:[8,10],html:[3,4,10],http:[1,4,8,10],huc_btc:9,idea:[1,2,3],illustr:8,immedi:[1,4],immut:0,impact:11,imper:3,implement:[1,2,4,11],impli:4,implicitli:0,importerror:1,improv:[3,11],inc:4,includ:[1,2,3,4,6,10,13],incomplet:2,inconsist:8,increas:[2,4,11],increment:[1,10],independ:6,index:[1,3,4,7,10],indic:[2,4,6],individu:[1,8],infer:2,influenc:1,info:[1,4,7],inform:[0,1,2,6,10],initi:[0,1,4,7,8,11,13],inlin:7,inplac:3,input:[5,7,9,15],insid:[1,6,7],insight:[1,5,15],inspect:1,instal:[1,3],installt:6,instanc:[0,2,4],instead:[1,2,3,4,7,9,11],instruct:[1,3,6],integ:[2,11],integr:[5,15],intend:[1,3,10],interact:7,intern:[2,6],interpret:[4,7,13],interv:4,introduc:[1,8,9,11],invest:[1,5,15],invok:[1,2],involv:[2,6],ipython:7,is_bui:[4,7],issu:[1,3,6,9,10,11],iter:[1,2,13],itself:1,jan:1,join:[5,6,15],json:[8,11],juli:13,jump:6,jupyt:1,just:[1,2,4,7,9,10],keep:[1,2,6],kei:[2,5,6,8,15],kept:1,keyerror:11,kind:4,know:7,knowledg:[5,15],kwarg:10,label:[1,4,8,10],lack:9,languag:4,lapack:6,larg:2,larger:11,last:[1,2,6,7,11],later:[1,2,3],latest:[10,11],launch:[6,7],law:4,layer:9,lazi:2,lbc_btc:9,leak:2,learn:[1,5,6,15],least:[1,3],legend:[4,7],legend_:1,len:[1,4],less:2,let:[1,7],level:[1,2,4],leverag:[4,7,12],lib:4,libatla:6,libfreetype6:6,libgfortran:6,librari:[1,3,4,5,6,11,12,15],licens:4,lifetim:2,like:[1,2,3,5,6,9,10,15],limit:[1,4,9,11],limit_pric:[4,7],linear:6,linter:10,linux:1,list:[0,2,6,9,10,13],littl:[1,3],live:[1,4,6],live_algo:4,live_graph:4,load:[1,2,7],load_ext:7,loc:[1,4,7],local:[1,2,3,6,7,10],locat:[1,2,13],log:[1,4,6],logbook:[1,4],logger:[1,4],logic:[1,11],long_mavg:1,long_window:1,longer:[1,3,10],look:[1,2,4,7,10,13],lookup:1,loop:2,loss:11,lot:2,low:[1,8],lower:11,lowercas:[8,9],lsk_btc:9,lsk_eth:9,ltc:8,ltc_btc:9,ltc_usd:1,ltc_usdt:9,ltc_xmr:9,machin:[2,5,10,15],maco:1,made:[2,3],magic:[1,7],mai:[1,2,4,6,10],maid_btc:9,maid_xmr:9,main:[1,6,10],maint:3,maintain:[9,10],mainten:3,major:10,make:[1,2,3,4,6,7,9,10],manag:[1,6,10],mani:[1,2,6,10,12],manifest:10,manner:8,manual:[6,10],map:[0,2,9],marker:[1,4],markers:[4,7],market:[1,8,9],market_curr:9,marketplac:1,master:10,match:[1,6,8,10],matplotlib:[1,4],matplotlibrc:6,matrix:10,matter:3,mavg:1,max_capital_us:3,max_leverag:3,maxim:[5,15],maybe_show_progress:2,mcoin:[4,7],mean:[1,2],mean_reversion_simpl:4,memori:2,mention:[1,6,10],menu:6,merg:1,merger:2,messag:1,method:[0,1,2,4,6,10,11,13],metric:[1,11],micro:10,microsoft:6,might:1,migrat:1,min:4,mind:[1,4],miniconda:6,minim:[5,15],minimum:11,minor:10,minut:[1,2,4,5,6,11,13,15],miss:[1,6,8,11],mkvirtualenv:3,mode:[1,4,5,8,11,15],modif:[3,8],modifi:13,modul:1,moment:[6,10],momentum:[1,4,14],monei:0,month:[10,13],more:[0,1,2,4,5,6,11,13,15],most:[1,2,4,6,7,8,11],mostli:1,movement:1,mpc:[1,4],msft:2,msi:6,msiexec:6,much:[1,2],multipl:[2,10,11],must:[1,2,8,10],my_algo_cod:8,my_algo_nam:8,name:[1,2,3,4,6,7,8],namespac:[1,4,10],nan:[1,7],nano:10,nativ:6,naut_btc:9,nav_btc:9,navig:[3,6],ndarrai:1,necessari:6,nee:6,need:[1,2,3,4,6,9,10,12,13],neg:1,neo_eth:8,neo_ethereum_asset:8,neo_usd:4,neos_btc:9,never:2,newer:2,nice:[5,15],nmc_btc:9,non:6,none:[1,4,7,13],normal:11,note:1,note_btc:9,notebook:1,noth:6,novemb:10,now:[1,2,4,6,10,11],number:[1,2,4,6,10,11],numer:6,numpi:[1,3,6,10,12],nxc_btc:9,nxt_btc:9,nxt_usdt:9,nxt_xmr:9,observ:6,obtain:[1,4],occur:[1,8],off:12,offer:1,offset:4,ohlc:1,ohlcv:11,older:2,omg_btc:9,omg_eth:9,omni:9,omni_btc:9,onc:[1,2,4,6,7,10],onli:[0,1,2,3,4,5,6,10,13,15],open:[1,3,6,7,11,13],openssl:6,oper:6,operatbl:6,opt:4,optim:[1,12],option:[1,2,6,13],order_id:1,order_target_perc:[1,4],order_target_valu:[4,7],ordered_pip:3,org:[4,10],organ:1,origin:[1,10],osx:10,other:[1,2,4,6,9,10,13],otherwis:6,our:[1,3,4,5,6,10,15],out:[1,2,3,5,6,7,10,15],outdat:6,outlin:6,output:[1,2,7],outstand:[4,7],overcom:9,overfit:1,overrid:[6,10],overview:[1,5,9,15],overwhelm:1,own:[2,6,8],packag:[1,6,7],pacman:6,page:[3,6,10,11],pair:[1,4,7,8,9,11],panda:[1,2,4,5,12,15],paper:3,parent:6,pars:2,part:[1,2,6,8],partial:6,particular:[5,6,15],pasc_btc:9,pass:[1,2,4,7,10],password:10,past:1,path:[2,6,11,13],pend:10,peopl:3,pep8:3,per:[1,2,4,11],percent:[1,4,7],percentag:1,perf:[1,3,4],perform:[0,1,3,4,5,6,7,11,12,15],period:[3,4],permiss:[4,6],persist:[1,4,11],pickl:[1,4],piec:[2,6],pink_btc:9,pip:[1,3],pkg:6,place:[1,4,7,11],platform:[6,11,12],pleas:[1,5,6,13,15],plot:[1,4,7,12],plt:[1,4,7],plu:13,png:7,point:[1,9,10],poloniex:[1,4,5,7,8,9,11,13,15],popul:10,portfolio:[1,4,7,11,13],portfolio_valu:[1,4,7],pos_amount:[1,4],posit:[1,4,7,11],possibl:[2,3,6],post:10,pot_btc:9,power:[1,4,7,12],ppc_btc:9,practic:[1,3],pre:[2,6],precis:11,predict:[1,8],prefer:6,prefix:3,preload:2,prepare_chunk:11,preprocess:10,prerequisit:[1,6],present:1,preserv:11,prevent:[2,6,10],previous:1,price_chang:[1,4],primari:6,print:[1,6,10],print_result:1,prior:[1,4],privileg:6,probabl:1,problem:[1,2,6,10],proce:6,proceed:6,process:[1,2,8],produc:[2,6],profit:[1,5,15],program:6,progress:2,project:[5,6,12,15],prompt:[1,6],proper:6,properli:[1,6,13],protect:0,protocol:[1,9],provid:[0,1,2,5,6,7,8,11,12,13,15],publish:10,pull:[3,10],pun:1,purchas:[4,7],purpos:[1,8],push:10,put:8,pycharm:10,pydata:[4,5,15],pyfolio:11,pypirc:10,pypitest:10,pyplot:[1,4,7],python2:[6,11],python3:11,python:[1,3,4,6,7],pytz:13,quandl_api_kei:2,quandl_download_attempt:2,quantit:[7,12],queri:2,question:[1,3,5,15],quick:1,quickli:[4,14],quirk:6,quit:2,rads_btc:9,rais:3,ran:2,rang:[1,2,4],rather:[1,6],raw:[2,6],read:[1,2,6],read_pickl:1,readi:10,real:[0,4],realist:1,reason:[1,2,6],rebalanc:1,recal:1,receiv:[1,2],recent:[1,2,4,6],recogn:6,recommend:[2,6],reconstruct:1,record:[1,4,7,13],red:[1,4],redhat:6,redon:11,redownload:[2,7],reduc:11,refactor:3,referenc:8,refus:7,regard:[5,15],regardless:[6,7,8],regedit:6,regist:[0,2,7],registri:6,regular:6,rel:3,relat:3,relationship:2,releas:[3,6],reli:12,remain:11,rememb:6,remot:2,remov:[1,3,6,10,11],renam:10,rep:6,rep_btc:9,rep_eth:9,rep_usdt:9,report:[1,3,6],repositori:[6,10,11],repres:[2,8],reproduc:2,request:[1,2,3,4],requir:[1,3,4],requirements_blaz:3,requirements_dev:3,requirements_doc:3,research:7,reserv:[4,7,9],reserve_ratio:[4,7],reserve_valu:[4,7],resolut:[1,4,5,11,13,15],resourc:[2,11],respect:[3,10,13],respons:2,rest:2,restart:11,restrict:6,restructuredtext:3,result:[1,2,4,6,7,8,13],resum:4,retri:2,retriev:[4,7,11],rev:3,revert:3,review:[1,6],revis:1,rhel:6,ric_btc:9,ride:[4,14],right:6,risk:[1,11],roll:1,rollup:2,root:[3,10],routin:6,row:[1,7],rsi:4,rst:[3,10],run_algo:[1,13],run_algorithm:[1,4,8,13],runtim:1,safe:1,said:1,same:[1,2,6,7,8,10,11,13],sampl:11,satisfi:6,save:[1,2,3,4,6,13],sbd_btc:9,sc_btc:9,scale:[7,11],scatter:[1,4],scientif:12,scikit:1,scipi:[5,6,15],scratch:6,script:[1,10,13],scriptnam:13,seamless:[5,15],search:6,second:[1,6],secret:8,section:[1,3,4,6,8,10,13],secur:[4,5,12,15],see:[0,1,2,4,5,6,8,13,15],seek:6,select:6,self:0,sell:[1,4,8,11,12,14],sell_df:[1,4],separ:[1,3,6,8,9],seper:8,seri:1,seriou:1,server:[1,2,7,10],servic:2,session:6,set:[1,2,4,6,11],set_size_inch:[4,7],set_tick:1,set_ylabel:[1,4,7],setup:[3,7,10],setuptool:6,sever:[1,5,6,15],share:[1,5,15],sharex:[1,4,7],sharp:1,ship:[2,6,10],short_exposur:1,short_mavg:1,short_valu:1,short_window:1,shorter:1,shorts_count:1,should:[0,1,2,3,6,8,10],shourc:2,show:[1,2,4,7],shown:2,sid:[2,7,11],signal:2,signatur:2,similar:[1,6,8],simpl:[1,4,14],simpler:13,simpli:[1,3,6,13],simplifi:1,simultan:11,sinc:[1,4,6,7,10,13],singl:[2,6,11],size:[4,6,11],sjcx_btc:9,skeleton:10,skim:1,skip:1,sklearn:[5,15],slightli:6,small:4,smaller:6,smoothli:14,snip:7,snippet:13,softwar:[4,6],solut:6,solv:[1,2,6],some:[1,2,3,4,6,8,11,12],someon:6,someth:3,somewhat:1,sortino:[1,11],sourc:[1,2,3,4,6,10,12],space:7,special:8,specif:[1,4,11],specifi:[1,2,4,7,8,10],spend:1,spent:9,sphinx:[3,10],split:[1,2],splitext:13,spring:12,sqliteadjustmentwrit:2,ssl:11,stabl:[4,6],stai:10,standard:[2,3,9,11],start:[1,2,3,4,5,6,7,8,13,15],start_dat:1,starting_cash:[1,4,7],starting_exposur:[1,7],starting_valu:[1,7],stat:11,state:[1,2,4,5,11,15],statist:[1,5,8,11,15],stats_util:[1,4],statsmodel:[5,15],statu:8,stdout:1,steem_btc:9,steem_eth:9,still:[1,2,4,6,7],stock:[1,2],stop:[4,7,11],stop_pric:[4,7],storag:[1,8,11],store:[1,2,9,13],str_btc:9,str_usdt:9,strat_btc:9,strategi:[1,4],stream:1,strictli:[2,6],string:[2,7,10],strongli:6,sty:3,style:3,subdirectori:2,subject:3,submit:3,subplot:[1,4,7],substanti:1,succe:10,succeed:7,success:[2,3],sudo:[1,6],suffici:6,suggest:3,summar:6,summari:11,suppli:[1,7],support:[1,4,6,7],suppos:[1,7],sure:6,surpris:1,suspect:3,symbol:[1,2,4,7],symbolnotfoundonexchang:9,sync:10,syntax:[10,11],sys_btc:9,system:[1,3,5,6,15],tag:10,take:[1,2,6,7,11],taken:10,talib:4,tar:10,tarbal:10,target:[1,8],target_hodl_ratio:[4,7],target_hodl_valu:[4,7],technic:[4,5,15],templat:10,temporari:10,ten:1,tend:8,tens:3,term:1,termin:[1,6],test:[1,3,10,11,12],testpypi:10,tether:[4,9],text:1,than:[1,2,3,6],thei:[1,2,10,11,12],them:[1,3,6,10],therefor:10,therein:6,thi:[0,1,2,3,4,6,7,8,9,10,13,14],thing:14,third:1,those:[1,3,10],though:2,three:[1,2,4,5,15],threshold:[4,7],through:[0,1,2,6,7],throughout:1,thu:[1,4,6,7],tick:4,tick_siz:7,ticker:2,time:[1,2,4,5,6,7,10,13,15],timeperiod:4,timeseri:4,timestamp:[1,2,11],titl:10,tkagg:6,to_csv:13,to_datetim:[1,4],to_pydatetim:[1,4],todai:[4,10],togeth:1,token:[8,13],tool:[2,3,6,10,12],top:[1,5,10,15],total:2,toward:1,traceback:9,track:[1,3,4,11],tracker:1,traded_todai:4,trader:[1,12],trading_dai:[1,7],tradingalgorithm:[0,10],tradingcalendar:2,tradit:1,train:1,tran:[4,7],transact:[1,4,7,11],transaction:2,transaction_df:[1,4],transfer:9,transform:1,transit:[5,15],travi:10,treasuri:[4,7],treasury_period_return:[1,4,7],trend:1,tri:[1,5,15],tst:3,tupl:2,turn:10,tweak:1,twice:10,two:[1,4,5,6,13,15],twoargument:1,txt:[3,6,10],type:[4,6,10],typo:3,ubuntu:[1,6],uncompress:11,under:[1,2,4,10],underli:1,underlin:10,underscor:9,understand:[1,6],undesir:0,unexpect:6,unit:[1,9,11],univers:[1,8],unknown:7,unless:4,unlik:2,unpack:6,unregist:0,unresolv:11,untar:2,until:[1,4],unus:3,updat:1,upgrad:[6,10],upper:[1,4],upward:1,url:10,usag:1,usd:[1,4,7,9],usdt:[4,9,13],usdt_btc:7,usdt_btc_benchmark:7,user:[1,2,5,6,7,9,10,15],usernam:10,usr:4,usual:1,utc:[1,4,13],utilit:13,valid:11,valu:[1,4,6,7,8,11],vari:[6,13],variabl:[1,2,4,7,13],varieti:13,variou:[1,2,4],varnam:1,vcforpython27:6,venv:6,veri:[1,2,6,7,10],verifi:[6,10],versatil:13,version:[1,4,6,10],via:[1,6,7,9],via_btc:9,viabl:9,victori:9,video:11,view:[3,10],virtual:6,virtualenvwrapp:3,visit:[5,15],visual:[1,5,6,15],volum:[1,4,5,7,9,11,13,15],volumeshareslippag:7,vrc_btc:9,vtc_btc:9,wai:[1,2,5,6,7,15],wait:[1,4],want:[1,2,3,4,7,9],warn:[7,10,11],warranti:4,wave:[4,14],web:10,weight:4,welcom:3,well:[1,2,5,6,15],were:[3,10],what:[1,3,6,8,10],whatev:2,whatsnew:10,wheel:[6,10],when:[0,1,2,3,4,6,8,10,14],where:[1,2,3,4,5,6,8,9,13,14,15],which:[1,2,3,4,6,7,8,10,11,13],whitepap:[5,12,15],whitespac:3,who:3,whole:1,why:3,width:10,win:10,window:1,within:[6,7],without:[2,4,6,7,8,11],workaround:11,world:1,wors:1,worth:1,would:[1,2,4,6,10],wouldlik:1,wrap:10,write:1,writerow:13,written:[1,2,5,9,15],wrong:9,www:[4,8],xbc_btc:9,xbt:8,xcp_btc:9,xem_btc:9,xmr_btc:9,xmr_usdt:9,xpm_btc:9,xrp_btc:9,xrp_usdt:9,xvc_btc:9,yahoo_equ:2,yaxi:1,year:10,yet:1,yml:[6,11],you:[1,2,3,4,5,6,7,9,10,13,15],your:[1,2,3,4,5,6,7,8,10,12,13,15],yourself:3,yum:6,zec_btc:9,zec_eth:9,zec_usdt:9,zec_xmr:9,zero:3,ziplin:[0,2,3,5,10,12,15],zipline_root:[2,10],zlib:6,zrx_btc:9,zrx_eth:9},titles:["API Reference","Catalyst Beginner Tutorial","Data Bundles","Development Guidelines","Example Algorithms","Features","Install","Catalyst & Jupyter Notebook","Live Trading","Naming Convention","Release Process","Release Notes","Resources","Utilities","Videos","Features"],titleterms:{"3rd":12,"__version__":10,"default":2,"function":0,"new":2,access:1,adjustment_writ:2,algorithm:[0,1,4,7,8],amazon:6,ami:6,api:[0,12],asset:0,asset_db_writ:2,authent:8,avail:2,averag:1,backtest:[0,2,14],basic:1,bdist:10,beginn:1,branch:3,bug:11,bui:4,build:11,built:0,bundl:[0,2],cach:[0,2],calendar:[0,2],cancel:0,catalyst:[1,7],command:[0,1],commiss:0,commit:[3,10],conda:[6,10],content:5,contribut:3,control:0,convent:9,creat:3,cross:1,csv:13,currenc:8,daily_bar_writ:2,data:[0,1,2,13],dev1:11,dev2:11,dev3:11,dev4:11,dev5:11,dev6:11,dev7:11,dev8:11,dev9:11,develop:3,discov:2,doc:3,docstr:3,document:[10,11],dual:1,end_sess:2,engin:0,environ:[2,3],exampl:[1,4],exchang:8,extract:13,factor:0,factori:2,featur:[5,15],file:[10,13],first:1,fix:11,format:3,get:6,git:3,gnu:6,guidelin:3,help:6,histori:1,hodl:4,ingest:[1,2],instal:[6,7,14],interfac:1,jupyt:7,line:[0,1],linux:6,live:8,loader:0,maco:[6,14],market:13,matplotlib:6,mean:4,messag:3,metadata:0,minute_bar_writ:2,mirror:2,miscellan:0,model:0,move:1,name:9,next:[1,10],note:[6,10,11],notebook:7,object:0,old:2,order:0,output:13,output_dir:2,over:1,packag:10,paramet:0,parti:12,pip:6,pipelin:0,polici:0,previou:1,price:1,process:10,pypi:10,python:10,quandl:2,quantopian:2,reader:0,refer:0,relat:12,releas:[10,11],requir:6,resourc:12,revers:4,run:[0,1,2,7],schedul:0,sdist:10,show_progress:2,simul:0,slippag:0,start_sess:2,step:1,strategi:14,structur:3,stub:10,support:8,symbol:8,tabl:5,trade:[0,8],troubleshoot:6,tutori:1,updat:10,upload:10,util:[0,13],version:11,video:14,virtualenv:6,wiki:2,window:[6,14],work:1,write:2,writer:0,yahoo:2}})
\ No newline at end of file
+Search.setIndex({envversion:46,filenames:["appendix","beginner-tutorial","bundles","development-guidelines","example-algos","index","install","jupyter","live-trading","naming-convention","release-process","releases","resources","utilities","videos","welcome"],objects:{"zipline.data.bundles":{bundles:[0,0,1,""]}},objnames:{"0":["py","data","Python data"]},objtypes:{"0":"py:data"},terms:{"000000e":1,"1000th":7,"15t":4,"1st":1,"328842e":1,"340mb":11,"380954e":1,"40mb":11,"460mb":11,"505275d6646a41f3856b22b16678d":1,"536708e":1,"5min":[4,7],"650729e":1,"7869f7828fa140328eb40477bb7d":1,"998236e":1,"998677e":1,"999120e":1,"999558e":1,"99mb":11,"__file__":13,"__main__":[1,4],"__name__":[1,4],"__wrapped__":10,"_tkinter":1,"boolean":[2,8],"case":[1,2,3,6,13],"class":[3,10],"default":[],"export":10,"final":[1,2,3],"float":[1,11],"import":[1,2,4,7,10,13],"int":2,"long":[1,2,4],"new":[],"public":11,"return":[1,4,8,10,11,12],"short":[1,3,4],"static":10,"throw":11,"true":[1,4,7,8],"try":[4,6],"var":1,"while":[6,10,11],aapl:2,abil:2,abl:[1,2,6],about:[1,2,5,6,15],abov:[1,3,4,6,8,9,10],accept:[2,6,10],accord:10,accordingli:[1,4],account:[2,4,5,7,11,15],acquir:[2,6],across:[5,9,11,15],activ:[6,10],actual:7,add:[1,2,3,6,10,13],addit:[1,3,5,6,11,15],address:10,adjust:[2,11],administr:6,advantag:6,afford:[4,7],aforement:1,after:[1,2,4,6,7,10],again:1,against:[1,5,8,11,15],agre:4,ahead:1,aim:12,algebra:6,algo:[1,2,4,11],algo_namespac:[1,4,8],algo_volatil:[1,7],algofil:[1,2],algorith:1,algorithm_period_return:[1,4,7],algotext:1,alia:4,alias:4,all:[0,1,2,3,4,5,6,7,8,9,10,11,15],allow:[1,2,5,6,15],along:2,alongsid:1,alpha:[1,4,6,7],alreadi:[1,2,3,6,7],also:[1,2,3,4,5,6,7,8,10,15],altern:[1,6,9],although:1,alwai:[2,8,9,10],amount:[1,4,7,11],amp_btc:9,anaconda:[1,6,10],analog:1,analysi:[1,4,5,10,11,12,15],analyst:12,analyt:[5,6,15],analyz:[1,4,7,8,11,13],ani:[1,2,4,6,7,9,10,13],anonym:2,anoth:[1,2,4,7],anymor:1,anyth:[1,6,10],apach:4,appar:1,appear:[2,10],append:10,appli:1,applic:[1,4],appropri:[1,3,4],approxim:[4,7],appveyor:10,apt:[1,6],arang:[1,4],arbitrari:8,arbitrarili:1,arch:6,architectur:1,ardr_btc:9,arg:[1,10],argument:[0,1,2,7,8,10],argv:13,around:[5,10,15],arrai:[4,6],art:[5,15],articl:3,ask:[1,3],assess:1,asset_nam:[4,7],assetdbwrit:2,assign:[1,8],assimil:1,assist:6,assum:[1,3,6],atla:6,attempt:[2,8],attribut:[4,10],auth:[8,11],auto:11,avail:[],avoid:[1,2,4],awar:10,ax1:[1,4,7],ax2:[1,4,7],ax3:[1,4,7],ax4:[1,4,7],ax5:[4,7],ax6:[4,7],axhlin:4,back:[3,6,9],backend:6,bah:4,bar:[1,4,11],bar_count:[1,4],base:[1,2,4,5,6,7,8,14,15],base_curr:[1,4,8,9,13],base_pric:[1,4],basenam:13,basi:[4,11],batch:6,batteri:1,bch_btc:9,bch_eth:9,bch_usdt:9,bcn_btc:9,bcn_xmr:9,bcolz:2,bcolzdailybarread:2,bcolzdailybarwrit:2,bcolzminutebarread:2,bcolzminutebarwrit:2,bcy_btc:9,be62ff77760c4599abaac43be9cc9:1,bear:[1,4],beautifi:1,becaus:[6,7,10,11],been:[0,1,2,6,10],befor:[1,2,4,6,8,11],before_trading_start:[0,4],begin:[1,4,6],behavior:0,bela_btc:9,believ:1,below:[1,4,6,7,13],benchmark:[4,5,7,11,15],benchmark_period_return:[1,4,7],benchmark_volatil:[1,7],benefit:1,best:[3,5,6,15],beta:[1,4,7],better:1,between:[1,3,4,5,9,15],bia:1,big:6,bin:[4,6],binari:[6,10],bit:[3,6],bitcoin:[1,5,8,9,13,15],bitcoin_usd_asset:8,bitfinex:[1,4,5,7,8,11,15],bittrex:[1,4,5,8,11,15],blablabla:[],bld:3,blk_btc:9,blk_xmr:9,blockchain:9,blotter:13,blue:1,bodi:3,book:1,both:[1,3,8,9,10],bought:1,bound:1,breakdown:8,brew:6,brother:6,brows:6,browser:[3,7,10],btc:8,btc_usd:[1,4,7,8,9],btc_usdt:[4,5,9,13,15],btcd_btc:9,btcd_xmr:9,btm_btc:9,bts_btc:9,bug:[2,3],bui:[],build:[3,6,10],build_ext:3,burst_btc:9,button:[6,10],buy_and_hodl:[4,11],buy_btc_simpl:[1,4],buy_btc_simple_out:[1,4],buy_df:[1,4],buy_low_sell_high:11,buyt_and_hodl:[],calcul:[1,3,4,8],call:[1,2,3,4],can:[1,2,3,4,5,6,8,9,10,11,13,15],can_trad:[1,4,11],cancel_ord:[4,7],candl:[1,9,11],candle_s:4,cannot:[1,4,6],canon:3,capit:[1,4,7],capital_bas:[1,4,11,13],capital_us:[1,7],captur:1,cash:[1,2,3,4,7,11],catalyst_dev:[1,5,6,15],caus:[0,1,2,3],cell:7,cert:11,certian:0,chanc:1,chang:[1,3,4,5,6,7,10,11,15],channel:[1,5,6,15],charact:3,charg:1,chart:[1,4,6],check:[1,2,3,4,6,7,8,9],checker:10,checkout:[3,10],choic:10,choos:[1,4,6,9,10,13],chosen:[1,13],chunk:[1,11],circumv:6,clam_btc:9,classic:[1,4],classifi:1,clean:[2,6,10,11],clear:2,cli:[1,4,7,11,13],click:[6,10],client:8,clone:3,close:[1,4,7,13],cmd:[1,6],code:[1,4,6,10,11,13],codebas:3,coin:[7,11],collect:[1,2,4],color:[4,7],column:[1,2,7],com:[1,2,3,8],combin:[6,8],come:[2,6],comment:1,common:1,commonli:1,commun:[6,12],comp:4,compar:[1,4,5,15],comparison:11,compat:[5,11,15],compil:[6,10,11],complement:4,complet:8,complex:[1,6],complianc:4,complimentari:13,comprehens:11,compress:[1,11],comput:[1,4,6,11,12],concept:1,conda:[],conda_build_matrix:10,condit:4,config:6,configur:[1,6,11],congratul:6,consid:[1,4],consist:[1,9],constant:7,constraint:2,consum:10,contain:[1,2,3,6,7],content:[],context:[1,4,7,13],continu:1,continuum:6,conveni:1,convent:8,convers:2,convert:2,copi:[1,2,3,4,10],copyright:4,core:6,correct:[2,6,8,10],correctli:[1,6,10],correctwai:6,correspond:[1,6,8,13],cost:[1,4],could:[0,1,2,4,6,7,13],count:2,coupl:1,cover:[1,4,13],coverag:[5,8,9,15],cpython:6,crash:2,creat:2,creation:11,crossov:[],crowd:12,crypto:[1,5,11,15],cryptoasset:[1,4,13,14],cryptocurr:[4,9],csv:7,csvfile:13,csvwriter:13,cumul:11,cumulative_capital_us:3,curat:[1,5,15],currenc:[],current:[0,1,2,4,6,7,8,10,11,13],current_dai:4,current_dt:[4,13],custom:[1,2,13],cvc_btc:9,cvc_eth:9,cython:10,d6dca79513214346a646079213526:1,dai:[1,2,4,7,10],daili:[1,2,4,5,9,11,13,15],darkgoldenrod:4,dash:8,dash_btc:9,dash_usdt:9,dash_xmr:9,data_frequ:[1,4,13],databas:2,datafram:[1,2,4,5,7,12,13,15],dataframe_cach:2,dataset:[1,2],date:[1,2,4,6,10,11,13],datetim:13,dcr_btc:9,debian:[1,6],debug:10,decid:10,decim:11,decor:10,decreas:4,def:[1,4,7,13],defin:[1,4,7,8],delai:1,delet:2,demonstr:1,denomin:7,dep:3,depend:[1,3,6,10,11,13],deploi:10,deprec:3,deriv:6,descript:[3,6],desir:[7,13],desktop:9,detail:[4,5,15],determin:4,dev1:6,dev2:6,dev3:6,dev4:6,dev5:6,dev6:6,dev8:6,dev9:6,dev:[3,6,9],devel:6,develop:[],devis:1,dgb_btc:9,dictionari:11,did:[5,15],didn:6,differ:[1,2,4,6,8,9,10,13],dir:6,directli:[1,2,6,11,13],directori:[1,2,3,4,6,8,10],disabl:11,disablemsi:6,discord:[1,3,5,6,15],discuss:1,disk:11,dismiss:1,displai:[1,4,6,7,10,11],dist:10,distribut:[4,6,10],distutil:10,divid:3,dividend:2,dma:1,dname:1,dnf:6,doc:2,docker:3,dockerfil:3,document:[3,6,8],doe:[2,4,6,7,9],doesn:2,doge_btc:9,dollar:9,don:[1,3,7,14],done:[1,4,7,10],down:[1,4,14],download:[1,2,6,7,11],draft:10,drawback:2,drive:1,driven:[1,5,15],dropbox:11,dual_moving_averag:[1,4],due:[],dword:6,each:[1,2,3,4,5,6,8,9,11,13,15],earlier:[1,2,3,4],earliest:4,eas:[5,15],easi:[1,2,7,12],easier:[1,2,9],easiest:6,easili:[1,5,6,15],echo:6,eco:[5,15],edit:[3,4,6,10],editor:6,educ:1,educt:1,either:[1,4,6],elaps:4,elif:[1,4],els:6,emc2_btc:9,empow:[1,5,15],empti:[1,2,3,4,8,10,11],enabl:8,encount:6,end:[1,4,7,11,13],end_dat:1,ending_cash:[1,7],ending_exposur:[1,7],enh:3,enhanc:3,enigma:[1,4,5,6,8,9,15],enigmampc:[1,3],enough:[1,6],ensur:[0,6,8,10],ensure_directori:4,enter:[1,6],entir:3,entri:[1,6],env:[4,6],enviorn:2,enviro:6,environ:[],environemnt:[6,7],equal:[2,4,7,13],equiti:2,error:[1,3,4,6,7,8,9,11],especi:1,establish:[5,15],estim:1,etc:[3,10,11],etc_btc:9,etc_eth:9,etc_usdt:9,eth:[1,8],eth_btc:[8,9],eth_usdt:9,ether:[],ethereum_bitcoin_asset:8,evalu:1,even:[2,6],event:1,eventu:1,everi:[1,6,7],everyth:[1,2],exact:[4,13],examin:1,excel:6,except:[1,4],exchang:2,exchange_algorithm:1,exchange_nam:[1,4,8,13],execut:[0,1,4,7,8,11],exist:[2,3,5,6,15],exit:[1,4,10],exit_success:10,exp_btc:9,expect:[0,2,6,7,9,10],experi:6,experienc:6,explain:[6,8],explicitli:10,explictili:6,express:[1,4,5,15],extend:1,extens:[2,3,6],extern:[1,4,6],extra:10,extract_transact:[1,4],facto:7,fail:[2,6,7],failur:2,fairli:[1,3],fals:[4,7],familiar:3,fantast:1,far:2,fast:2,fatal:6,fct_btc:9,featur:[],fedora:6,feedback:2,feel:[1,7],fetch:[2,9,11],few:[1,2,10],fewer:6,field:[2,4,10],file:[2,3,6,7,8],filenam:[1,13],fill:1,filter:11,financ:7,financi:[1,11],find:[1,2,6,10],fine:10,finish:1,fix:3,flag:[1,4,6,8,10],flake8:3,fldc_btc:9,flo_btc:9,floor:4,focu:[1,5,15],folder:[4,6,11],follow:[0,1,2,3,4,6,7,8,9,10,13],footprint:6,fork:12,form:[1,9],format:2,fortran:6,forward:2,foster:12,found:[1,3,6,9],fourth:[1,4],fraction:11,frame:[1,4],free:[1,7],freelanc:12,freetyp:6,freq:[1,4],frequenc:[1,4,11],fresh:10,from:[0,1,2,3,4,6,7,9,10,11,13],full:[1,7,13],fund:12,fundament:12,further:[1,4,5,15],futur:[1,2],game_btc:9,gas_btc:9,gas_eth:9,gave:1,gcc:6,gcf:[4,7],gen_type_stub:10,gener:[2,3,5,6,8,10,11,13,15],get:[2,3],get_open_ord:[1,4,7],get_ylim:[1,4],gettempdir:4,gfortran:6,github:[1,3,6,10],give:4,given:[1,2,9,13],global:1,gno_btc:9,gno_eth:9,gnt_btc:9,gnt_eth:9,goe:[4,8,14],good:[1,10],goog:2,got:1,govern:4,grain:10,graph:7,grc_btc:9,green:[1,4],group:[1,3],grow:2,guid:[3,6,11],gzip:10,hand:3,handi:[1,4,6],handl:[3,4,11],handle_data:[0,1,4,7,8,13],hang:6,happen:[1,2],happi:10,hard:1,hash:11,have:[0,1,2,3,5,6,7,10,15],haven:1,head:[1,6,7],header:[6,10],heavi:[1,4],heavili:12,hedg:12,hei:[],held:9,help:2,henc:1,here:[1,2,6,7,8],hidden:10,high:[1,8,12,13],highest:10,hint:[6,10],histor:[1,4,5,11,15],hit:[1,11],hitchhik:6,hkey_local_machin:6,hold:[4,8],home:11,homebrew:6,hope:1,hopefulli:[4,14],how:[1,2,4,6,7,8],howev:[8,10],html:[3,4,10],http:[1,4,8,10],huc_btc:9,idea:[1,2,3],illustr:8,immedi:[1,4],immut:0,impact:11,imper:3,implement:[1,2,4,11],impli:4,implicitli:0,importerror:1,improv:[3,11],inc:4,includ:[1,2,3,4,6,10,13],incomplet:2,inconsist:8,increas:[2,4,11],increment:[1,10],independ:6,index:[1,3,4,7,10],indic:[2,4,6],individu:[1,8],infer:2,influenc:1,info:[1,4,7],inform:[0,1,2,6,10],initi:[0,1,4,7,8,11,13],inlin:7,inplac:3,input:[5,7,9,15],insid:[1,6,7],insight:[1,5,15],inspect:[1,4],instal:3,installt:6,instanc:[0,2,4],instead:[1,2,3,4,7,9,11],instruct:[1,3,6],integ:[2,11],integr:[5,15],intend:[1,3,10],interact:7,intern:[2,6],interpret:[4,7,13],interv:4,introduc:[1,4,8,9,11],invest:[1,5,15],invok:[1,2],involv:[2,6],ipython:7,is_bui:[4,7],issu:[1,3,6,9,10,11],iter:[1,2,13],itself:1,jan:1,join:[4,5,6,15],json:[8,11],juli:13,jump:6,jupyt:[],just:[1,2,4,7,9,10],keep:[1,2,4,6],kei:[2,5,6,8,15],kept:1,keyerror:11,kind:4,know:7,knowledg:[5,15],kwarg:10,label:[1,4,8,10],lack:9,languag:4,lapack:6,larg:2,larger:11,last:[1,2,4,6,7,11],later:[1,2,3,4],latest:[10,11],launch:[6,7],law:4,layer:9,lazi:2,lbc_btc:9,leak:2,learn:[1,5,6,15],least:[1,3],legend:[4,7],legend_:[1,4],len:[1,4],less:2,let:[1,4,7],level:[1,2,4],leverag:[4,7,12],lib:4,libatla:6,libfreetype6:6,libgfortran:6,librari:[1,3,4,5,6,11,12,15],licens:4,lifetim:2,like:[1,2,3,5,6,9,10,15],limit:[1,4,9,11],limit_pric:[4,7],linear:6,linter:10,linux:[],list:[0,2,6,9,10,13],littl:[1,3],live:6,live_algo:4,live_graph:4,load:[1,2,7],load_ext:7,loc:[1,4,7],local:[1,2,3,6,7,10],locat:[1,2,13],log:[1,4,6],logbook:[1,4],logger:[1,4],logic:[1,4,11],long_mavg:[1,4],long_window:[1,4],longer:[1,3,10],look:[1,2,4,7,10,13],lookup:1,loop:2,loss:11,lot:2,low:[1,8],lower:11,lowercas:[8,9],lsk_btc:9,lsk_eth:9,ltc:8,ltc_btc:9,ltc_usd:[1,4],ltc_usdt:9,ltc_xmr:9,machin:[2,5,10,15],maco:[],made:[2,3],magic:[1,7],mai:[1,2,4,6,10],maid_btc:9,maid_xmr:9,main:[1,6,10],maint:3,maintain:[9,10],mainten:3,major:10,make:[1,2,3,4,6,7,9,10],manag:[1,4,6,10],mani:[1,2,4,6,10,12],manifest:10,manner:8,manual:[6,10],map:[0,2,9],marker:[1,4],markers:7,market:[8,9],market_curr:9,marketplac:1,master:10,match:[1,6,8,10],matplotlib:[],matplotlibrc:6,matrix:10,matter:3,mavg:1,max_capital_us:3,max_leverag:3,maxim:[5,15],maybe_show_progress:2,mcoin:[4,7],mean:2,mean_reversion_simpl:4,memori:2,mention:[1,6,10],menu:6,merg:1,merger:2,messag:[],method:[0,1,2,4,6,10,11,13],metric:[1,11],micro:10,microsoft:6,might:1,migrat:1,min:4,mind:[1,4],miniconda:6,minim:[5,15],minimum:11,minor:10,minut:[1,2,4,5,6,11,13,15],miss:[1,6,8,11],mkvirtualenv:3,mode:[1,4,5,8,11,15],modif:[3,8],modifi:13,modul:1,moment:[6,10],momentum:[1,4,14],monei:0,month:[10,13],more:[0,1,2,4,5,6,11,13,15],most:[1,2,4,6,7,8,11],mostli:1,movement:1,mpc:[1,4],msft:2,msi:6,msiexec:6,much:[1,2],multipl:[2,10,11],must:[1,2,8,10],my_algo_cod:8,my_algo_nam:8,name:[2,3,6,7,8],namespac:[1,4,10],nan:[1,7],nano:10,nativ:6,naut_btc:9,nav_btc:9,navig:[3,6],nchang:4,ndarrai:1,necessari:6,nee:6,need:[1,2,3,4,6,9,10,12,13],neg:1,neo:4,neo_eth:[4,8],neo_ethereum_asset:8,neo_usd:4,neos_btc:9,never:2,newer:2,nice:[5,15],nmc_btc:9,non:6,none:[1,4,7,13],nor:4,normal:11,note:[],note_btc:9,notebook:[],noth:6,notic:4,notion:4,novemb:10,now:[1,2,4,6,10,11],number:[1,2,4,6,10,11],numer:6,numpi:[1,3,4,6,10,12],nvalu:4,nxc_btc:9,nxt_btc:9,nxt_usdt:9,nxt_xmr:9,observ:6,obtain:[1,4],occur:[1,8],off:12,offer:1,offset:4,ohlc:1,ohlcv:11,older:2,omg_btc:9,omg_eth:9,omni:9,omni_btc:9,onc:[1,2,4,6,7,10],onli:[0,1,2,3,4,5,6,10,13,15],open:[1,3,6,7,11,13],openssl:6,oper:6,operatbl:6,opt:4,optim:[1,12],option:[1,2,6,13],order_id:1,order_target_perc:[1,4],order_target_valu:[4,7],ordered_pip:3,org:[4,10],organ:1,origin:[1,10],osx:10,other:[1,2,4,6,9,10,13],otherwis:6,our:[1,3,4,5,6,10,15],out:[1,2,3,4,5,6,7,10,15],outdat:6,outlin:6,output:[2,7],outstand:[4,7],overcom:9,overfit:1,overrid:[6,10],overview:[9,15],overwhelm:1,own:[2,6,8],packag:[6,7],pacman:6,page:[3,6,10,11],pair:[1,4,7,8,9,11],pairon:4,panda:[1,2,4,5,12,15],paper:3,parent:6,pars:2,part:[1,2,4,6,8],partial:6,particular:[5,6,15],pasc_btc:9,pass:[1,2,4,7,10],password:10,past:1,path:[2,4,6,11,13],pend:10,peopl:3,pep8:3,per:[1,2,4,11],percent:[1,4,7],percentag:[1,4],perf:[1,3,4],perform:[0,1,3,4,5,6,7,11,12,15],period:[3,4],permiss:[4,6],persist:[1,4,11],pickl:[1,4],piec:[2,6],pink_btc:9,pip:3,pkg:6,place:[1,4,7,11],platform:[6,11,12],pleas:[1,5,6,13,15],plot:[1,4,7,12],plt:[1,4,7],plu:13,png:7,point:[1,9,10],poloniex:[1,4,5,7,8,9,11,13,15],popul:10,portfolio:[1,4,7,11,13],portfolio_valu:[1,4,7],pos_amount:[1,4],posit:[1,4,7,11],possibl:[2,3,6],post:10,pot_btc:9,power:[1,4,7,12],ppc_btc:9,practic:[1,3],pre:[2,6],precis:11,predict:[1,8],prefer:6,prefix:3,preload:2,prepare_chunk:11,preprocess:10,prerequisit:[1,6],present:1,preserv:11,prevent:[2,6,10],previous:1,price_chang:[1,4],primari:6,print:[1,4,6,10],print_result:1,prior:[1,4],privileg:6,probabl:1,problem:[1,2,6,10],proce:6,proceed:6,process:[2,8],produc:[2,4,6],profit:[1,5,15],program:6,progress:2,project:[5,6,12,15],prompt:[1,6],proper:6,properli:[1,4,6,13],protect:0,protocol:[1,9],provid:[0,1,2,5,6,7,8,11,12,13,15],publish:10,pull:[3,10],pun:1,purchas:[4,7],purpos:[1,8],push:10,put:8,pycharm:10,pydata:[4,5,15],pyfolio:11,pypirc:10,pypitest:10,pyplot:[1,4,7],python2:[6,11],python3:11,python:[3,6,7],pytz:13,quandl_api_kei:2,quandl_download_attempt:2,quantit:[7,12],queri:2,question:[1,3,5,15],quick:1,quickli:[4,14],quirk:6,quit:2,rads_btc:9,rais:3,ran:2,rang:[1,2,4],rather:[1,6],raw:[2,6],read:[1,2,6],read_pickl:1,readi:10,real:[0,4],realist:[1,4],reason:[1,2,6],rebalanc:1,recal:1,receiv:[1,2],recent:[1,2,4,6],recogn:6,recommend:[2,6],reconstruct:1,record:[1,4,7,13],red:[1,4],redhat:6,redon:11,redownload:[2,7],reduc:11,ref:[],refactor:3,referenc:8,refus:7,regard:[5,15],regardless:[6,7,8],regedit:6,regist:[0,2,7],registri:6,regular:6,rel:3,relat:3,relationship:2,releas:[3,6],reli:12,remain:11,rememb:6,remot:2,remov:[1,3,4,6,10,11],renam:10,rep:6,rep_btc:9,rep_eth:9,rep_usdt:9,report:[1,3,6],repositori:[6,10,11],repres:[2,8],reproduc:2,request:[1,2,3,4],requir:3,requirements_blaz:3,requirements_dev:3,requirements_doc:3,research:7,reserv:[4,7,9],reserve_ratio:[4,7],reserve_valu:[4,7],resolut:[1,4,5,11,13,15],resourc:2,respect:[3,10,13],respons:2,rest:2,restart:11,restrict:6,restructuredtext:3,result:[1,2,4,6,7,8,13],resum:4,retri:2,retriev:[4,7,11],rev:3,revert:3,review:[1,6],revis:1,rhel:6,ric_btc:9,ride:[4,14],right:6,risk:[1,11],roll:1,rollup:2,root:[3,10],routin:6,row:[1,7],rsi:4,rsi_overbought:4,rsi_oversold:4,rst:[3,10],run_algo:[1,13],run_algorithm:[1,4,8,13],runtim:1,safe:1,said:1,same:[1,2,4,6,7,8,10,11,13],sampl:11,satisfi:6,save:[1,2,3,4,6,13],sbd_btc:9,sc_btc:9,scale:[7,11],scatter:[1,4],scientif:12,scikit:1,scipi:[5,6,15],scratch:6,script:[1,10,13],scriptnam:13,seamless:[5,15],search:6,second:[1,4,6],secret:8,section:[1,3,4,6,8,10,13],secur:[4,5,12,15],see:[0,1,2,4,5,6,8,13,15],seek:6,seen:4,select:6,self:0,sell:[1,4,8,11,12,14],sell_df:[1,4],separ:[1,3,6,8,9],seper:8,seri:1,seriou:1,server:[1,2,7,10],servic:2,session:6,set:[1,2,4,6,11],set_size_inch:[4,7],set_tick:[1,4],set_ylabel:[1,4,7],setup:[3,7,10],setuptool:6,sever:[1,5,6,15],share:[1,5,15],sharex:[1,4,7],sharp:1,ship:[2,6,10],short_exposur:1,short_mavg:[1,4],short_valu:1,short_window:[1,4],shorter:1,shorts_count:1,should:[0,1,2,3,6,8,10],shourc:2,show:[1,2,4,7],shown:2,sid:[2,7,11],signal:2,signatur:2,signific:4,similar:[1,6,8],simpl:14,simpler:13,simplest:4,simpli:[1,3,6,13],simplifi:1,simultan:11,sinc:[1,4,6,7,10,13],singl:[2,4,6,11],size:[4,6,11],sjcx_btc:9,skeleton:10,skim:1,skip:[1,4],sklearn:[5,15],slighlti:4,slightli:6,small:[],smaller:6,smoothli:14,snip:7,snippet:13,softwar:[4,6],solut:6,solv:[1,2,6],some:[1,2,3,4,6,8,11,12],someon:6,someth:3,somewhat:1,sortino:[1,11],sourc:[1,2,3,4,6,10,12],space:7,special:8,specif:[1,4,11],specifi:[1,2,4,7,8,10],spend:1,spent:9,sphinx:[3,10],split:[1,2],splitext:13,spring:12,sqliteadjustmentwrit:2,ssl:11,stabl:[4,6],stai:10,standard:[2,3,9,11],start:[1,2,3,4,5,6,7,8,13,15],start_dat:1,start_tim:4,starting_cash:[1,4,7],starting_exposur:[1,7],starting_valu:[1,7],stat:[4,11],state:[1,2,4,5,11,15],statist:[1,5,8,11,15],stats_util:[1,4],statsmodel:[5,15],statu:[4,8],stdout:1,steem_btc:9,steem_eth:9,still:[1,2,4,6,7],stock:[1,2],stop:[4,7,11],stop_pric:[4,7],storag:[1,8,11],store:[1,2,9,13],str_btc:9,str_usdt:9,straightforward:4,strat_btc:9,strategi:[],stream:1,strftime:4,strictli:[2,6],string:[2,7,10],strongli:6,sty:3,style:[3,4],subdirectori:2,subject:3,submit:3,subplot:[1,4,7],substanti:1,succe:10,succeed:7,success:[2,3],sudo:[1,6],suffici:6,suggest:3,summar:6,summari:11,suppli:[1,7],support:[6,7],suppos:[1,7],sure:[4,6],surpris:1,suspect:3,symbol:[2,7],symbolnotfoundonexchang:9,sync:10,syntax:[10,11],sys_btc:9,system:[1,3,5,6,15],tag:10,take:[1,2,6,7,11],taken:10,talib:4,tar:10,tarbal:10,target:[1,8],target_hodl_ratio:[4,7],target_hodl_valu:[4,7],technic:[4,5,15],tempfil:4,templat:10,temporari:10,ten:1,tend:8,tens:3,term:1,termin:[1,4,6],test:[1,3,10,11,12],testpypi:10,tether:9,text:1,than:[1,2,3,6],thei:[1,2,10,11,12],them:[1,3,6,10],therefor:10,therein:6,thi:[0,1,2,3,4,6,7,8,9,10,13,14],thing:14,third:[1,4],those:[1,3,4,10],though:2,three:[1,2,4,5,15],threshold:[4,7],through:[0,1,2,6,7],throughout:1,thu:[1,4,6,7],tick:4,tick_siz:7,ticker:2,time:[1,2,4,5,6,7,10,13,15],timeperiod:4,timeseri:4,timestamp:[1,2,11],timestr:4,titl:10,tkagg:6,to_csv:13,to_datetim:[1,4],to_pydatetim:[1,4],todai:[4,10],togeth:1,token:[8,13],tool:[2,3,6,10,12],top:[1,5,10,15],total:2,toward:1,traceback:9,track:[1,3,4,11],tracker:1,traded_todai:4,trader:[1,12],trading_dai:[1,7],tradingalgorithm:[0,10],tradingcalendar:2,tradit:1,train:1,tran:[4,7],transact:[1,4,7,11],transaction:2,transaction_df:[1,4],transfer:9,transform:1,transit:[5,15],travi:10,treasuri:[4,7],treasury_period_return:[1,4,7],trend:1,tri:[1,5,15],trigger:4,tst:3,tupl:2,turn:10,tweak:1,twice:10,two:[1,4,5,6,13,15],twoargument:1,txt:[3,6,10],type:[4,6,10],typo:3,ubuntu:[1,6],uncompress:11,under:[1,2,4,10],underli:1,underlin:10,underscor:9,understand:[1,6],undesir:0,unexpect:6,unit:[1,9,11],univers:[1,8],unknown:7,unless:4,unlik:2,unpack:6,unregist:0,unresolv:11,untar:2,until:[1,4],unus:3,updat:[],upgrad:[6,10],upper:[1,4],upward:1,url:10,usag:1,usd:[1,4,7,9],usdt:[4,9,13],usdt_btc:7,usdt_btc_benchmark:7,user:[1,2,5,6,7,9,10,15],usernam:10,usr:4,usual:1,utc:[1,4,13],utilit:13,valid:11,valu:[1,4,6,7,8,11],vari:[6,13],variabl:[1,2,4,7,13],varieti:13,variou:[1,2,4],varnam:1,vcforpython27:6,venv:6,veri:[1,2,4,6,7,10],verifi:[6,10],versatil:13,version:[6,10],via:[1,6,7,9],via_btc:9,viabl:9,victori:9,video:[],view:[3,10],virtual:6,virtualenvwrapp:3,visit:[4,5,15],visual:[1,4,5,6,15],volum:[1,4,5,7,9,11,13,15],volumeshareslippag:7,vrc_btc:9,vtc_btc:9,wai:[1,2,5,6,7,15],wait:[1,4],want:[1,2,3,4,7,9],warn:[7,10,11],warranti:4,wave:[4,14],web:10,weight:4,welcom:3,well:[1,2,5,6,15],were:[3,4,10],what:[1,3,4,6,8,10],whatev:2,whatsnew:10,wheel:[6,10],when:[0,1,2,3,4,6,8,10,14],where:[1,2,3,4,5,6,8,9,13,14,15],which:[1,2,3,4,6,7,8,10,11,13],whitepap:[5,12,15],whitespac:3,who:3,whole:1,why:3,width:10,win:10,window:[],within:[6,7],without:[2,4,6,7,8,11],workaround:11,world:1,wors:1,worth:1,would:[1,2,4,6,10],wouldlik:1,wrap:10,write:[],writerow:13,written:[1,2,5,9,15],wrong:9,www:[4,8],xbc_btc:9,xbt:8,xcp_btc:9,xem_btc:9,xmr_btc:9,xmr_usdt:9,xpm_btc:9,xrp_btc:9,xrp_usdt:9,xvc_btc:9,yahoo_equ:2,yaxi:[1,4],year:10,yet:1,yml:[6,11],you:[1,2,3,4,5,6,7,9,10,13,15],your:[1,2,3,4,5,6,7,8,10,12,13,15],yourself:3,yum:6,zec_btc:9,zec_eth:9,zec_usdt:9,zec_xmr:9,zero:3,ziplin:[0,2,3,5,10,12,15],zipline_root:[2,10],zlib:6,zrx_btc:9,zrx_eth:9},titles:["API Reference","Catalyst Beginner Tutorial","Data Bundles","Development Guidelines","Example Algorithms","Features","Install","Catalyst & Jupyter Notebook","Live Trading","Naming Convention","Release Process","Release Notes","Resources","Utilities","Videos","Features"],titleterms:{"3rd":12,"__version__":10,"default":2,"function":0,"new":2,access:1,adjustment_writ:2,algorithm:[0,1,4,7,8],amazon:6,ami:6,api:[0,12],asset:0,asset_db_writ:2,authent:8,avail:2,averag:[1,4],backtest:[0,2,14],basic:1,bdist:10,beginn:1,branch:3,btc:4,bug:11,bui:4,build:11,built:0,bundl:[0,2],buy_and_hold:[],cach:[0,2],calendar:[0,2],cancel:0,catalyst:[1,7],command:[0,1],commiss:0,commit:[3,10],conda:[6,10],content:5,contribut:3,control:0,convent:9,creat:3,cross:1,crossov:4,csv:13,currenc:8,daily_bar_writ:2,data:[0,1,2,13],dev1:11,dev2:11,dev3:11,dev4:11,dev5:11,dev6:11,dev7:11,dev8:11,dev9:11,develop:3,discov:2,doc:3,docstr:3,document:[10,11],dual:[1,4],end_sess:2,engin:0,environ:[2,3],exampl:[1,4],exchang:8,extract:13,factor:0,factori:2,featur:[5,15],file:[10,13],first:1,fix:11,format:3,get:6,git:3,gnu:6,guidelin:3,help:6,histori:1,hodl:4,ingest:[1,2],instal:[6,7,14],interfac:1,jupyt:7,line:[0,1],linux:6,live:8,loader:0,maco:[6,14],market:13,matplotlib:6,mean:4,messag:3,metadata:0,minute_bar_writ:2,mirror:2,miscellan:0,model:0,move:[1,4],name:9,next:[1,10],note:[6,10,11],notebook:7,object:0,old:2,order:0,output:13,output_dir:2,over:1,overview:4,packag:10,paramet:0,parti:12,pip:6,pipelin:0,polici:0,previou:1,price:1,process:10,pypi:10,python:10,quandl:2,quantopian:2,reader:0,refer:0,relat:12,releas:[10,11],requir:6,resourc:12,revers:4,run:[0,1,2,7],schedul:0,sdist:10,show_progress:2,simpl:4,simul:0,slippag:0,start_sess:2,step:1,strategi:14,structur:3,stub:10,support:8,symbol:8,tabl:5,trade:[0,8],troubleshoot:6,tutori:1,updat:10,upload:10,util:[0,13],version:11,video:14,virtualenv:6,wiki:2,window:[6,14],work:1,write:2,writer:0,yahoo:2}})
\ No newline at end of file