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:

    +
    python buy_and_hodl.py
     

    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), + )
    +https://s3.amazonaws.com/enigmaco-docs/github.io/example_buy_and_hodl.png +
    +
    +

    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),
    +        )
    +
    +
    +https://s3.amazonaws.com/enigmaco-docs/github.io/tutorial_dual_moving_average.png

    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 )
    +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.

    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 ded63fcd..4848afe7 100644 Binary files a/objects.inv and b/objects.inv differ diff --git a/releases.html b/releases.html index 846a974f..966379dc 100644 --- a/releases.html +++ b/releases.html @@ -121,7 +121,10 @@
    • 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