├── Eclipse Projects ├── Section 1.zip ├── Section 1 │ ├── main.py │ └── strategies │ │ ├── __init__.py │ │ ├── buy_and_hold.py │ │ └── run_zipline.py ├── Section 2.zip ├── Section 2 │ ├── main.py │ └── strategies │ │ ├── __init__.py │ │ ├── buy_and_hold.py │ │ ├── models │ │ └── rf_regressor.joblib │ │ └── run_zipline.py ├── Section 3.zip ├── Section 3 │ ├── main.py │ └── strategies │ │ ├── __init__.py │ │ ├── auto_correlation.py │ │ ├── buy_and_hold.py │ │ ├── models │ │ └── rf_regressor.joblib │ │ └── run_zipline.py ├── Section 5.zip ├── Section 5 │ ├── extension.py │ ├── main.py │ └── strategies │ │ ├── __init__.py │ │ ├── auto_correlation.py │ │ ├── buy_and_hold.py │ │ ├── calendar.py │ │ ├── models │ │ └── rf_regressor.joblib │ │ ├── run_zipline.py │ │ └── scalping.py ├── Section 6A.zip ├── Section 6A │ ├── extension.py │ ├── main.py │ └── strategies │ │ ├── __init__.py │ │ ├── auto_correlation.py │ │ ├── buy_and_hold.py │ │ ├── calendar.py │ │ ├── models │ │ └── rf_regressor.joblib │ │ ├── run_zipline.py │ │ └── scalping.py ├── Section 6B.zip └── Section 6B │ ├── extension.py │ ├── main.py │ └── strategies │ ├── __init__.py │ ├── auto_correlation.py │ ├── buy_and_hold.py │ ├── calendar.py │ ├── models │ ├── rf_regressor.joblib │ └── sv_regressor.joblib │ ├── run_zipline.py │ └── scalping.py ├── Images ├── 1.png ├── 2.png ├── 3.png ├── 4.png └── 5.png ├── LICENSE ├── Lecture Notebooks ├── Lectures Notebooks.zip └── Lectures Notebooks │ ├── section 0001 │ ├── SEC001 VID004 Fetching and understanding the Dataset.ipynb │ └── SEC001 VID006 Evaluate the Strategy Performance.ipynb │ ├── section 0002 │ ├── SEC002 VID002 Build and Implement Random Forests Algorithm.ipynb │ ├── SEC002 VID004 Evaluate Random Forests Performance.ipynb │ └── rf_regressor.joblib │ ├── section 0003 │ ├── SEC003 VID004 Evaluate the Strategy.ipynb │ └── performance.csv │ ├── section 0004 │ └── SEC004 VID002 Implementing GBoosting using Python.ipynb │ ├── section 0005 │ ├── SEC005 VID003 Evaluate the Strategy.ipynb │ └── scalping.csv │ └── section 0006 │ ├── SEC 0006 VID 0003 Bayesian Value at Risk.ipynb │ ├── SEC 006 VID 0003 Bayesian Value at Risk.ipynb │ ├── SEC006 VID002 Evaluate Scalping Strategy with CVaR.ipynb │ ├── SEC006 VID004 Evaluate Scalping Strategy with CVaR_SVR.ipynb │ ├── SEC006_VID004_Implement_VaR_using_SVR.ipynb │ ├── estimator.joblib │ ├── performance.csv │ ├── scalping-var-svr.csv │ └── scalping.csv ├── README.md ├── buy_and_hold.py ├── packtpub-machine-learning-algo-trading-bots-src-code.zip ├── section 0001 ├── SEC001 VID004 Fetching and understanding the Dataset.ipynb └── SEC001 VID006 Evaluate the Strategy Performance.ipynb ├── section 0002 ├── SEC002 VID002 Build and Implement Random Forests Algorithm.ipynb ├── SEC002 VID004 Evaluate Random Forests Performance.ipynb └── rf_regressor.joblib ├── section 0003 ├── SEC003 VID004 Evaluate the Strategy.ipynb └── performance.csv ├── section 0004 └── SEC004 VID002 Implementing GBoosting using Python.ipynb ├── section 0005 ├── SEC005 VID003 Evaluate the Strategy.ipynb └── scalping.csv └── section 0006 ├── SEC 0006 VID 0003 Bayesian Value at Risk.ipynb ├── SEC 006 VID 0003 Bayesian Value at Risk.ipynb ├── SEC006 VID002 Evaluate Scalping Strategy with CVaR.ipynb ├── SEC006 VID004 Evaluate Scalping Strategy with CVaR_SVR.ipynb ├── SEC006_VID004_Implement_VaR_using_SVR.ipynb ├── estimator.joblib ├── extension.py ├── main.py ├── performance.csv ├── scalping-var-svr.csv ├── scalping.csv └── strategies ├── __init__.py ├── auto_correlation.py ├── buy_and_hold.py ├── calendar.py ├── models ├── rf_regressor.joblib └── sv_regressor.joblib ├── run_zipline.py └── scalping.py /Eclipse Projects/Section 1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 1.zip -------------------------------------------------------------------------------- /Eclipse Projects/Section 1/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from matplotlib import pyplot as plt 3 | import numpy as np 4 | from strategies.run_zipline import run_strategy 5 | import zipline 6 | import os 7 | 8 | 9 | def main(): 10 | zipline_dir = os.path.dirname(zipline.__file__) 11 | print("*** Zipline is installed @ {} ***".format(zipline_dir)) 12 | print("*** PackPub - Hands-on Machine Learning for Algorithmic Trading Bots ***") 13 | print("*** SEC001/VID005: Build the Conventional Buy and Hold Strategy ***") 14 | perf = run_strategy("buy_and_hold") 15 | perf.to_csv("buy_and_hold.csv") 16 | 17 | 18 | if __name__ == '__main__': 19 | main() -------------------------------------------------------------------------------- /Eclipse Projects/Section 1/strategies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 1/strategies/__init__.py -------------------------------------------------------------------------------- /Eclipse Projects/Section 1/strategies/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | 5 | 6 | class BuyAndHold: 7 | 8 | stocks = ['AAPL', 'MSFT', 'TSLA'] 9 | 10 | def initialize(self, context): 11 | context.has_ordered = False 12 | context.stocks = self.stocks 13 | context.asset = symbol('AAPL') 14 | 15 | def handle_data(self, context, data): 16 | if not context.has_ordered: 17 | for stock in context.stocks: 18 | order(symbol(stock), 100) 19 | context.has_ordered = True 20 | 21 | record(AAPL=data.current(context.asset, 'price')) 22 | 23 | def _test_args(self): 24 | return { 25 | 'start': pd.Timestamp('2008', tz='utc'), 26 | 'end': pd.Timestamp('2018', tz='utc'), 27 | 'capital_base': 1e7 28 | } 29 | 30 | def analyze(self, context, perf): 31 | fig = plt.figure() 32 | ax1 = fig.add_subplot(211) 33 | perf.portfolio_value.plot(ax=ax1) 34 | ax1.set_ylabel('portfolio value in $') 35 | 36 | ax2 = fig.add_subplot(212) 37 | perf['AAPL'].plot(ax=ax2) 38 | 39 | ax2.set_ylabel('price in $') 40 | plt.legend(loc=0) 41 | plt.show() 42 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 1/strategies/run_zipline.py: -------------------------------------------------------------------------------- 1 | from toolz import merge 2 | from zipline import run_algorithm 3 | from zipline.utils.calendars import register_calendar, get_calendar 4 | from strategies.buy_and_hold import BuyAndHold 5 | from os import environ 6 | 7 | 8 | # Columns that we expect to be able to reliably deterministic 9 | # Doesn't include fields that have UUIDS. 10 | _cols_to_check = [ 11 | 'algo_volatility', 12 | 'algorithm_period_return', 13 | 'alpha', 14 | 'benchmark_period_return', 15 | 'benchmark_volatility', 16 | 'beta', 17 | 'capital_used', 18 | 'ending_cash', 19 | 'ending_exposure', 20 | 'ending_value', 21 | 'excess_return', 22 | 'gross_leverage', 23 | 'long_exposure', 24 | 'long_value', 25 | 'longs_count', 26 | 'max_drawdown', 27 | 'max_leverage', 28 | 'net_leverage', 29 | 'period_close', 30 | 'period_label', 31 | 'period_open', 32 | 'pnl', 33 | 'portfolio_value', 34 | 'positions', 35 | 'returns', 36 | 'short_exposure', 37 | 'short_value', 38 | 'shorts_count', 39 | 'sortino', 40 | 'starting_cash', 41 | 'starting_exposure', 42 | 'starting_value', 43 | 'trading_days', 44 | 'treasury_period_return', 45 | ] 46 | 47 | 48 | def run_strategy(strategy_name): 49 | mod = None 50 | 51 | if strategy_name == "buy_and_hold": 52 | mod = BuyAndHold() 53 | 54 | register_calendar("YAHOO", get_calendar("NYSE"), force=True) 55 | 56 | return run_algorithm( 57 | initialize=getattr(mod, 'initialize', None), 58 | handle_data=getattr(mod, 'handle_data', None), 59 | before_trading_start=getattr(mod, 'before_trading_start', None), 60 | analyze=getattr(mod, 'analyze', None), 61 | bundle='quandl', 62 | environ=environ, 63 | # Provide a default capital base, but allow the test to override. 64 | **merge({'capital_base': 1e7}, mod._test_args()) 65 | ) 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 2.zip -------------------------------------------------------------------------------- /Eclipse Projects/Section 2/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from matplotlib import pyplot as plt 3 | import numpy as np 4 | from strategies.run_zipline import run_strategy 5 | 6 | 7 | def main(): 8 | print("*** PackPub - Hands-on Machine Learning for Algorithmic Trading Bots ***") 9 | print("*** SEC001/VID005: Build the Conventional Buy and Hold Strategy ***") 10 | perf = run_strategy("buy_and_hold") 11 | perf.to_csv("buy_and_hold.csv") 12 | 13 | 14 | if __name__ == '__main__': 15 | main() -------------------------------------------------------------------------------- /Eclipse Projects/Section 2/strategies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 2/strategies/__init__.py -------------------------------------------------------------------------------- /Eclipse Projects/Section 2/strategies/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | from joblib import load 5 | import numpy as np 6 | 7 | 8 | class BuyAndHold: 9 | 10 | stocks = ['AAPL', 'MSFT', 'TSLA'] 11 | lag = 33 12 | forecast = 8 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol('AAPL') 18 | context.regressor = load('./strategies/models/rf_regressor.joblib') 19 | 20 | def handle_data(self, context, data): 21 | for stock in context.stocks: 22 | timeseries = data.history( 23 | symbol(stock), 24 | 'price', 25 | bar_count=self.lag, 26 | frequency='1d') 27 | np_timeseries = np.array(timeseries.values).reshape(1, -1) 28 | preds = context.regressor.predict(np_timeseries) 29 | max_price = np.max(preds) 30 | historical_mean = np.mean(np_timeseries) 31 | 32 | if max_price > historical_mean: 33 | order(symbol(stock), 1000) 34 | 35 | if max_price < historical_mean: 36 | order(symbol(stock), -1000) 37 | 38 | record(AAPL=data.current(context.asset, 'price')) 39 | 40 | def _test_args(self): 41 | return { 42 | 'start': pd.Timestamp('2017', tz='utc'), 43 | 'end': pd.Timestamp('2018', tz='utc'), 44 | 'capital_base': 1e7 45 | } 46 | 47 | def analyze(self, context, perf): 48 | fig = plt.figure() 49 | ax1 = fig.add_subplot(211) 50 | perf.portfolio_value.plot(ax=ax1) 51 | ax1.set_ylabel('portfolio value in $') 52 | 53 | ax2 = fig.add_subplot(212) 54 | perf['AAPL'].plot(ax=ax2) 55 | 56 | ax2.set_ylabel('price in $') 57 | plt.legend(loc=0) 58 | plt.show() 59 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 2/strategies/models/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 2/strategies/models/rf_regressor.joblib -------------------------------------------------------------------------------- /Eclipse Projects/Section 2/strategies/run_zipline.py: -------------------------------------------------------------------------------- 1 | from toolz import merge 2 | from zipline import run_algorithm 3 | from zipline.utils.calendars import register_calendar, get_calendar 4 | from strategies.buy_and_hold import BuyAndHold 5 | from os import environ 6 | 7 | 8 | # Columns that we expect to be able to reliably deterministic 9 | # Doesn't include fields that have UUIDS. 10 | _cols_to_check = [ 11 | 'algo_volatility', 12 | 'algorithm_period_return', 13 | 'alpha', 14 | 'benchmark_period_return', 15 | 'benchmark_volatility', 16 | 'beta', 17 | 'capital_used', 18 | 'ending_cash', 19 | 'ending_exposure', 20 | 'ending_value', 21 | 'excess_return', 22 | 'gross_leverage', 23 | 'long_exposure', 24 | 'long_value', 25 | 'longs_count', 26 | 'max_drawdown', 27 | 'max_leverage', 28 | 'net_leverage', 29 | 'period_close', 30 | 'period_label', 31 | 'period_open', 32 | 'pnl', 33 | 'portfolio_value', 34 | 'positions', 35 | 'returns', 36 | 'short_exposure', 37 | 'short_value', 38 | 'shorts_count', 39 | 'sortino', 40 | 'starting_cash', 41 | 'starting_exposure', 42 | 'starting_value', 43 | 'trading_days', 44 | 'treasury_period_return', 45 | ] 46 | 47 | 48 | def run_strategy(strategy_name): 49 | mod = None 50 | 51 | if strategy_name == "buy_and_hold": 52 | mod = BuyAndHold() 53 | 54 | register_calendar("YAHOO", get_calendar("NYSE"), force=True) 55 | 56 | return run_algorithm( 57 | initialize=getattr(mod, 'initialize', None), 58 | handle_data=getattr(mod, 'handle_data', None), 59 | before_trading_start=getattr(mod, 'before_trading_start', None), 60 | analyze=getattr(mod, 'analyze', None), 61 | bundle='quandl', 62 | environ=environ, 63 | # Provide a default capital base, but allow the test to override. 64 | **merge({'capital_base': 1e7}, mod._test_args()) 65 | ) 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 3.zip -------------------------------------------------------------------------------- /Eclipse Projects/Section 3/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from matplotlib import pyplot as plt 3 | import numpy as np 4 | from strategies.run_zipline import run_strategy 5 | 6 | 7 | def main(): 8 | print("*** PackPub - Hands-on Machine Learning for Algorithmic Trading Bots ***") 9 | print("*** SEC003/VID003: Implement Statistical Auto Correlation Strategy ***") 10 | perf = run_strategy("auto_correlation") 11 | perf.to_csv("auto_correlation.csv") 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 3/strategies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 3/strategies/__init__.py -------------------------------------------------------------------------------- /Eclipse Projects/Section 3/strategies/auto_correlation.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | from scipy.stats.stats import pearsonr 6 | 7 | 8 | class AutoCorrelation: 9 | 10 | stocks = ['APL', 'MSFT', 'TSLA'] 11 | lag = 1 12 | steps = 3 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol(self.stocks[-1]) 18 | 19 | def handle_data(self, context, data): 20 | # loop stocks in portfolio 21 | for stock in context.stocks: 22 | # fetch history up to steps 23 | s1 = data.history( 24 | symbol(stock), 25 | 'price', 26 | bar_count=self.steps, 27 | frequency='1d') 28 | 29 | # fetch history up to steps + lag and drop extra values 30 | s2 = data.history( 31 | symbol(stock), 32 | 'price', 33 | bar_count=self.steps+self.lag, 34 | frequency='1d').iloc[:-1 * self.lag] 35 | 36 | # convert to numpy arrays 37 | np_s1 = np.array(s1.values) 38 | np_s2 = np.array(s2.values) 39 | 40 | # calculate auto-correlation 41 | corr, hypothesis = pearsonr(np_s1, np_s2) 42 | 43 | # fetch our basket status 44 | cpp = context.portfolio.positions 45 | 46 | # map basket to symbol:shares pairs 47 | cpp_symbols = map(lambda x: x.symbol, cpp) 48 | 49 | # what is today price 50 | curr_price = data.current(symbol(stock), 'price') 51 | 52 | # what was yesterday closing price 53 | last_price = data.history( 54 | symbol(stock), 55 | 'price', 56 | bar_count=2, 57 | frequency='1d').iloc[0:1].values 58 | 59 | # go short or long positions 60 | if corr < -0.75 and hypothesis < 0.85: 61 | # is stock falling? exit position 62 | if curr_price < last_price: 63 | order(symbol(stock), -1 * cpp[symbol(stock)].amount) 64 | # is stock rising? enter position 65 | elif curr_price > last_price: 66 | order(symbol(stock), 1000) 67 | 68 | record(ASSETME=data.current(context.asset, 'price')) 69 | record(CORR=corr) 70 | 71 | def _test_args(self): 72 | return { 73 | 'start': pd.Timestamp('2017', tz='utc'), 74 | 'end': pd.Timestamp('2018', tz='utc'), 75 | 'capital_base': 1e7 76 | } 77 | 78 | def analyze(self, context, perf): 79 | # init figure 80 | fig = plt.figure() 81 | 82 | # plot stock price 83 | ax1 = fig.add_subplot(211) 84 | perf['ASSETME'].plot(ax=ax1) 85 | ax1.set_ylabel('price in $') 86 | 87 | # plot correlation 88 | ax2 = fig.add_subplot(212) 89 | perf['CORR'].plot(ax=ax2) 90 | ax2.set_ylabel('correlation') 91 | 92 | # plot confidence levels 93 | ax2.axhline(0.75, linestyle='dashed', color='k') 94 | ax2.axhline(0, linestyle='dashed', color='b') 95 | ax2.axhline(-0.75, linestyle='dashed', color='k') 96 | 97 | # add spacing between plots 98 | plt.subplots_adjust(hspace=1) 99 | 100 | # display plot 101 | plt.show() 102 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 3/strategies/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | from joblib import load 5 | import numpy as np 6 | 7 | 8 | class BuyAndHold: 9 | 10 | stocks = ['AAPL', 'MSFT', 'TSLA'] 11 | lag = 33 12 | forecast = 8 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol('AAPL') 18 | context.regressor = load('./strategies/models/rf_regressor.joblib') 19 | 20 | def handle_data(self, context, data): 21 | for stock in context.stocks: 22 | timeseries = data.history( 23 | symbol(stock), 24 | 'price', 25 | bar_count=self.lag, 26 | frequency='1d') 27 | np_timeseries = np.array(timeseries.values).reshape(1, -1) 28 | preds = context.regressor.predict(np_timeseries) 29 | max_price = np.max(preds) 30 | historical_mean = np.mean(np_timeseries) 31 | 32 | if max_price > historical_mean: 33 | order(symbol(stock), 1000) 34 | 35 | if max_price < historical_mean: 36 | order(symbol(stock), -1000) 37 | 38 | record(AAPL=data.current(context.asset, 'price')) 39 | 40 | def _test_args(self): 41 | return { 42 | 'start': pd.Timestamp('2017', tz='utc'), 43 | 'end': pd.Timestamp('2018', tz='utc'), 44 | 'capital_base': 1e7 45 | } 46 | 47 | def analyze(self, context, perf): 48 | fig = plt.figure() 49 | ax1 = fig.add_subplot(211) 50 | perf.portfolio_value.plot(ax=ax1) 51 | ax1.set_ylabel('portfolio value in $') 52 | 53 | ax2 = fig.add_subplot(212) 54 | perf['AAPL'].plot(ax=ax2) 55 | 56 | ax2.set_ylabel('price in $') 57 | plt.legend(loc=0) 58 | plt.show() 59 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 3/strategies/models/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 3/strategies/models/rf_regressor.joblib -------------------------------------------------------------------------------- /Eclipse Projects/Section 3/strategies/run_zipline.py: -------------------------------------------------------------------------------- 1 | from toolz import merge 2 | from zipline import run_algorithm 3 | from zipline.utils.calendars import register_calendar, get_calendar 4 | from strategies.buy_and_hold import BuyAndHold 5 | from strategies.auto_correlation import AutoCorrelation 6 | from os import environ 7 | 8 | 9 | # Columns that we expect to be able to reliably deterministic 10 | # Doesn't include fields that have UUIDS. 11 | _cols_to_check = [ 12 | 'algo_volatility', 13 | 'algorithm_period_return', 14 | 'alpha', 15 | 'benchmark_period_return', 16 | 'benchmark_volatility', 17 | 'beta', 18 | 'capital_used', 19 | 'ending_cash', 20 | 'ending_exposure', 21 | 'ending_value', 22 | 'excess_return', 23 | 'gross_leverage', 24 | 'long_exposure', 25 | 'long_value', 26 | 'longs_count', 27 | 'max_drawdown', 28 | 'max_leverage', 29 | 'net_leverage', 30 | 'period_close', 31 | 'period_label', 32 | 'period_open', 33 | 'pnl', 34 | 'portfolio_value', 35 | 'positions', 36 | 'returns', 37 | 'short_exposure', 38 | 'short_value', 39 | 'shorts_count', 40 | 'sortino', 41 | 'starting_cash', 42 | 'starting_exposure', 43 | 'starting_value', 44 | 'trading_days', 45 | 'treasury_period_return', 46 | ] 47 | 48 | 49 | def run_strategy(strategy_name): 50 | mod = None 51 | 52 | if strategy_name == "buy_and_hold": 53 | mod = BuyAndHold() 54 | elif strategy_name == "auto_correlation": 55 | mod = AutoCorrelation() 56 | 57 | register_calendar("YAHOO", get_calendar("NYSE"), force=True) 58 | 59 | return run_algorithm( 60 | initialize=getattr(mod, 'initialize', None), 61 | handle_data=getattr(mod, 'handle_data', None), 62 | before_trading_start=getattr(mod, 'before_trading_start', None), 63 | analyze=getattr(mod, 'analyze', None), 64 | bundle='quandl', 65 | environ=environ, 66 | # Provide a default capital base, but allow the test to override. 67 | **merge({'capital_base': 1e7}, mod._test_args()) 68 | ) 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 5.zip -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/extension.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from zipline.data.bundles import register 4 | from zipline.data.bundles.csvdir import csvdir_equities 5 | 6 | start_session = pd.Timestamp('2017-01-01 00:00:00', tz='utc') 7 | end_session = pd.Timestamp('2017-12-31 23:59:00', tz='utc') 8 | 9 | register( 10 | 'crypto-bundle', 11 | csvdir_equities( 12 | ['minute'], 13 | '/path/to/your/csvs', 14 | ), 15 | calendar_name='NYSE', # US equities 16 | start_session=start_session, 17 | end_session=end_session 18 | ) -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from matplotlib import pyplot as plt 3 | import numpy as np 4 | from strategies.run_zipline import run_strategy 5 | 6 | 7 | def main(): 8 | print("*** PackPub - Hands-on Machine Learning for Algorithmic Trading Bots ***") 9 | print("*** SEC005/VID002: Implement Scalping Strategy ***") 10 | perf = run_strategy("scalping") 11 | perf.to_csv("scalping.csv") 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/strategies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 5/strategies/__init__.py -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/strategies/auto_correlation.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | from scipy.stats.stats import pearsonr 6 | 7 | 8 | class AutoCorrelation: 9 | 10 | stocks = ['APL', 'MSFT', 'TSLA'] 11 | lag = 1 12 | steps = 3 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol(self.stocks[-1]) 18 | 19 | def handle_data(self, context, data): 20 | # loop stocks in portfolio 21 | for stock in context.stocks: 22 | # fetch history up to steps 23 | s1 = data.history( 24 | symbol(stock), 25 | 'price', 26 | bar_count=self.steps, 27 | frequency='1d') 28 | 29 | # fetch history up to steps + lag and drop extra values 30 | s2 = data.history( 31 | symbol(stock), 32 | 'price', 33 | bar_count=self.steps+self.lag, 34 | frequency='1d').iloc[:-1 * self.lag] 35 | 36 | # convert to numpy arrays 37 | np_s1 = np.array(s1.values) 38 | np_s2 = np.array(s2.values) 39 | 40 | # calculate auto-correlation 41 | corr, hypothesis = pearsonr(np_s1, np_s2) 42 | 43 | # fetch our basket status 44 | cpp = context.portfolio.positions 45 | 46 | # map basket to symbol:shares pairs 47 | cpp_symbols = map(lambda x: x.symbol, cpp) 48 | 49 | # what is today price 50 | curr_price = data.current(symbol(stock), 'price') 51 | 52 | # what was yesterday closing price 53 | last_price = data.history( 54 | symbol(stock), 55 | 'price', 56 | bar_count=2, 57 | frequency='1d').iloc[0:1].values 58 | 59 | # go short or long positions 60 | if corr < -0.75 and hypothesis < 0.85: 61 | # is stock falling? exit position 62 | if curr_price < last_price: 63 | order(symbol(stock), -1 * cpp[symbol(stock)].amount) 64 | # is stock rising? enter position 65 | elif curr_price > last_price: 66 | order(symbol(stock), 1000) 67 | 68 | record(ASSETME=data.current(context.asset, 'price')) 69 | record(CORR=corr) 70 | 71 | def _test_args(self): 72 | return { 73 | 'start': pd.Timestamp('2017', tz='utc'), 74 | 'end': pd.Timestamp('2018', tz='utc'), 75 | 'capital_base': 1e7 76 | } 77 | 78 | def analyze(self, context, perf): 79 | # init figure 80 | fig = plt.figure() 81 | 82 | # plot stock price 83 | ax1 = fig.add_subplot(211) 84 | perf['ASSETME'].plot(ax=ax1) 85 | ax1.set_ylabel('price in $') 86 | 87 | # plot correlation 88 | ax2 = fig.add_subplot(212) 89 | perf['CORR'].plot(ax=ax2) 90 | ax2.set_ylabel('correlation') 91 | 92 | # plot confidence levels 93 | ax2.axhline(0.75, linestyle='dashed', color='k') 94 | ax2.axhline(0, linestyle='dashed', color='b') 95 | ax2.axhline(-0.75, linestyle='dashed', color='k') 96 | 97 | # add spacing between plots 98 | plt.subplots_adjust(hspace=1) 99 | 100 | # display plot 101 | plt.show() 102 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/strategies/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | from joblib import load 5 | import numpy as np 6 | 7 | 8 | class BuyAndHold: 9 | 10 | stocks = ['AAPL', 'MSFT', 'TSLA'] 11 | lag = 33 12 | forecast = 8 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol('AAPL') 18 | context.regressor = load('./strategies/models/rf_regressor.joblib') 19 | 20 | def handle_data(self, context, data): 21 | for stock in context.stocks: 22 | timeseries = data.history( 23 | symbol(stock), 24 | 'price', 25 | bar_count=self.lag, 26 | frequency='1d') 27 | np_timeseries = np.array(timeseries.values).reshape(1, -1) 28 | preds = context.regressor.predict(np_timeseries) 29 | max_price = np.max(preds) 30 | historical_mean = np.mean(np_timeseries) 31 | 32 | if max_price > historical_mean: 33 | order(symbol(stock), 1000) 34 | 35 | if max_price < historical_mean: 36 | order(symbol(stock), -1000) 37 | 38 | record(AAPL=data.current(context.asset, 'price')) 39 | 40 | def _test_args(self): 41 | return { 42 | 'start': pd.Timestamp('2017', tz='utc'), 43 | 'end': pd.Timestamp('2018', tz='utc'), 44 | 'capital_base': 1e7 45 | } 46 | 47 | def analyze(self, context, perf): 48 | fig = plt.figure() 49 | ax1 = fig.add_subplot(211) 50 | perf.portfolio_value.plot(ax=ax1) 51 | ax1.set_ylabel('portfolio value in $') 52 | 53 | ax2 = fig.add_subplot(212) 54 | perf['AAPL'].plot(ax=ax2) 55 | 56 | ax2.set_ylabel('price in $') 57 | plt.legend(loc=0) 58 | plt.show() 59 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/strategies/calendar.py: -------------------------------------------------------------------------------- 1 | from zipline.utils.calendars import TradingCalendar 2 | from datetime import time 3 | from pandas.tseries.offsets import CustomBusinessDay 4 | from pytz import timezone 5 | from zipline.utils.memoize import lazyval 6 | 7 | 8 | class CryptoCalendar(TradingCalendar): 9 | """ 10 | Exchange calendar for 24/7 trading. 11 | 12 | Open Time: 12am, UTC 13 | Close Time: 11:59pm, UTC 14 | 15 | """ 16 | @property 17 | def name(self): 18 | return "cryptocalendar" 19 | 20 | @property 21 | def tz(self): 22 | return timezone("UTC") 23 | 24 | @property 25 | def open_time(self): 26 | return time(0, 0) 27 | 28 | @property 29 | def close_time(self): 30 | return time(23, 59) 31 | 32 | @property 33 | def open_times(self): 34 | return [(None, time(0, 0))] 35 | 36 | @property 37 | def close_times(self): 38 | return [(None, time(23, 59))] 39 | 40 | @lazyval 41 | def day(self): 42 | return CustomBusinessDay( 43 | weekmask='Mon Tue Wed Thu Fri Sat Sun', 44 | ) -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/strategies/models/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 5/strategies/models/rf_regressor.joblib -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/strategies/run_zipline.py: -------------------------------------------------------------------------------- 1 | from toolz import merge 2 | from zipline import run_algorithm 3 | from zipline.utils.calendars import register_calendar, get_calendar 4 | from strategies.buy_and_hold import BuyAndHold 5 | from strategies.auto_correlation import AutoCorrelation 6 | from os import environ 7 | from strategies.scalping import ScalpBollingerBand 8 | import pandas as pd 9 | import os 10 | import pytz 11 | from collections import OrderedDict 12 | from strategies.calendar import CryptoCalendar 13 | 14 | 15 | # Columns that we expect to be able to reliably deterministic 16 | # Doesn't include fields that have UUIDS. 17 | _cols_to_check = [ 18 | 'algo_volatility', 19 | 'algorithm_period_return', 20 | 'alpha', 21 | 'benchmark_period_return', 22 | 'benchmark_volatility', 23 | 'beta', 24 | 'capital_used', 25 | 'ending_cash', 26 | 'ending_exposure', 27 | 'ending_value', 28 | 'excess_return', 29 | 'gross_leverage', 30 | 'long_exposure', 31 | 'long_value', 32 | 'longs_count', 33 | 'max_drawdown', 34 | 'max_leverage', 35 | 'net_leverage', 36 | 'period_close', 37 | 'period_label', 38 | 'period_open', 39 | 'pnl', 40 | 'portfolio_value', 41 | 'positions', 42 | 'returns', 43 | 'short_exposure', 44 | 'short_value', 45 | 'shorts_count', 46 | 'sortino', 47 | 'starting_cash', 48 | 'starting_exposure', 49 | 'starting_value', 50 | 'trading_days', 51 | 'treasury_period_return', 52 | ] 53 | 54 | 55 | def prepareCSV(csv_pth): 56 | files = os.listdir(csv_pth) 57 | start = end = None 58 | 59 | dd = OrderedDict() 60 | for f in files: 61 | fp = os.path.join(csv_pth, f) 62 | n1 = os.path.splitext(fp)[0] 63 | key = n1.split('/')[1] 64 | df = pd.read_csv(fp) 65 | df.index = pd.DatetimeIndex(df.date) 66 | df = df.sort_index() 67 | dd[key] = df.drop(columns=['date']) 68 | start = df.index.values[0] 69 | end = df.index.values[10*24*60] 70 | 71 | panel = pd.Panel(dd) 72 | 73 | panel.major_axis = panel.major_axis.tz_localize(pytz.utc) 74 | 75 | return panel, pd.to_datetime(start).tz_localize(pytz.utc), pd.to_datetime(end).tz_localize(pytz.utc) 76 | 77 | 78 | def run_strategy(strategy_name): 79 | mod = None 80 | 81 | if strategy_name == "buy_and_hold": 82 | mod = BuyAndHold() 83 | elif strategy_name == "auto_correlation": 84 | mod = AutoCorrelation() 85 | elif strategy_name == "scalping": 86 | mod = ScalpBollingerBand() 87 | 88 | # register_calendar("YAHOO", get_calendar("NYSE"), force=True) 89 | data_panel, start, end = prepareCSV('csv') 90 | print(data_panel, type(start)) 91 | 92 | return run_algorithm( 93 | data=data_panel, 94 | trading_calendar=CryptoCalendar(), 95 | initialize=getattr(mod, 'initialize', None), 96 | handle_data=getattr(mod, 'handle_data', None), 97 | before_trading_start=getattr(mod, 'before_trading_start', None), 98 | analyze=getattr(mod, 'analyze', None), 99 | # bundle='quandl', 100 | environ=environ, 101 | data_frequency='minute', 102 | # Provide a default capital base, but allow the test to override. 103 | **merge({ 104 | 'capital_base': 5000, 105 | 'start': start, 106 | 'end': end 107 | }, mod._test_args()) 108 | ) 109 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 5/strategies/scalping.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | 6 | 7 | class ScalpBollingerBand: 8 | 9 | stocks = ['BTCUSD', 'ETHUSD'] 10 | ma1 = 10 11 | ma2 = 120 12 | steps = 1280 13 | stop_loss = 0.005 14 | stdv = 0.5 15 | 16 | 17 | def initialize(self, context): 18 | context.stocks = self.stocks 19 | context.asset = symbol(self.stocks[-1]) 20 | 21 | context.burndown = 0 22 | context.number_shorts = 0 23 | context.number_longs = 0 24 | 25 | context.position = {} 26 | for stock in self.stocks: 27 | context.position[stock] = None 28 | 29 | 30 | def handle_data(self, context, data): 31 | 32 | # wait till enough historical data arrives for calculations 33 | context.burndown += 1 34 | 35 | # log while backtesting 36 | if context.burndown % 1000 == 0: 37 | print(context.burndown) 38 | 39 | # trade only when there is enough data 40 | if context.burndown > self.steps: 41 | 42 | # loop stocks in portfolio 43 | for i, stock in enumerate(context.stocks): 44 | # history 45 | hist = data.history( 46 | symbol(stock), 47 | 'price', 48 | bar_count=self.steps, 49 | frequency='1m') 50 | 51 | # bollinger bands 52 | blw = hist.mean() - self.stdv * hist.std() 53 | bhi = hist.mean() + self.stdv * hist.std() 54 | 55 | # moving average short 56 | short_term = data.history( 57 | symbol(stock), 58 | 'price', 59 | bar_count=self.ma1, 60 | frequency='1m').mean() 61 | 62 | # moving average long 63 | long_term = data.history( 64 | symbol(stock), 65 | 'price', 66 | bar_count=self.ma2, 67 | frequency='1m').mean() 68 | 69 | # fetch our basket status 70 | cpp = context.portfolio.positions 71 | 72 | # map basket to symbol:shares pairs 73 | cpp_symbols = map(lambda x: x.symbol, cpp) 74 | 75 | # check indicator signal 76 | if short_term >= long_term and context.position[stock] != 'trade': 77 | context.position[stock] = 'long' 78 | elif short_term <= long_term and context.position[stock] == 'trade': 79 | context.position[stock] = 'short' 80 | 81 | 82 | # what is current price 83 | current_price = data.current(symbol(stock), 'price') 84 | 85 | 86 | # check bollinger bands 87 | if short_term >= bhi and context.position[stock] == 'long': 88 | # how many shares I can afford? 89 | num_shares = context.portfolio.cash // current_price 90 | 91 | # long position 92 | order(symbol(stock), num_shares) # order_value 93 | context.position[stock] = 'trade' 94 | context.number_longs += 1 95 | 96 | elif (current_price <= blw and context.position[stock] == 'trade') \ 97 | or (short_term <= blw and context.position[stock] == 'short'): 98 | # short position 99 | order(symbol(stock), 0) 100 | context.position[stock] = None 101 | context.number_shorts += 1 102 | print('Exit Trade: ', stock) 103 | 104 | 105 | # what is the price paid on beginning of trade 106 | last_price = cpp[symbol(stock)].last_sale_price 107 | 108 | # stop loss value 109 | val = last_price - last_price * self.stop_loss 110 | 111 | # are we in a trade? 112 | if context.position[stock] == 'trade': 113 | # stop loss violated 114 | if current_price < val: 115 | # short position 116 | order(symbol(stock), 0) 117 | context.position[stock] = None 118 | context.number_shorts += 1 119 | print('Stop Loss: ', stock) 120 | 121 | # is last stock? 122 | if i == len(self.stocks) - 1: 123 | 124 | # record price, ma1, ma2, Bollinger bands 125 | record(REC_PRICE=current_price) 126 | record(REC_MA1=short_term) 127 | record(REC_MA2=long_term) 128 | record(REC_BB1=blw) 129 | record(REC_BB2=bhi) 130 | 131 | # record positions count 132 | record(REC_NUM_SHORTS=context.number_shorts) 133 | record(REC_NUM_LONGS=context.number_longs) 134 | 135 | def _test_args(self): 136 | return { 137 | # 'start': pd.Timestamp('2017', tz='utc'), 138 | # 'end': pd.Timestamp('2018', tz='utc'), 139 | # 'capital_base': 1e7, 140 | # 'data_frequency': 'minute' 141 | } 142 | 143 | def analyze(self, context, perf): 144 | # init figure 145 | fig = plt.figure() 146 | 147 | # plot recorded data 148 | ax1 = fig.add_subplot(211) 149 | perf.plot(y=[ 150 | 'REC_PRICE', 151 | 'REC_MA1', 152 | 'REC_MA2' 153 | ], ax=ax1) 154 | ax1.set_ylabel('price in $') 155 | 156 | # plot recorded data 157 | ax2 = fig.add_subplot(212) 158 | perf.plot(y=[ 159 | 'REC_PRICE', 160 | 'REC_BB1', 161 | 'REC_BB2' 162 | ], ax=ax2) 163 | ax2.set_ylabel('Bollinger Bands') 164 | 165 | # add spacing between plots 166 | plt.subplots_adjust(hspace=1) 167 | 168 | # display plot 169 | plt.show() 170 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 6A.zip -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/extension.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from zipline.data.bundles import register 4 | from zipline.data.bundles.csvdir import csvdir_equities 5 | 6 | start_session = pd.Timestamp('2017-01-01 00:00:00', tz='utc') 7 | end_session = pd.Timestamp('2017-12-31 23:59:00', tz='utc') 8 | 9 | register( 10 | 'crypto-bundle', 11 | csvdir_equities( 12 | ['minute'], 13 | '/path/to/your/csvs', 14 | ), 15 | calendar_name='NYSE', # US equities 16 | start_session=start_session, 17 | end_session=end_session 18 | ) -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from matplotlib import pyplot as plt 3 | import numpy as np 4 | from strategies.run_zipline import run_strategy 5 | 6 | 7 | def main(): 8 | print("*** PackPub - Hands-on Machine Learning for Algorithmic Trading Bots ***") 9 | print("*** SEC005/VID002: Implement Scalping Strategy ***") 10 | perf = run_strategy("scalping") 11 | perf.to_csv("scalping.csv") 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/strategies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 6A/strategies/__init__.py -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/strategies/auto_correlation.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | from scipy.stats.stats import pearsonr 6 | 7 | 8 | class AutoCorrelation: 9 | 10 | stocks = ['APL', 'MSFT', 'TSLA'] 11 | lag = 1 12 | steps = 3 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol(self.stocks[-1]) 18 | 19 | def handle_data(self, context, data): 20 | # loop stocks in portfolio 21 | for stock in context.stocks: 22 | # fetch history up to steps 23 | s1 = data.history( 24 | symbol(stock), 25 | 'price', 26 | bar_count=self.steps, 27 | frequency='1d') 28 | 29 | # fetch history up to steps + lag and drop extra values 30 | s2 = data.history( 31 | symbol(stock), 32 | 'price', 33 | bar_count=self.steps+self.lag, 34 | frequency='1d').iloc[:-1 * self.lag] 35 | 36 | # convert to numpy arrays 37 | np_s1 = np.array(s1.values) 38 | np_s2 = np.array(s2.values) 39 | 40 | # calculate auto-correlation 41 | corr, hypothesis = pearsonr(np_s1, np_s2) 42 | 43 | # fetch our basket status 44 | cpp = context.portfolio.positions 45 | 46 | # map basket to symbol:shares pairs 47 | cpp_symbols = map(lambda x: x.symbol, cpp) 48 | 49 | # what is today price 50 | curr_price = data.current(symbol(stock), 'price') 51 | 52 | # what was yesterday closing price 53 | last_price = data.history( 54 | symbol(stock), 55 | 'price', 56 | bar_count=2, 57 | frequency='1d').iloc[0:1].values 58 | 59 | # go short or long positions 60 | if corr < -0.75 and hypothesis < 0.85: 61 | # is stock falling? exit position 62 | if curr_price < last_price: 63 | order(symbol(stock), -1 * cpp[symbol(stock)].amount) 64 | # is stock rising? enter position 65 | elif curr_price > last_price: 66 | order(symbol(stock), 1000) 67 | 68 | record(ASSETME=data.current(context.asset, 'price')) 69 | record(CORR=corr) 70 | 71 | def _test_args(self): 72 | return { 73 | 'start': pd.Timestamp('2017', tz='utc'), 74 | 'end': pd.Timestamp('2018', tz='utc'), 75 | 'capital_base': 1e7 76 | } 77 | 78 | def analyze(self, context, perf): 79 | # init figure 80 | fig = plt.figure() 81 | 82 | # plot stock price 83 | ax1 = fig.add_subplot(211) 84 | perf['ASSETME'].plot(ax=ax1) 85 | ax1.set_ylabel('price in $') 86 | 87 | # plot correlation 88 | ax2 = fig.add_subplot(212) 89 | perf['CORR'].plot(ax=ax2) 90 | ax2.set_ylabel('correlation') 91 | 92 | # plot confidence levels 93 | ax2.axhline(0.75, linestyle='dashed', color='k') 94 | ax2.axhline(0, linestyle='dashed', color='b') 95 | ax2.axhline(-0.75, linestyle='dashed', color='k') 96 | 97 | # add spacing between plots 98 | plt.subplots_adjust(hspace=1) 99 | 100 | # display plot 101 | plt.show() 102 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/strategies/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | from joblib import load 5 | import numpy as np 6 | 7 | 8 | class BuyAndHold: 9 | 10 | stocks = ['AAPL', 'MSFT', 'TSLA'] 11 | lag = 33 12 | forecast = 8 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol('AAPL') 18 | context.regressor = load('./strategies/models/rf_regressor.joblib') 19 | 20 | def handle_data(self, context, data): 21 | for stock in context.stocks: 22 | timeseries = data.history( 23 | symbol(stock), 24 | 'price', 25 | bar_count=self.lag, 26 | frequency='1d') 27 | np_timeseries = np.array(timeseries.values).reshape(1, -1) 28 | preds = context.regressor.predict(np_timeseries) 29 | max_price = np.max(preds) 30 | historical_mean = np.mean(np_timeseries) 31 | 32 | if max_price > historical_mean: 33 | order(symbol(stock), 1000) 34 | 35 | if max_price < historical_mean: 36 | order(symbol(stock), -1000) 37 | 38 | record(AAPL=data.current(context.asset, 'price')) 39 | 40 | def _test_args(self): 41 | return { 42 | 'start': pd.Timestamp('2017', tz='utc'), 43 | 'end': pd.Timestamp('2018', tz='utc'), 44 | 'capital_base': 1e7 45 | } 46 | 47 | def analyze(self, context, perf): 48 | fig = plt.figure() 49 | ax1 = fig.add_subplot(211) 50 | perf.portfolio_value.plot(ax=ax1) 51 | ax1.set_ylabel('portfolio value in $') 52 | 53 | ax2 = fig.add_subplot(212) 54 | perf['AAPL'].plot(ax=ax2) 55 | 56 | ax2.set_ylabel('price in $') 57 | plt.legend(loc=0) 58 | plt.show() 59 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/strategies/calendar.py: -------------------------------------------------------------------------------- 1 | from zipline.utils.calendars import TradingCalendar 2 | from datetime import time 3 | from pandas.tseries.offsets import CustomBusinessDay 4 | from pytz import timezone 5 | from zipline.utils.memoize import lazyval 6 | 7 | 8 | class CryptoCalendar(TradingCalendar): 9 | """ 10 | Exchange calendar for 24/7 trading. 11 | 12 | Open Time: 12am, UTC 13 | Close Time: 11:59pm, UTC 14 | 15 | """ 16 | @property 17 | def name(self): 18 | return "cryptocalendar" 19 | 20 | @property 21 | def tz(self): 22 | return timezone("UTC") 23 | 24 | @property 25 | def open_time(self): 26 | return time(0, 0) 27 | 28 | @property 29 | def close_time(self): 30 | return time(23, 59) 31 | 32 | @property 33 | def open_times(self): 34 | return [(None, time(0, 0))] 35 | 36 | @property 37 | def close_times(self): 38 | return [(None, time(23, 59))] 39 | 40 | @lazyval 41 | def day(self): 42 | return CustomBusinessDay( 43 | weekmask='Mon Tue Wed Thu Fri Sat Sun', 44 | ) -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/strategies/models/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 6A/strategies/models/rf_regressor.joblib -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/strategies/run_zipline.py: -------------------------------------------------------------------------------- 1 | from toolz import merge 2 | from zipline import run_algorithm 3 | from zipline.utils.calendars import register_calendar, get_calendar 4 | from strategies.buy_and_hold import BuyAndHold 5 | from strategies.auto_correlation import AutoCorrelation 6 | from os import environ 7 | from strategies.scalping import ScalpBollingerBand 8 | import pandas as pd 9 | import os 10 | import pytz 11 | from collections import OrderedDict 12 | from strategies.calendar import CryptoCalendar 13 | 14 | 15 | # Columns that we expect to be able to reliably deterministic 16 | # Doesn't include fields that have UUIDS. 17 | _cols_to_check = [ 18 | 'algo_volatility', 19 | 'algorithm_period_return', 20 | 'alpha', 21 | 'benchmark_period_return', 22 | 'benchmark_volatility', 23 | 'beta', 24 | 'capital_used', 25 | 'ending_cash', 26 | 'ending_exposure', 27 | 'ending_value', 28 | 'excess_return', 29 | 'gross_leverage', 30 | 'long_exposure', 31 | 'long_value', 32 | 'longs_count', 33 | 'max_drawdown', 34 | 'max_leverage', 35 | 'net_leverage', 36 | 'period_close', 37 | 'period_label', 38 | 'period_open', 39 | 'pnl', 40 | 'portfolio_value', 41 | 'positions', 42 | 'returns', 43 | 'short_exposure', 44 | 'short_value', 45 | 'shorts_count', 46 | 'sortino', 47 | 'starting_cash', 48 | 'starting_exposure', 49 | 'starting_value', 50 | 'trading_days', 51 | 'treasury_period_return', 52 | ] 53 | 54 | 55 | def prepareCSV(csv_pth): 56 | files = os.listdir(csv_pth) 57 | start = end = None 58 | 59 | dd = OrderedDict() 60 | for f in files: 61 | fp = os.path.join(csv_pth, f) 62 | n1 = os.path.splitext(fp)[0] 63 | key = n1.split('/')[1] 64 | df = pd.read_csv(fp) 65 | df.index = pd.DatetimeIndex(df.date) 66 | df = df.sort_index() 67 | dd[key] = df.drop(columns=['date']) 68 | start = df.index.values[0] 69 | end = df.index.values[10*24*60] 70 | 71 | panel = pd.Panel(dd) 72 | 73 | panel.major_axis = panel.major_axis.tz_localize(pytz.utc) 74 | 75 | return panel, pd.to_datetime(start).tz_localize(pytz.utc), pd.to_datetime(end).tz_localize(pytz.utc) 76 | 77 | 78 | def run_strategy(strategy_name): 79 | mod = None 80 | 81 | if strategy_name == "buy_and_hold": 82 | mod = BuyAndHold() 83 | elif strategy_name == "auto_correlation": 84 | mod = AutoCorrelation() 85 | elif strategy_name == "scalping": 86 | mod = ScalpBollingerBand() 87 | 88 | # register_calendar("YAHOO", get_calendar("NYSE"), force=True) 89 | data_panel, start, end = prepareCSV('csv') 90 | print(data_panel, type(start)) 91 | 92 | return run_algorithm( 93 | data=data_panel, 94 | trading_calendar=CryptoCalendar(), 95 | initialize=getattr(mod, 'initialize', None), 96 | handle_data=getattr(mod, 'handle_data', None), 97 | before_trading_start=getattr(mod, 'before_trading_start', None), 98 | analyze=getattr(mod, 'analyze', None), 99 | # bundle='quandl', 100 | environ=environ, 101 | data_frequency='minute', 102 | # Provide a default capital base, but allow the test to override. 103 | **merge({ 104 | 'capital_base': 1000, 105 | 'start': start, 106 | 'end': end 107 | }, mod._test_args()) 108 | ) 109 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6A/strategies/scalping.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | 6 | 7 | class ScalpBollingerBand: 8 | 9 | stocks = ['BTCUSD', 'ETHUSD'] 10 | ma1 = 10 11 | ma2 = 120 12 | steps = 1280 13 | stop_loss = 0.005 14 | stdv = 0.5 15 | 16 | 17 | def initialize(self, context): 18 | context.stocks = self.stocks 19 | context.asset = symbol(self.stocks[-1]) 20 | 21 | context.burndown = 0 22 | context.number_shorts = 0 23 | context.number_longs = 0 24 | 25 | context.position = {} 26 | for stock in self.stocks: 27 | context.position[stock] = None 28 | 29 | # VaR 30 | context.historical_returns = [] 31 | 32 | 33 | def handle_data(self, context, data): 34 | # wait till enough historical data arrives for calculations 35 | context.burndown += 1 36 | 37 | # log while backtesting 38 | if context.burndown % 1000 == 0: 39 | print(context.burndown) 40 | 41 | # calculate VaR only when there is enough data 42 | if len(context.historical_returns) > 100: 43 | 44 | # Non-Parametric Historical Value at Risk 45 | historical_returns = np.array(context.historical_returns) 46 | lowest_percentile = np.percentile(historical_returns, 0.05) 47 | expected_shortfall = np.mean( 48 | np.where( 49 | historical_returns <= lowest_percentile 50 | ) 51 | ) 52 | 53 | # stop loss value 54 | value_at_risk = expected_shortfall / 60 / 24 55 | 56 | # exit all positions 57 | if ( context.portfolio.returns <= value_at_risk ): 58 | # loop stocks in portfolio 59 | for i, stock in enumerate(context.stocks): 60 | # are we in a trade? 61 | if context.position[stock] == 'trade': 62 | # short position 63 | order(symbol(stock), 0) 64 | context.position[stock] = None 65 | context.number_shorts += 1 66 | print('Stop Loss: {} @ VaR {} for {}'.format( 67 | context.portfolio.returns, 68 | value_at_risk, 69 | stock 70 | ) 71 | ) 72 | 73 | 74 | # trade only when there is enough data 75 | if context.burndown > self.steps: 76 | 77 | # loop stocks in portfolio 78 | for i, stock in enumerate(context.stocks): 79 | # history 80 | hist = data.history( 81 | symbol(stock), 82 | 'price', 83 | bar_count=self.steps, 84 | frequency='1m') 85 | 86 | # bollinger bands 87 | blw = hist.mean() - self.stdv * hist.std() 88 | bhi = hist.mean() + self.stdv * hist.std() 89 | 90 | # moving average short 91 | short_term = data.history( 92 | symbol(stock), 93 | 'price', 94 | bar_count=self.ma1, 95 | frequency='1m').mean() 96 | 97 | # moving average long 98 | long_term = data.history( 99 | symbol(stock), 100 | 'price', 101 | bar_count=self.ma2, 102 | frequency='1m').mean() 103 | 104 | # fetch our basket status 105 | cpp = context.portfolio.positions 106 | 107 | # map basket to symbol:shares pairs 108 | cpp_symbols = map(lambda x: x.symbol, cpp) 109 | 110 | # check indicator signal 111 | if short_term >= long_term and context.position[stock] != 'trade': 112 | context.position[stock] = 'long' 113 | elif short_term <= long_term and context.position[stock] == 'trade': 114 | context.position[stock] = 'short' 115 | 116 | 117 | # what is current price 118 | current_price = data.current(symbol(stock), 'price') 119 | 120 | 121 | # check bollinger bands 122 | if short_term >= bhi and context.position[stock] == 'long': 123 | # how many shares I can afford? 124 | num_shares = context.portfolio.cash // current_price 125 | 126 | # long position 127 | order(symbol(stock), num_shares) # order_value 128 | context.position[stock] = 'trade' 129 | context.number_longs += 1 130 | print('Enter Trade: ', stock) 131 | 132 | elif (current_price <= blw and context.position[stock] == 'trade') \ 133 | or (short_term <= blw and context.position[stock] == 'short'): 134 | # short position 135 | order(symbol(stock), 0) 136 | context.position[stock] = None 137 | context.number_shorts += 1 138 | print('Exit Trade: ', stock) 139 | 140 | 141 | # what is the price paid on beginning of trade 142 | last_price = cpp[symbol(stock)].last_sale_price 143 | 144 | # stop loss value 145 | val = last_price - last_price * self.stop_loss 146 | 147 | # are we in a trade? 148 | if context.position[stock] == 'trade': 149 | # stop loss violated 150 | if current_price < val: 151 | # short position 152 | order(symbol(stock), 0) 153 | context.position[stock] = None 154 | context.number_shorts += 1 155 | print('Stop Loss: ', stock) 156 | 157 | # is last stock? 158 | if i == len(self.stocks) - 1: 159 | 160 | # record price, ma1, ma2, Bollinger bands 161 | record(REC_PRICE=current_price) 162 | record(REC_MA1=short_term) 163 | record(REC_MA2=long_term) 164 | record(REC_BB1=blw) 165 | record(REC_BB2=bhi) 166 | 167 | context.historical_returns.append(context.portfolio.returns) 168 | 169 | # record positions count 170 | record(REC_NUM_SHORTS=context.number_shorts) 171 | record(REC_NUM_LONGS=context.number_longs) 172 | 173 | def _test_args(self): 174 | return { 175 | # 'start': pd.Timestamp('2017', tz='utc'), 176 | # 'end': pd.Timestamp('2018', tz='utc'), 177 | # 'capital_base': 1e7, 178 | # 'data_frequency': 'minute' 179 | } 180 | 181 | def analyze(self, context, perf): 182 | # init figure 183 | fig = plt.figure() 184 | 185 | # plot recorded data 186 | ax1 = fig.add_subplot(211) 187 | perf.plot(y=[ 188 | 'REC_PRICE', 189 | 'REC_MA1', 190 | 'REC_MA2' 191 | ], ax=ax1) 192 | ax1.set_ylabel('price in $') 193 | 194 | # plot recorded data 195 | ax2 = fig.add_subplot(212) 196 | perf.plot(y=[ 197 | 'REC_PRICE', 198 | 'REC_BB1', 199 | 'REC_BB2' 200 | ], ax=ax2) 201 | ax2.set_ylabel('Bollinger Bands') 202 | 203 | # add spacing between plots 204 | plt.subplots_adjust(hspace=1) 205 | 206 | # display plot 207 | plt.show() 208 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 6B.zip -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/extension.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from zipline.data.bundles import register 4 | from zipline.data.bundles.csvdir import csvdir_equities 5 | 6 | start_session = pd.Timestamp('2017-01-01 00:00:00', tz='utc') 7 | end_session = pd.Timestamp('2017-12-31 23:59:00', tz='utc') 8 | 9 | register( 10 | 'crypto-bundle', 11 | csvdir_equities( 12 | ['minute'], 13 | '/path/to/your/csvs', 14 | ), 15 | calendar_name='NYSE', # US equities 16 | start_session=start_session, 17 | end_session=end_session 18 | ) -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from matplotlib import pyplot as plt 3 | import numpy as np 4 | from strategies.run_zipline import run_strategy 5 | 6 | 7 | def main(): 8 | print("*** PackPub - Hands-on Machine Learning for Algorithmic Trading Bots ***") 9 | print("*** SEC005/VID002: Implement Scalping Strategy ***") 10 | perf = run_strategy("scalping") 11 | perf.to_csv("scalping.csv") 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 6B/strategies/__init__.py -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/auto_correlation.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | from scipy.stats.stats import pearsonr 6 | 7 | 8 | class AutoCorrelation: 9 | 10 | stocks = ['APL', 'MSFT', 'TSLA'] 11 | lag = 1 12 | steps = 3 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol(self.stocks[-1]) 18 | 19 | def handle_data(self, context, data): 20 | # loop stocks in portfolio 21 | for stock in context.stocks: 22 | # fetch history up to steps 23 | s1 = data.history( 24 | symbol(stock), 25 | 'price', 26 | bar_count=self.steps, 27 | frequency='1d') 28 | 29 | # fetch history up to steps + lag and drop extra values 30 | s2 = data.history( 31 | symbol(stock), 32 | 'price', 33 | bar_count=self.steps+self.lag, 34 | frequency='1d').iloc[:-1 * self.lag] 35 | 36 | # convert to numpy arrays 37 | np_s1 = np.array(s1.values) 38 | np_s2 = np.array(s2.values) 39 | 40 | # calculate auto-correlation 41 | corr, hypothesis = pearsonr(np_s1, np_s2) 42 | 43 | # fetch our basket status 44 | cpp = context.portfolio.positions 45 | 46 | # map basket to symbol:shares pairs 47 | cpp_symbols = map(lambda x: x.symbol, cpp) 48 | 49 | # what is today price 50 | curr_price = data.current(symbol(stock), 'price') 51 | 52 | # what was yesterday closing price 53 | last_price = data.history( 54 | symbol(stock), 55 | 'price', 56 | bar_count=2, 57 | frequency='1d').iloc[0:1].values 58 | 59 | # go short or long positions 60 | if corr < -0.75 and hypothesis < 0.85: 61 | # is stock falling? exit position 62 | if curr_price < last_price: 63 | order(symbol(stock), -1 * cpp[symbol(stock)].amount) 64 | # is stock rising? enter position 65 | elif curr_price > last_price: 66 | order(symbol(stock), 1000) 67 | 68 | record(ASSETME=data.current(context.asset, 'price')) 69 | record(CORR=corr) 70 | 71 | def _test_args(self): 72 | return { 73 | 'start': pd.Timestamp('2017', tz='utc'), 74 | 'end': pd.Timestamp('2018', tz='utc'), 75 | 'capital_base': 1e7 76 | } 77 | 78 | def analyze(self, context, perf): 79 | # init figure 80 | fig = plt.figure() 81 | 82 | # plot stock price 83 | ax1 = fig.add_subplot(211) 84 | perf['ASSETME'].plot(ax=ax1) 85 | ax1.set_ylabel('price in $') 86 | 87 | # plot correlation 88 | ax2 = fig.add_subplot(212) 89 | perf['CORR'].plot(ax=ax2) 90 | ax2.set_ylabel('correlation') 91 | 92 | # plot confidence levels 93 | ax2.axhline(0.75, linestyle='dashed', color='k') 94 | ax2.axhline(0, linestyle='dashed', color='b') 95 | ax2.axhline(-0.75, linestyle='dashed', color='k') 96 | 97 | # add spacing between plots 98 | plt.subplots_adjust(hspace=1) 99 | 100 | # display plot 101 | plt.show() 102 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | from joblib import load 5 | import numpy as np 6 | 7 | 8 | class BuyAndHold: 9 | 10 | stocks = ['AAPL', 'MSFT', 'TSLA'] 11 | lag = 33 12 | forecast = 8 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol('AAPL') 18 | context.regressor = load('./strategies/models/rf_regressor.joblib') 19 | 20 | def handle_data(self, context, data): 21 | for stock in context.stocks: 22 | timeseries = data.history( 23 | symbol(stock), 24 | 'price', 25 | bar_count=self.lag, 26 | frequency='1d') 27 | np_timeseries = np.array(timeseries.values).reshape(1, -1) 28 | preds = context.regressor.predict(np_timeseries) 29 | max_price = np.max(preds) 30 | historical_mean = np.mean(np_timeseries) 31 | 32 | if max_price > historical_mean: 33 | order(symbol(stock), 1000) 34 | 35 | if max_price < historical_mean: 36 | order(symbol(stock), -1000) 37 | 38 | record(AAPL=data.current(context.asset, 'price')) 39 | 40 | def _test_args(self): 41 | return { 42 | 'start': pd.Timestamp('2017', tz='utc'), 43 | 'end': pd.Timestamp('2018', tz='utc'), 44 | 'capital_base': 1e7 45 | } 46 | 47 | def analyze(self, context, perf): 48 | fig = plt.figure() 49 | ax1 = fig.add_subplot(211) 50 | perf.portfolio_value.plot(ax=ax1) 51 | ax1.set_ylabel('portfolio value in $') 52 | 53 | ax2 = fig.add_subplot(212) 54 | perf['AAPL'].plot(ax=ax2) 55 | 56 | ax2.set_ylabel('price in $') 57 | plt.legend(loc=0) 58 | plt.show() 59 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/calendar.py: -------------------------------------------------------------------------------- 1 | from zipline.utils.calendars import TradingCalendar 2 | from datetime import time 3 | from pandas.tseries.offsets import CustomBusinessDay 4 | from pytz import timezone 5 | from zipline.utils.memoize import lazyval 6 | 7 | 8 | class CryptoCalendar(TradingCalendar): 9 | """ 10 | Exchange calendar for 24/7 trading. 11 | 12 | Open Time: 12am, UTC 13 | Close Time: 11:59pm, UTC 14 | 15 | """ 16 | @property 17 | def name(self): 18 | return "cryptocalendar" 19 | 20 | @property 21 | def tz(self): 22 | return timezone("UTC") 23 | 24 | @property 25 | def open_time(self): 26 | return time(0, 0) 27 | 28 | @property 29 | def close_time(self): 30 | return time(23, 59) 31 | 32 | @property 33 | def open_times(self): 34 | return [(None, time(0, 0))] 35 | 36 | @property 37 | def close_times(self): 38 | return [(None, time(23, 59))] 39 | 40 | @lazyval 41 | def day(self): 42 | return CustomBusinessDay( 43 | weekmask='Mon Tue Wed Thu Fri Sat Sun', 44 | ) -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/models/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 6B/strategies/models/rf_regressor.joblib -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/models/sv_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Eclipse Projects/Section 6B/strategies/models/sv_regressor.joblib -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/run_zipline.py: -------------------------------------------------------------------------------- 1 | from toolz import merge 2 | from zipline import run_algorithm 3 | from zipline.utils.calendars import register_calendar, get_calendar 4 | from strategies.buy_and_hold import BuyAndHold 5 | from strategies.auto_correlation import AutoCorrelation 6 | from os import environ 7 | from strategies.scalping import ScalpBollingerBand 8 | import pandas as pd 9 | import os 10 | import pytz 11 | from collections import OrderedDict 12 | from strategies.calendar import CryptoCalendar 13 | 14 | 15 | # Columns that we expect to be able to reliably deterministic 16 | # Doesn't include fields that have UUIDS. 17 | _cols_to_check = [ 18 | 'algo_volatility', 19 | 'algorithm_period_return', 20 | 'alpha', 21 | 'benchmark_period_return', 22 | 'benchmark_volatility', 23 | 'beta', 24 | 'capital_used', 25 | 'ending_cash', 26 | 'ending_exposure', 27 | 'ending_value', 28 | 'excess_return', 29 | 'gross_leverage', 30 | 'long_exposure', 31 | 'long_value', 32 | 'longs_count', 33 | 'max_drawdown', 34 | 'max_leverage', 35 | 'net_leverage', 36 | 'period_close', 37 | 'period_label', 38 | 'period_open', 39 | 'pnl', 40 | 'portfolio_value', 41 | 'positions', 42 | 'returns', 43 | 'short_exposure', 44 | 'short_value', 45 | 'shorts_count', 46 | 'sortino', 47 | 'starting_cash', 48 | 'starting_exposure', 49 | 'starting_value', 50 | 'trading_days', 51 | 'treasury_period_return', 52 | ] 53 | 54 | 55 | def prepareCSV(csv_pth): 56 | files = os.listdir(csv_pth) 57 | start = end = None 58 | 59 | dd = OrderedDict() 60 | for f in files: 61 | fp = os.path.join(csv_pth, f) 62 | n1 = os.path.splitext(fp)[0] 63 | key = n1.split('/')[1] 64 | df = pd.read_csv(fp) 65 | df.index = pd.DatetimeIndex(df.date) 66 | df = df.sort_index() 67 | dd[key] = df.drop(columns=['date']) 68 | start = df.index.values[0] 69 | end = df.index.values[10*24*60] 70 | 71 | panel = pd.Panel(dd) 72 | 73 | panel.major_axis = panel.major_axis.tz_localize(pytz.utc) 74 | 75 | return panel, pd.to_datetime(start).tz_localize(pytz.utc), pd.to_datetime(end).tz_localize(pytz.utc) 76 | 77 | 78 | def run_strategy(strategy_name): 79 | mod = None 80 | 81 | if strategy_name == "buy_and_hold": 82 | mod = BuyAndHold() 83 | elif strategy_name == "auto_correlation": 84 | mod = AutoCorrelation() 85 | elif strategy_name == "scalping": 86 | mod = ScalpBollingerBand() 87 | 88 | # register_calendar("YAHOO", get_calendar("NYSE"), force=True) 89 | data_panel, start, end = prepareCSV('csv') 90 | print(data_panel, type(start)) 91 | 92 | return run_algorithm( 93 | data=data_panel, 94 | trading_calendar=CryptoCalendar(), 95 | initialize=getattr(mod, 'initialize', None), 96 | handle_data=getattr(mod, 'handle_data', None), 97 | before_trading_start=getattr(mod, 'before_trading_start', None), 98 | analyze=getattr(mod, 'analyze', None), 99 | # bundle='quandl', 100 | environ=environ, 101 | data_frequency='minute', 102 | # Provide a default capital base, but allow the test to override. 103 | **merge({ 104 | 'capital_base': 1000, 105 | 'start': start, 106 | 'end': end 107 | }, mod._test_args()) 108 | ) 109 | -------------------------------------------------------------------------------- /Eclipse Projects/Section 6B/strategies/scalping.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | from joblib import load 6 | 7 | 8 | class ScalpBollingerBand: 9 | 10 | stocks = ['BTCUSD', 'ETHUSD'] 11 | ma1 = 10 12 | ma2 = 120 13 | steps = 1280 14 | stop_loss = 0.005 15 | stdv = 0.5 16 | 17 | 18 | def initialize(self, context): 19 | context.stocks = self.stocks 20 | context.asset = symbol(self.stocks[-1]) 21 | 22 | context.burndown = 0 23 | context.number_shorts = 0 24 | context.number_longs = 0 25 | 26 | context.position = {} 27 | for stock in self.stocks: 28 | context.position[stock] = None 29 | 30 | # VaR 31 | context.historical_returns = [] 32 | 33 | #SVR 34 | context.regressor = load('./strategies/models/sv_regressor.joblib') 35 | 36 | 37 | def handle_data(self, context, data): 38 | # wait till enough historical data arrives for calculations 39 | context.burndown += 1 40 | 41 | # log while backtesting 42 | if context.burndown % 1000 == 0: 43 | print(context.burndown) 44 | 45 | # calculate VaR only when there is enough data 46 | if len(context.historical_returns) > 15: 47 | 48 | # Non-Parametric Historical Value at Risk 49 | 50 | # history 51 | historical_returns = np.array(context.historical_returns) 52 | 53 | # forecast 54 | forecast_returns = context.regressor.predict( 55 | historical_returns[-15:].reshape(1, -1) 56 | ) 57 | 58 | # VaR 59 | lowest_percentile = np.percentile( 60 | np.concatenate( 61 | ( 62 | historical_returns, 63 | forecast_returns[0] 64 | ), axis=0 65 | ), 0.05) 66 | expected_shortfall = np.mean( 67 | np.where( 68 | historical_returns <= lowest_percentile 69 | ) 70 | ) 71 | 72 | # stop loss value 73 | value_at_risk = expected_shortfall / 60 / 24 74 | 75 | # exit all positions 76 | if ( context.portfolio.returns <= value_at_risk ): 77 | # loop stocks in portfolio 78 | for i, stock in enumerate(context.stocks): 79 | # are we in a trade? 80 | if context.position[stock] == 'trade': 81 | # short position 82 | order(symbol(stock), 0) 83 | context.position[stock] = None 84 | context.number_shorts += 1 85 | print('Stop Loss: {} @ VaR {} for {}'.format( 86 | context.portfolio.returns, 87 | value_at_risk, 88 | stock 89 | ) 90 | ) 91 | 92 | 93 | # trade only when there is enough data 94 | if context.burndown > self.steps: 95 | 96 | # loop stocks in portfolio 97 | for i, stock in enumerate(context.stocks): 98 | # history 99 | hist = data.history( 100 | symbol(stock), 101 | 'price', 102 | bar_count=self.steps, 103 | frequency='1m') 104 | 105 | # bollinger bands 106 | blw = hist.mean() - self.stdv * hist.std() 107 | bhi = hist.mean() + self.stdv * hist.std() 108 | 109 | # moving average short 110 | short_term = data.history( 111 | symbol(stock), 112 | 'price', 113 | bar_count=self.ma1, 114 | frequency='1m').mean() 115 | 116 | # moving average long 117 | long_term = data.history( 118 | symbol(stock), 119 | 'price', 120 | bar_count=self.ma2, 121 | frequency='1m').mean() 122 | 123 | # fetch our basket status 124 | cpp = context.portfolio.positions 125 | 126 | # map basket to symbol:shares pairs 127 | cpp_symbols = map(lambda x: x.symbol, cpp) 128 | 129 | # check indicator signal 130 | if short_term >= long_term and context.position[stock] != 'trade': 131 | context.position[stock] = 'long' 132 | elif short_term <= long_term and context.position[stock] == 'trade': 133 | context.position[stock] = 'short' 134 | 135 | 136 | # what is current price 137 | current_price = data.current(symbol(stock), 'price') 138 | 139 | 140 | # check bollinger bands 141 | if short_term >= bhi and context.position[stock] == 'long': 142 | # how many shares I can afford? 143 | num_shares = context.portfolio.cash // current_price 144 | 145 | # long position 146 | order(symbol(stock), num_shares) # order_value 147 | context.position[stock] = 'trade' 148 | context.number_longs += 1 149 | print('Enter Trade: ', stock) 150 | 151 | elif (current_price <= blw and context.position[stock] == 'trade') \ 152 | or (short_term <= blw and context.position[stock] == 'short'): 153 | # short position 154 | order(symbol(stock), 0) 155 | context.position[stock] = None 156 | context.number_shorts += 1 157 | print('Exit Trade: ', stock) 158 | 159 | 160 | # what is the price paid on beginning of trade 161 | last_price = cpp[symbol(stock)].last_sale_price 162 | 163 | # stop loss value 164 | val = last_price - last_price * self.stop_loss 165 | 166 | # are we in a trade? 167 | if context.position[stock] == 'trade': 168 | # stop loss violated 169 | if current_price < val: 170 | # short position 171 | order(symbol(stock), 0) 172 | context.position[stock] = None 173 | context.number_shorts += 1 174 | print('Stop Loss: ', stock) 175 | 176 | # is last stock? 177 | if i == len(self.stocks) - 1: 178 | 179 | # record price, ma1, ma2, Bollinger bands 180 | record(REC_PRICE=current_price) 181 | record(REC_MA1=short_term) 182 | record(REC_MA2=long_term) 183 | record(REC_BB1=blw) 184 | record(REC_BB2=bhi) 185 | 186 | context.historical_returns.append(context.portfolio.returns) 187 | 188 | # record positions count 189 | record(REC_NUM_SHORTS=context.number_shorts) 190 | record(REC_NUM_LONGS=context.number_longs) 191 | 192 | def _test_args(self): 193 | return { 194 | # 'start': pd.Timestamp('2017', tz='utc'), 195 | # 'end': pd.Timestamp('2018', tz='utc'), 196 | # 'capital_base': 1e7, 197 | # 'data_frequency': 'minute' 198 | } 199 | 200 | def analyze(self, context, perf): 201 | # init figure 202 | fig = plt.figure() 203 | 204 | # plot recorded data 205 | ax1 = fig.add_subplot(211) 206 | perf.plot(y=[ 207 | 'REC_PRICE', 208 | 'REC_MA1', 209 | 'REC_MA2' 210 | ], ax=ax1) 211 | ax1.set_ylabel('price in $') 212 | 213 | # plot recorded data 214 | ax2 = fig.add_subplot(212) 215 | perf.plot(y=[ 216 | 'REC_PRICE', 217 | 'REC_BB1', 218 | 'REC_BB2' 219 | ], ax=ax2) 220 | ax2.set_ylabel('Bollinger Bands') 221 | 222 | # add spacing between plots 223 | plt.subplots_adjust(hspace=1) 224 | 225 | # display plot 226 | plt.show() 227 | -------------------------------------------------------------------------------- /Images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Images/1.png -------------------------------------------------------------------------------- /Images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Images/2.png -------------------------------------------------------------------------------- /Images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Images/3.png -------------------------------------------------------------------------------- /Images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Images/4.png -------------------------------------------------------------------------------- /Images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Images/5.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Lecture Notebooks/Lectures Notebooks.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Lecture Notebooks/Lectures Notebooks.zip -------------------------------------------------------------------------------- /Lecture Notebooks/Lectures Notebooks/section 0002/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Lecture Notebooks/Lectures Notebooks/section 0002/rf_regressor.joblib -------------------------------------------------------------------------------- /Lecture Notebooks/Lectures Notebooks/section 0005/scalping.csv: -------------------------------------------------------------------------------- 1 | ,REC_BB1,REC_BB2,REC_MA1,REC_MA2,REC_NUM_LONGS,REC_NUM_SHORTS,REC_PRICE,algo_volatility,algorithm_period_return,alpha,benchmark_period_return,benchmark_volatility,beta,capital_used,ending_cash,ending_exposure,ending_value,excess_return,gross_leverage,long_exposure,long_value,longs_count,max_drawdown,max_leverage,net_leverage,orders,period_close,period_label,period_open,pnl,portfolio_value,positions,returns,sharpe,short_exposure,short_value,shorts_count,sortino,starting_cash,starting_exposure,starting_value,trading_days,transactions,treasury_period_return 2 | 2017-01-01 23:59:00+00:00,8.290873610186098,8.419001389814218,8.239999999999998,8.20466666666668,1,0,8.24,,0.00016607600000018152,,0.0,,,-997.73962,4002.2603799999997,998.57,998.57,0.0,0.1996808378051807,998.57,998.57,1,0.0,0.1996808378051807,0.1996808378051807,"[{'id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'dt': Timestamp('2017-01-01 23:02:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-01 21:20:00+0000', tz='UTC'), 'amount': 4, 'filled': 1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 0}]",2017-01-01 23:59:00+00:00,2017-01,2017-01-01 00:00:00+00:00,0.8303799999994226,5000.830379999999,"[{'sid': Equity(0 [BTCUSD]), 'amount': 1, 'cost_basis': 997.73962, 'last_sale_price': 998.57}]",0.00016607600000018152,,0.0,0.0,0,,5000.0,0.0,0.0,1,"[{'amount': 1, 'dt': Timestamp('2017-01-01 23:02:00+0000', tz='UTC'), 'price': 997.73862, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}]",0.0 3 | 2017-01-02 23:59:00+00:00,8.229591428522099,8.348142946477786,8.549999999999999,8.516583333333317,14,1,8.55,0.25063976714675607,0.022664652999999646,,0.0,0.0,,-2750.337115000005,1251.9232649999994,3861.3999999999996,3861.3999999999996,0.0,1.240074149702718,5101.15,5101.15,1,0.0,1.240074149702718,0.7551644595660041,"[{'id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'dt': Timestamp('2017-01-02 02:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-01 21:20:00+0000', tz='UTC'), 'amount': 4, 'filled': 4, 'commission': 0.004, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '0dc7b9a4039447f0b2aa9fa8da0163e9', 'dt': Timestamp('2017-01-02 02:50:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 01:09:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'cbd0c02309134d639dd8832df0997f1a', 'dt': Timestamp('2017-01-02 09:36:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 01:43:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'd4826b1519a84408b4701956c327ad9b', 'dt': Timestamp('2017-01-02 10:34:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 07:02:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '5c5e4fdebdf740d080ee95b2ccd8e245', 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 07:51:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'd790b59c26d84cf2a696184a326949f5', 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 08:09:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '329dc12445414db2bdfc6c6a436327cd', 'dt': Timestamp('2017-01-02 15:07:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 14:23:00+0000', tz='UTC'), 'amount': 3, 'filled': 3, 'commission': 0.003, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'ed19eb9f554e4cb383432238dbe92ef6', 'dt': Timestamp('2017-01-02 15:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 15:05:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '5eaf700a9fc84f90aa0a462fe963f546', 'dt': Timestamp('2017-01-02 19:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 18:34:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '51367f148dc541f2b118e146d2f5c02c', 'dt': Timestamp('2017-01-02 19:43:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 18:36:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'bcd83064e86c45269146d0478f9cbc17', 'dt': Timestamp('2017-01-02 21:08:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 21:02:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '16d3dc4b2ba84701b21bba3b49577330', 'dt': Timestamp('2017-01-02 21:13:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 21:13:00+0000', tz='UTC'), 'amount': 18, 'filled': 0, 'commission': 0, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 0}, {'id': '4bd104678844422485329584822aba92', 'dt': Timestamp('2017-01-02 23:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 16:17:00+0000', tz='UTC'), 'amount': -243, 'filled': -145, 'commission': 0.14500000000000002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 0}]",2017-01-02 23:59:00+00:00,2017-01,2017-01-02 00:00:00+00:00,112.49288499999966,5113.323264999999,"[{'sid': Equity(0 [BTCUSD]), 'amount': 5, 'cost_basis': 1017.9654975969391, 'last_sale_price': 1020.23}, {'sid': Equity(1 [ETHUSD]), 'amount': -145, 'cost_basis': 8.50571003448276, 'last_sale_price': 8.55}]",0.022494841146761146,11.391949461954654,-1239.75,-1239.75,1,,4002.2603799999997,998.57,998.57,2,"[{'amount': 1, 'dt': Timestamp('2017-01-02 00:20:00+0000', tz='UTC'), 'price': 997.99875, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 00:56:00+0000', tz='UTC'), 'price': 995.4975, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 02:29:00+0000', tz='UTC'), 'price': 998.77914, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 02:42:00+0000', tz='UTC'), 'price': 1002.7211100000001, 'order_id': '0dc7b9a4039447f0b2aa9fa8da0163e9', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 02:50:00+0000', tz='UTC'), 'price': 1004.0517749999999, 'order_id': '0dc7b9a4039447f0b2aa9fa8da0163e9', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 04:18:00+0000', tz='UTC'), 'price': 1011.0952950000001, 'order_id': 'cbd0c02309134d639dd8832df0997f1a', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 09:36:00+0000', tz='UTC'), 'price': 1014.296895, 'order_id': 'cbd0c02309134d639dd8832df0997f1a', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 09:37:00+0000', tz='UTC'), 'price': 1013.2931, 'order_id': 'd4826b1519a84408b4701956c327ad9b', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 10:34:00+0000', tz='UTC'), 'price': 1019.19015, 'order_id': 'd4826b1519a84408b4701956c327ad9b', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 11:19:00+0000', tz='UTC'), 'price': 1020.759365, 'order_id': '5c5e4fdebdf740d080ee95b2ccd8e245', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'price': 1020.999245, 'order_id': '5c5e4fdebdf740d080ee95b2ccd8e245', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -2, 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'price': 1020.999245, 'order_id': 'd790b59c26d84cf2a696184a326949f5', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 14:50:00+0000', tz='UTC'), 'price': 1020.499995, 'order_id': '329dc12445414db2bdfc6c6a436327cd', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-02 15:07:00+0000', tz='UTC'), 'price': 1020.499995, 'order_id': '329dc12445414db2bdfc6c6a436327cd', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-02 15:29:00+0000', tz='UTC'), 'price': 1023.501495, 'order_id': 'ed19eb9f554e4cb383432238dbe92ef6', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -6, 'dt': Timestamp('2017-01-02 17:26:00+0000', tz='UTC'), 'price': 8.365815, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 17:29:00+0000', tz='UTC'), 'price': 8.365815, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -4, 'dt': Timestamp('2017-01-02 17:35:00+0000', tz='UTC'), 'price': 8.41579, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -4, 'dt': Timestamp('2017-01-02 18:02:00+0000', tz='UTC'), 'price': 8.41579, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 18:15:00+0000', tz='UTC'), 'price': 8.41579, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -2, 'dt': Timestamp('2017-01-02 19:29:00+0000', tz='UTC'), 'price': 1018.460515, 'order_id': '5eaf700a9fc84f90aa0a462fe963f546', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -2, 'dt': Timestamp('2017-01-02 19:43:00+0000', tz='UTC'), 'price': 1018.5404749999999, 'order_id': '51367f148dc541f2b118e146d2f5c02c', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 21:07:00+0000', tz='UTC'), 'price': 1021.520505, 'order_id': 'bcd83064e86c45269146d0478f9cbc17', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 21:08:00+0000', tz='UTC'), 'price': 1019.419455, 'order_id': 'bcd83064e86c45269146d0478f9cbc17', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -5, 'dt': Timestamp('2017-01-02 21:24:00+0000', tz='UTC'), 'price': 8.475760000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -15, 'dt': Timestamp('2017-01-02 22:17:00+0000', tz='UTC'), 'price': 8.505745, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -76, 'dt': Timestamp('2017-01-02 23:26:00+0000', tz='UTC'), 'price': 8.51574, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -33, 'dt': Timestamp('2017-01-02 23:29:00+0000', tz='UTC'), 'price': 8.545725000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}]",0.0 4 | 2017-01-03 23:59:00+00:00,8.660496173953051,9.314956951046982,9.793000000000001,9.841999999999992,29,4,9.75,0.46890256850870604,-0.014187915000001605,2.8552755604919273,0.007650322201503856,0.07011636115838527,-6.1914107377890915,-1246.0428400000042,5.8804250000000176,4923.18,4923.18,0.0,1.5210160463796707,6210.18,6210.18,1,-0.03603582845255648,1.5210160463796707,0.9988069886564638,"[{'id': '6782718462674593a30ba211a52a41a1', 'dt': Timestamp('2017-01-03 00:55:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 00:26:00+0000', tz='UTC'), 'amount': 1, 'filled': 1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '4bd104678844422485329584822aba92', 'dt': Timestamp('2017-01-03 10:57:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 16:17:00+0000', tz='UTC'), 'amount': -243, 'filled': -243, 'commission': 0.24300000000000002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '039494f935a54bdda32bf258cd94ecd5', 'dt': Timestamp('2017-01-03 13:25:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 12:38:00+0000', tz='UTC'), 'amount': 1, 'filled': 1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '16d3dc4b2ba84701b21bba3b49577330', 'dt': Timestamp('2017-01-03 15:16:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 21:13:00+0000', tz='UTC'), 'amount': 18, 'filled': 18, 'commission': 0.018, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '5225b83b6fb74b89a011effe25113606', 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 10:31:00+0000', tz='UTC'), 'amount': 118, 'filled': 118, 'commission': 0.118, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '79a448aa39ca43ce8cc09807485054df', 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 14:34:00+0000', tz='UTC'), 'amount': -1, 'filled': -1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '2b17444302ad4f62bcb1a4bb78169d0e', 'dt': Timestamp('2017-01-03 18:37:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 17:26:00+0000', tz='UTC'), 'amount': -78, 'filled': -78, 'commission': 0.078, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': 'add63a5adc8948e58722df76981b05dd', 'dt': Timestamp('2017-01-03 18:52:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 18:51:00+0000', tz='UTC'), 'amount': -1, 'filled': -1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '80ef93cbbf204567a51aba41ffb416a9', 'dt': Timestamp('2017-01-03 21:08:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 19:32:00+0000', tz='UTC'), 'amount': 54, 'filled': 54, 'commission': 0.054, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}]",2017-01-03 23:59:00+00:00,2017-01,2017-01-03 00:00:00+00:00,-184.2628399999985,4929.060425000001,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 1035.03}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 9.75}]",-0.036035828452556595,-2.3960042557667136,-1287.0,-1287.0,1,-3.401700257998596,1251.9232649999994,3861.3999999999996,3861.3999999999996,3,"[{'amount': 1, 'dt': Timestamp('2017-01-03 00:55:00+0000', tz='UTC'), 'price': 1028.684085, 'order_id': '6782718462674593a30ba211a52a41a1', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -5, 'dt': Timestamp('2017-01-03 00:57:00+0000', tz='UTC'), 'price': 8.465765000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -14, 'dt': Timestamp('2017-01-03 03:05:00+0000', tz='UTC'), 'price': 8.305845, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -26, 'dt': Timestamp('2017-01-03 06:37:00+0000', tz='UTC'), 'price': 8.3958, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -36, 'dt': Timestamp('2017-01-03 06:48:00+0000', tz='UTC'), 'price': 8.3958, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -13, 'dt': Timestamp('2017-01-03 10:29:00+0000', tz='UTC'), 'price': 8.545725000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -4, 'dt': Timestamp('2017-01-03 10:57:00+0000', tz='UTC'), 'price': 8.545725000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 10:57:00+0000', tz='UTC'), 'price': 8.554275, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 13:25:00+0000', tz='UTC'), 'price': 1020.920205, 'order_id': '039494f935a54bdda32bf258cd94ecd5', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 14:34:00+0000', tz='UTC'), 'price': 8.72436, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 14:39:00+0000', tz='UTC'), 'price': 8.74437, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 14:57:00+0000', tz='UTC'), 'price': 8.74437, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 4, 'dt': Timestamp('2017-01-03 14:58:00+0000', tz='UTC'), 'price': 8.74437, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 4, 'dt': Timestamp('2017-01-03 15:04:00+0000', tz='UTC'), 'price': 8.96448, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 15:09:00+0000', tz='UTC'), 'price': 8.864429999999999, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 15:16:00+0000', tz='UTC'), 'price': 8.984490000000001, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 6, 'dt': Timestamp('2017-01-03 15:16:00+0000', tz='UTC'), 'price': 8.984490000000001, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 15:17:00+0000', tz='UTC'), 'price': 9.0045, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 7, 'dt': Timestamp('2017-01-03 15:22:00+0000', tz='UTC'), 'price': 9.44472, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 25, 'dt': Timestamp('2017-01-03 15:23:00+0000', tz='UTC'), 'price': 9.44472, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 15:27:00+0000', tz='UTC'), 'price': 9.96498, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 15:37:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 15:56:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 16:00:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 16:01:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 16:02:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 16:13:00+0000', tz='UTC'), 'price': 9.50475, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 16:32:00+0000', tz='UTC'), 'price': 9.784889999999999, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 17:23:00+0000', tz='UTC'), 'price': 9.98499, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 17:34:00+0000', tz='UTC'), 'price': 9.554775000000001, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 6, 'dt': Timestamp('2017-01-03 17:41:00+0000', tz='UTC'), 'price': 9.754875, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 40, 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'price': 9.90495, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'price': 9.895050000000001, 'order_id': '79a448aa39ca43ce8cc09807485054df', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -32, 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'price': 9.895050000000001, 'order_id': '2b17444302ad4f62bcb1a4bb78169d0e', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -46, 'dt': Timestamp('2017-01-03 18:37:00+0000', tz='UTC'), 'price': 9.895050000000001, 'order_id': '2b17444302ad4f62bcb1a4bb78169d0e', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-03 18:52:00+0000', tz='UTC'), 'price': 1024.177655, 'order_id': 'add63a5adc8948e58722df76981b05dd', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 6, 'dt': Timestamp('2017-01-03 19:36:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 10, 'dt': Timestamp('2017-01-03 19:48:00+0000', tz='UTC'), 'price': 9.84492, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 19:52:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 8, 'dt': Timestamp('2017-01-03 19:53:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 20:00:00+0000', tz='UTC'), 'price': 9.834915, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 20:01:00+0000', tz='UTC'), 'price': 9.824910000000001, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 14, 'dt': Timestamp('2017-01-03 20:07:00+0000', tz='UTC'), 'price': 9.824910000000001, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 20:55:00+0000', tz='UTC'), 'price': 9.454725, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 21:02:00+0000', tz='UTC'), 'price': 9.654825, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 21:08:00+0000', tz='UTC'), 'price': 9.50475, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}]",0.0 5 | 2017-01-04 23:59:00+00:00,10.659356969423053,10.87315865557695,11.168000000000003,10.99908333333334,49,4,11.21,0.8597321908218044,0.0770240849999968,4.884971632937453,0.01364482250735044,0.06328773075372535,0.11843169802167909,0.0,5.8804250000000176,5379.240000000001,5379.240000000001,0.0,1.5484667643249592,6858.960000000001,6858.960000000001,1,-0.03603582845255648,1.5484667643249592,0.9989080234914152,[],2017-01-04 23:59:00+00:00,2017-01,2017-01-04 00:00:00+00:00,456.0600000000004,5385.120425000001,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 1143.16}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 11.21}]",0.09252473304787956,5.799990768037722,-1479.72,-1479.72,1,17.43354491658354,5.8804250000000176,4923.18,4923.18,4,[],0.0 6 | 2017-01-05 23:59:00+00:00,10.430453581021212,11.128562043978846,10.340000000000002,10.30658333333333,57,6,10.34,1.3143939912614633,-0.06599191500000101,-8.112422976586277,0.0128395497495013,0.06237491853969911,8.381374549210223,0.0,5.8804250000000176,4664.16,4664.16,0.0,1.5832668086593704,6029.04,6029.04,1,-0.1327881168042759,1.5832668086593704,0.9987408192510453,[],2017-01-05 23:59:00+00:00,2017-01,2017-01-05 00:00:00+00:00,-715.0800000000008,4670.040425,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 1004.84}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.34}]",-0.13278811680427582,-2.0567425666180568,-1364.8799999999999,-1364.8799999999999,1,-2.767581488011503,5.8804250000000176,5379.240000000001,5379.240000000001,5,[],0.0 7 | 2017-01-06 23:59:00+00:00,9.99067774200546,10.175978507994365,10.200000000000001,10.181583333333359,59,6,10.2,1.4402369974664968,-0.1959159149999985,-12.587722600092285,0.016463046157883188,0.05617747941484457,6.5292877250752674,0.0,5.8804250000000176,4014.540000000001,4014.540000000001,0.0,1.668318059049757,5360.9400000000005,5360.9400000000005,1,-0.25342051658946535,1.668318059049757,0.9985373606791385,[],2017-01-06 23:59:00+00:00,2017-01,2017-01-06 00:00:00+00:00,-649.6199999999994,4020.4204250000007,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 893.49}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.2}]",-0.139103720927638,-5.620717066575118,-1346.3999999999999,-1346.3999999999999,1,-6.3842337674782605,5.8804250000000176,4664.16,4664.16,6,[],0.0 8 | 2017-01-07 23:59:00+00:00,9.67500276053733,9.923965989462646,10.049999999999999,10.026333333333342,68,7,10.05,1.3597317766681372,-0.17526391500000038,-8.352027142886207,0.016463046157883188,0.05383594218578734,3.9641603261721796,0.0,5.8804250000000176,4117.799999999999,4117.799999999999,0.0,1.6419798098200107,5444.4,5444.4,1,-0.25342051658946535,1.668318059049757,0.998573986246764,[],2017-01-07 23:59:00+00:00,2017-01,2017-01-07 00:00:00+00:00,103.25999999999885,4123.680425,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 907.4}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.05}]",0.025683881058282676,-4.422999418512168,-1326.6000000000001,-1326.6000000000001,1,-5.12302667818816,5.8804250000000176,4014.540000000001,4014.540000000001,7,[],0.0 9 | 2017-01-08 23:59:00+00:00,10.03418671671531,10.165985158284466,10.42,10.278083333333331,167,9,10.42,1.2646884366253217,-0.1771359149999998,-6.937441095755038,0.016463046157883188,0.05154413028874283,3.107490278888933,0.0,5.8804250000000176,4108.4400000000005,4108.4400000000005,0.0,1.6671817679343723,5483.88,5483.88,1,-0.25342051658946535,1.668318059049757,0.998570742092845,[],2017-01-08 23:59:00+00:00,2017-01,2017-01-08 00:00:00+00:00,-9.359999999998763,4114.320425000001,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 913.98}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.42}]",-0.0022698170166756126,-4.2175055388358995,-1375.44,-1375.44,1,-4.856936753133122,5.8804250000000176,4117.799999999999,4117.799999999999,8,[],0.0 10 | 2017-01-09 23:59:00+00:00,10.423694594171101,10.645258530828825,10.379999999999999,10.348416666666687,178,11,10.38,1.1835024020325289,-0.18923191499999947,-5.8858513455979855,0.013107974002117606,0.05590786581657495,2.0013555284676707,0.0,5.8804250000000176,4047.96,4047.96,0.0,1.674530639671146,5418.12,5418.12,1,-0.25342051658946535,1.674530639671146,0.9985494187280448,[],2017-01-09 23:59:00+00:00,2017-01,2017-01-09 00:00:00+00:00,-60.48000000000093,4053.840425,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 903.02}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.38}]",-0.014699875982556287,-4.353839226023117,-1370.16,-1370.16,1,-4.9627100911351105,5.8804250000000176,4108.4400000000005,4108.4400000000005,9,[],0.0 11 | 2017-01-10 23:59:00+00:00,10.458049235339931,10.595966389659932,10.67,10.69175000000001,190,13,10.67,1.1185433761538153,-0.19320391500000111,-5.342013637027109,0.013107974002117606,0.05321307558572865,1.7625972072434188,0.0,5.8804250000000176,4028.1,4028.1,0.0,1.6968302467655132,5436.54,5436.54,1,-0.25342051658946535,1.6968302467655132,0.9985422772595631,[],2017-01-10 23:59:00+00:00,2017-01,2017-01-10 00:00:00+00:00,-19.860000000000127,4033.9804249999997,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 906.09}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.67}]",-0.004899058156688119,-4.256390615601364,-1408.44,-1408.44,1,-4.831868520092666,5.8804250000000176,4047.96,4047.96,10,[],0.0 12 | 2017-01-11 23:59:00+00:00,9.916638239298495,10.32126801070167,9.97,9.872500000000002,197,14,9.97,1.271073092285016,-0.3263919150000011,-8.027182898229908,0.015971012028732856,0.05100241180843514,-0.22734819260468958,0.0,5.8804250000000176,3362.1600000000008,3362.1600000000008,0.0,1.7797411086596444,4678.200000000001,4678.200000000001,1,-0.3745654397320179,1.7797411086596444,0.9982540515379948,[],2017-01-11 23:59:00+00:00,2017-01,2017-01-11 00:00:00+00:00,-665.9399999999991,3368.0404250000006,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 779.7}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 9.97}]",-0.16508260572434508,-6.380463625438262,-1316.0400000000002,-1316.0400000000002,1,-6.606576507659419,5.8804250000000176,4028.1,4028.1,11,[],0.0 13 | -------------------------------------------------------------------------------- /Lecture Notebooks/Lectures Notebooks/section 0006/estimator.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/Lecture Notebooks/Lectures Notebooks/section 0006/estimator.joblib -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Machine-Learning-for-Algorithmic-Trading-Bots-with-Python 5 | This is the code repository for [Machine Learning for Algorithmic Trading Bots with Python [Video]](https://www.packtpub.com/application-development/machine-learning-algorithmic-trading-bots-python-video), published by [Packt](https://www.packtpub.com/?utm_source=github). It contains all the supporting project files necessary to work through the video course from start to finish. 6 | ## About the Video Course 7 | Have you ever wondered how the Stock Market, Forex, Cryptocurrency and Online Trading works? Have you ever wanted to become a rich trader having your computers work and make money for you while you’re away for a trip in the Maldives? Ever wanted to land a decent job in a brokerage, bank, or any other prestigious financial institution?We have compiled this course for you in order to seize your moment and land your dream job in financial sector. This course covers the advances in the techniques developed for algorithmic trading and financial analysis based on the recent breakthroughs in machine learning. We leverage the classic techniques widely used and applied by financial data scientists to equip you with the necessary concepts and modern tools to reach a common ground with financial professionals and conquer your next interview.By the end of the course, you will gain a solid understanding of financial terminology and methodology and a hands-on experience in designing and building financial machine learning models. You will be able to evaluate and validate different algorithmic trading strategies. We have a dedicated section to backtesting which is the holy grail of algorithmic trading and is an essential key to successful deployment of reliable algorithms. 8 | 9 | The code bundle for this video course is available at - https://github.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python 10 | 11 |

What You Will Learn

12 |
13 |
21 | 22 | ## Instructions and Navigation 23 | ### Assumed Knowledge 24 | To fully benefit from the coverage included in this course, you will need:
25 | This course is compiled for data science beginners and professionals who want to shift their career to financial sector. This course assumes a basic knowledge of Python programming such as conditional and looping statements. The course is self contained in terms of the concepts, theories, and technologies it requires to build trading bots. 26 | ### Technical Requirements 27 | This course has the following software requirements:
28 | Eclipse Photon with PyDev Plugin, Latest Version 29 | Anaconda platform 30 | Google Chrome 31 | 32 | 33 | 34 | 35 | ## Related Products 36 | * [Machine Learning for Algorithmic Trading Bots with Python [Video]](https://www.packtpub.com/application-development/machine-learning-algorithmic-trading-bots-python-video) 37 | 38 | * [Hands-On Machine Learning using JavaScript [Video]](https://www.packtpub.com/application-development/hands-machine-learning-using-javascript-video) 39 | 40 | * [Python Machine Learning By Example - Second Edition](https://www.packtpub.com/big-data-and-business-intelligence/getting-started-tensorflow-deep-learning-video) 41 | -------------------------------------------------------------------------------- /buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | from joblib import load 5 | import numpy as np 6 | 7 | 8 | class BuyAndHold: 9 | 10 | stocks = ['AAPL', 'MSFT', 'TSLA'] 11 | lag = 33 12 | forecast = 8 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol('AAPL') 18 | context.regressor = load('./strategies/models/rf_regressor.joblib') 19 | 20 | def handle_data(self, context, data): 21 | for stock in context.stocks: 22 | timeseries = data.history( 23 | symbol(stock), 24 | 'price', 25 | bar_count=self.lag, 26 | frequency='1d') 27 | np_timeseries = np.array(timeseries.values).reshape(1, -1) 28 | preds = context.regressor.predict(np_timeseries) 29 | max_price = np.max(preds) 30 | historical_mean = np.mean(np_timeseries) 31 | 32 | if max_price > historical_mean: 33 | order(symbol(stock), 1000) 34 | 35 | if max_price < historical_mean: 36 | order(symbol(stock), -1000) 37 | 38 | record(AAPL=data.current(context.asset, 'price')) 39 | 40 | def _test_args(self): 41 | return { 42 | 'start': pd.Timestamp('2017', tz='utc'), 43 | 'end': pd.Timestamp('2018', tz='utc'), 44 | 'capital_base': 1e7 45 | } 46 | 47 | def analyze(self, context, perf): 48 | fig = plt.figure() 49 | ax1 = fig.add_subplot(211) 50 | perf.portfolio_value.plot(ax=ax1) 51 | ax1.set_ylabel('portfolio value in $') 52 | 53 | ax2 = fig.add_subplot(212) 54 | perf['AAPL'].plot(ax=ax2) 55 | 56 | ax2.set_ylabel('price in $') 57 | plt.legend(loc=0) 58 | plt.show() 59 | -------------------------------------------------------------------------------- /packtpub-machine-learning-algo-trading-bots-src-code.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/packtpub-machine-learning-algo-trading-bots-src-code.zip -------------------------------------------------------------------------------- /section 0002/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/section 0002/rf_regressor.joblib -------------------------------------------------------------------------------- /section 0005/scalping.csv: -------------------------------------------------------------------------------- 1 | ,REC_BB1,REC_BB2,REC_MA1,REC_MA2,REC_NUM_LONGS,REC_NUM_SHORTS,REC_PRICE,algo_volatility,algorithm_period_return,alpha,benchmark_period_return,benchmark_volatility,beta,capital_used,ending_cash,ending_exposure,ending_value,excess_return,gross_leverage,long_exposure,long_value,longs_count,max_drawdown,max_leverage,net_leverage,orders,period_close,period_label,period_open,pnl,portfolio_value,positions,returns,sharpe,short_exposure,short_value,shorts_count,sortino,starting_cash,starting_exposure,starting_value,trading_days,transactions,treasury_period_return 2 | 2017-01-01 23:59:00+00:00,8.290873610186098,8.419001389814218,8.239999999999998,8.20466666666668,1,0,8.24,,0.00016607600000018152,,0.0,,,-997.73962,4002.2603799999997,998.57,998.57,0.0,0.1996808378051807,998.57,998.57,1,0.0,0.1996808378051807,0.1996808378051807,"[{'id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'dt': Timestamp('2017-01-01 23:02:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-01 21:20:00+0000', tz='UTC'), 'amount': 4, 'filled': 1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 0}]",2017-01-01 23:59:00+00:00,2017-01,2017-01-01 00:00:00+00:00,0.8303799999994226,5000.830379999999,"[{'sid': Equity(0 [BTCUSD]), 'amount': 1, 'cost_basis': 997.73962, 'last_sale_price': 998.57}]",0.00016607600000018152,,0.0,0.0,0,,5000.0,0.0,0.0,1,"[{'amount': 1, 'dt': Timestamp('2017-01-01 23:02:00+0000', tz='UTC'), 'price': 997.73862, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}]",0.0 3 | 2017-01-02 23:59:00+00:00,8.229591428522099,8.348142946477786,8.549999999999999,8.516583333333317,14,1,8.55,0.25063976714675607,0.022664652999999646,,0.0,0.0,,-2750.337115000005,1251.9232649999994,3861.3999999999996,3861.3999999999996,0.0,1.240074149702718,5101.15,5101.15,1,0.0,1.240074149702718,0.7551644595660041,"[{'id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'dt': Timestamp('2017-01-02 02:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-01 21:20:00+0000', tz='UTC'), 'amount': 4, 'filled': 4, 'commission': 0.004, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '0dc7b9a4039447f0b2aa9fa8da0163e9', 'dt': Timestamp('2017-01-02 02:50:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 01:09:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'cbd0c02309134d639dd8832df0997f1a', 'dt': Timestamp('2017-01-02 09:36:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 01:43:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'd4826b1519a84408b4701956c327ad9b', 'dt': Timestamp('2017-01-02 10:34:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 07:02:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '5c5e4fdebdf740d080ee95b2ccd8e245', 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 07:51:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'd790b59c26d84cf2a696184a326949f5', 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 08:09:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '329dc12445414db2bdfc6c6a436327cd', 'dt': Timestamp('2017-01-02 15:07:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 14:23:00+0000', tz='UTC'), 'amount': 3, 'filled': 3, 'commission': 0.003, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'ed19eb9f554e4cb383432238dbe92ef6', 'dt': Timestamp('2017-01-02 15:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 15:05:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '5eaf700a9fc84f90aa0a462fe963f546', 'dt': Timestamp('2017-01-02 19:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 18:34:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '51367f148dc541f2b118e146d2f5c02c', 'dt': Timestamp('2017-01-02 19:43:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 18:36:00+0000', tz='UTC'), 'amount': -2, 'filled': -2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': 'bcd83064e86c45269146d0478f9cbc17', 'dt': Timestamp('2017-01-02 21:08:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 21:02:00+0000', tz='UTC'), 'amount': 2, 'filled': 2, 'commission': 0.002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '16d3dc4b2ba84701b21bba3b49577330', 'dt': Timestamp('2017-01-02 21:13:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 21:13:00+0000', tz='UTC'), 'amount': 18, 'filled': 0, 'commission': 0, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 0}, {'id': '4bd104678844422485329584822aba92', 'dt': Timestamp('2017-01-02 23:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 16:17:00+0000', tz='UTC'), 'amount': -243, 'filled': -145, 'commission': 0.14500000000000002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 0}]",2017-01-02 23:59:00+00:00,2017-01,2017-01-02 00:00:00+00:00,112.49288499999966,5113.323264999999,"[{'sid': Equity(0 [BTCUSD]), 'amount': 5, 'cost_basis': 1017.9654975969391, 'last_sale_price': 1020.23}, {'sid': Equity(1 [ETHUSD]), 'amount': -145, 'cost_basis': 8.50571003448276, 'last_sale_price': 8.55}]",0.022494841146761146,11.391949461954654,-1239.75,-1239.75,1,,4002.2603799999997,998.57,998.57,2,"[{'amount': 1, 'dt': Timestamp('2017-01-02 00:20:00+0000', tz='UTC'), 'price': 997.99875, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 00:56:00+0000', tz='UTC'), 'price': 995.4975, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 02:29:00+0000', tz='UTC'), 'price': 998.77914, 'order_id': 'c6ac7aaf43274ba9b6363f12212f9de7', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 02:42:00+0000', tz='UTC'), 'price': 1002.7211100000001, 'order_id': '0dc7b9a4039447f0b2aa9fa8da0163e9', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 02:50:00+0000', tz='UTC'), 'price': 1004.0517749999999, 'order_id': '0dc7b9a4039447f0b2aa9fa8da0163e9', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 04:18:00+0000', tz='UTC'), 'price': 1011.0952950000001, 'order_id': 'cbd0c02309134d639dd8832df0997f1a', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 09:36:00+0000', tz='UTC'), 'price': 1014.296895, 'order_id': 'cbd0c02309134d639dd8832df0997f1a', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 09:37:00+0000', tz='UTC'), 'price': 1013.2931, 'order_id': 'd4826b1519a84408b4701956c327ad9b', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 10:34:00+0000', tz='UTC'), 'price': 1019.19015, 'order_id': 'd4826b1519a84408b4701956c327ad9b', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 11:19:00+0000', tz='UTC'), 'price': 1020.759365, 'order_id': '5c5e4fdebdf740d080ee95b2ccd8e245', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'price': 1020.999245, 'order_id': '5c5e4fdebdf740d080ee95b2ccd8e245', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -2, 'dt': Timestamp('2017-01-02 13:17:00+0000', tz='UTC'), 'price': 1020.999245, 'order_id': 'd790b59c26d84cf2a696184a326949f5', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 14:50:00+0000', tz='UTC'), 'price': 1020.499995, 'order_id': '329dc12445414db2bdfc6c6a436327cd', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-02 15:07:00+0000', tz='UTC'), 'price': 1020.499995, 'order_id': '329dc12445414db2bdfc6c6a436327cd', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-02 15:29:00+0000', tz='UTC'), 'price': 1023.501495, 'order_id': 'ed19eb9f554e4cb383432238dbe92ef6', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -6, 'dt': Timestamp('2017-01-02 17:26:00+0000', tz='UTC'), 'price': 8.365815, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 17:29:00+0000', tz='UTC'), 'price': 8.365815, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -4, 'dt': Timestamp('2017-01-02 17:35:00+0000', tz='UTC'), 'price': 8.41579, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -4, 'dt': Timestamp('2017-01-02 18:02:00+0000', tz='UTC'), 'price': 8.41579, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-02 18:15:00+0000', tz='UTC'), 'price': 8.41579, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -2, 'dt': Timestamp('2017-01-02 19:29:00+0000', tz='UTC'), 'price': 1018.460515, 'order_id': '5eaf700a9fc84f90aa0a462fe963f546', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -2, 'dt': Timestamp('2017-01-02 19:43:00+0000', tz='UTC'), 'price': 1018.5404749999999, 'order_id': '51367f148dc541f2b118e146d2f5c02c', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 21:07:00+0000', tz='UTC'), 'price': 1021.520505, 'order_id': 'bcd83064e86c45269146d0478f9cbc17', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-02 21:08:00+0000', tz='UTC'), 'price': 1019.419455, 'order_id': 'bcd83064e86c45269146d0478f9cbc17', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -5, 'dt': Timestamp('2017-01-02 21:24:00+0000', tz='UTC'), 'price': 8.475760000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -15, 'dt': Timestamp('2017-01-02 22:17:00+0000', tz='UTC'), 'price': 8.505745, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -76, 'dt': Timestamp('2017-01-02 23:26:00+0000', tz='UTC'), 'price': 8.51574, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -33, 'dt': Timestamp('2017-01-02 23:29:00+0000', tz='UTC'), 'price': 8.545725000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}]",0.0 4 | 2017-01-03 23:59:00+00:00,8.660496173953051,9.314956951046982,9.793000000000001,9.841999999999992,29,4,9.75,0.46890256850870604,-0.014187915000001605,2.8552755604919273,0.007650322201503856,0.07011636115838527,-6.1914107377890915,-1246.0428400000042,5.8804250000000176,4923.18,4923.18,0.0,1.5210160463796707,6210.18,6210.18,1,-0.03603582845255648,1.5210160463796707,0.9988069886564638,"[{'id': '6782718462674593a30ba211a52a41a1', 'dt': Timestamp('2017-01-03 00:55:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 00:26:00+0000', tz='UTC'), 'amount': 1, 'filled': 1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '4bd104678844422485329584822aba92', 'dt': Timestamp('2017-01-03 10:57:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 16:17:00+0000', tz='UTC'), 'amount': -243, 'filled': -243, 'commission': 0.24300000000000002, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '039494f935a54bdda32bf258cd94ecd5', 'dt': Timestamp('2017-01-03 13:25:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 12:38:00+0000', tz='UTC'), 'amount': 1, 'filled': 1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '16d3dc4b2ba84701b21bba3b49577330', 'dt': Timestamp('2017-01-03 15:16:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-02 21:13:00+0000', tz='UTC'), 'amount': 18, 'filled': 18, 'commission': 0.018, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '5225b83b6fb74b89a011effe25113606', 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 10:31:00+0000', tz='UTC'), 'amount': 118, 'filled': 118, 'commission': 0.118, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '79a448aa39ca43ce8cc09807485054df', 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 14:34:00+0000', tz='UTC'), 'amount': -1, 'filled': -1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': '2b17444302ad4f62bcb1a4bb78169d0e', 'dt': Timestamp('2017-01-03 18:37:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 17:26:00+0000', tz='UTC'), 'amount': -78, 'filled': -78, 'commission': 0.078, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}, {'id': 'add63a5adc8948e58722df76981b05dd', 'dt': Timestamp('2017-01-03 18:52:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 18:51:00+0000', tz='UTC'), 'amount': -1, 'filled': -1, 'commission': 0.001, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(0 [BTCUSD]), 'status': 1}, {'id': '80ef93cbbf204567a51aba41ffb416a9', 'dt': Timestamp('2017-01-03 21:08:00+0000', tz='UTC'), 'reason': None, 'created': Timestamp('2017-01-03 19:32:00+0000', tz='UTC'), 'amount': 54, 'filled': 54, 'commission': 0.054, 'stop': None, 'limit': None, 'stop_reached': False, 'limit_reached': False, 'sid': Equity(1 [ETHUSD]), 'status': 1}]",2017-01-03 23:59:00+00:00,2017-01,2017-01-03 00:00:00+00:00,-184.2628399999985,4929.060425000001,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 1035.03}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 9.75}]",-0.036035828452556595,-2.3960042557667136,-1287.0,-1287.0,1,-3.401700257998596,1251.9232649999994,3861.3999999999996,3861.3999999999996,3,"[{'amount': 1, 'dt': Timestamp('2017-01-03 00:55:00+0000', tz='UTC'), 'price': 1028.684085, 'order_id': '6782718462674593a30ba211a52a41a1', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': -5, 'dt': Timestamp('2017-01-03 00:57:00+0000', tz='UTC'), 'price': 8.465765000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -14, 'dt': Timestamp('2017-01-03 03:05:00+0000', tz='UTC'), 'price': 8.305845, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -26, 'dt': Timestamp('2017-01-03 06:37:00+0000', tz='UTC'), 'price': 8.3958, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -36, 'dt': Timestamp('2017-01-03 06:48:00+0000', tz='UTC'), 'price': 8.3958, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -13, 'dt': Timestamp('2017-01-03 10:29:00+0000', tz='UTC'), 'price': 8.545725000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -4, 'dt': Timestamp('2017-01-03 10:57:00+0000', tz='UTC'), 'price': 8.545725000000001, 'order_id': '4bd104678844422485329584822aba92', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 10:57:00+0000', tz='UTC'), 'price': 8.554275, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 13:25:00+0000', tz='UTC'), 'price': 1020.920205, 'order_id': '039494f935a54bdda32bf258cd94ecd5', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 14:34:00+0000', tz='UTC'), 'price': 8.72436, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 14:39:00+0000', tz='UTC'), 'price': 8.74437, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 14:57:00+0000', tz='UTC'), 'price': 8.74437, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 4, 'dt': Timestamp('2017-01-03 14:58:00+0000', tz='UTC'), 'price': 8.74437, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 4, 'dt': Timestamp('2017-01-03 15:04:00+0000', tz='UTC'), 'price': 8.96448, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 15:09:00+0000', tz='UTC'), 'price': 8.864429999999999, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 15:16:00+0000', tz='UTC'), 'price': 8.984490000000001, 'order_id': '16d3dc4b2ba84701b21bba3b49577330', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 6, 'dt': Timestamp('2017-01-03 15:16:00+0000', tz='UTC'), 'price': 8.984490000000001, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 15:17:00+0000', tz='UTC'), 'price': 9.0045, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 7, 'dt': Timestamp('2017-01-03 15:22:00+0000', tz='UTC'), 'price': 9.44472, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 25, 'dt': Timestamp('2017-01-03 15:23:00+0000', tz='UTC'), 'price': 9.44472, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 15:27:00+0000', tz='UTC'), 'price': 9.96498, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 15:37:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 15:56:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 16:00:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 16:01:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 16:02:00+0000', tz='UTC'), 'price': 9.254625, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 3, 'dt': Timestamp('2017-01-03 16:13:00+0000', tz='UTC'), 'price': 9.50475, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 16:32:00+0000', tz='UTC'), 'price': 9.784889999999999, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 17:23:00+0000', tz='UTC'), 'price': 9.98499, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 17:34:00+0000', tz='UTC'), 'price': 9.554775000000001, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 6, 'dt': Timestamp('2017-01-03 17:41:00+0000', tz='UTC'), 'price': 9.754875, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 40, 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'price': 9.90495, 'order_id': '5225b83b6fb74b89a011effe25113606', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'price': 9.895050000000001, 'order_id': '79a448aa39ca43ce8cc09807485054df', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -32, 'dt': Timestamp('2017-01-03 18:29:00+0000', tz='UTC'), 'price': 9.895050000000001, 'order_id': '2b17444302ad4f62bcb1a4bb78169d0e', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -46, 'dt': Timestamp('2017-01-03 18:37:00+0000', tz='UTC'), 'price': 9.895050000000001, 'order_id': '2b17444302ad4f62bcb1a4bb78169d0e', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': -1, 'dt': Timestamp('2017-01-03 18:52:00+0000', tz='UTC'), 'price': 1024.177655, 'order_id': 'add63a5adc8948e58722df76981b05dd', 'sid': Equity(0 [BTCUSD]), 'commission': None}, {'amount': 6, 'dt': Timestamp('2017-01-03 19:36:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 10, 'dt': Timestamp('2017-01-03 19:48:00+0000', tz='UTC'), 'price': 9.84492, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 19:52:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 8, 'dt': Timestamp('2017-01-03 19:53:00+0000', tz='UTC'), 'price': 9.894945, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 20:00:00+0000', tz='UTC'), 'price': 9.834915, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 2, 'dt': Timestamp('2017-01-03 20:01:00+0000', tz='UTC'), 'price': 9.824910000000001, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 14, 'dt': Timestamp('2017-01-03 20:07:00+0000', tz='UTC'), 'price': 9.824910000000001, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 20:55:00+0000', tz='UTC'), 'price': 9.454725, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 5, 'dt': Timestamp('2017-01-03 21:02:00+0000', tz='UTC'), 'price': 9.654825, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}, {'amount': 1, 'dt': Timestamp('2017-01-03 21:08:00+0000', tz='UTC'), 'price': 9.50475, 'order_id': '80ef93cbbf204567a51aba41ffb416a9', 'sid': Equity(1 [ETHUSD]), 'commission': None}]",0.0 5 | 2017-01-04 23:59:00+00:00,10.659356969423053,10.87315865557695,11.168000000000003,10.99908333333334,49,4,11.21,0.8597321908218044,0.0770240849999968,4.884971632937453,0.01364482250735044,0.06328773075372535,0.11843169802167909,0.0,5.8804250000000176,5379.240000000001,5379.240000000001,0.0,1.5484667643249592,6858.960000000001,6858.960000000001,1,-0.03603582845255648,1.5484667643249592,0.9989080234914152,[],2017-01-04 23:59:00+00:00,2017-01,2017-01-04 00:00:00+00:00,456.0600000000004,5385.120425000001,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 1143.16}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 11.21}]",0.09252473304787956,5.799990768037722,-1479.72,-1479.72,1,17.43354491658354,5.8804250000000176,4923.18,4923.18,4,[],0.0 6 | 2017-01-05 23:59:00+00:00,10.430453581021212,11.128562043978846,10.340000000000002,10.30658333333333,57,6,10.34,1.3143939912614633,-0.06599191500000101,-8.112422976586277,0.0128395497495013,0.06237491853969911,8.381374549210223,0.0,5.8804250000000176,4664.16,4664.16,0.0,1.5832668086593704,6029.04,6029.04,1,-0.1327881168042759,1.5832668086593704,0.9987408192510453,[],2017-01-05 23:59:00+00:00,2017-01,2017-01-05 00:00:00+00:00,-715.0800000000008,4670.040425,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 1004.84}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.34}]",-0.13278811680427582,-2.0567425666180568,-1364.8799999999999,-1364.8799999999999,1,-2.767581488011503,5.8804250000000176,5379.240000000001,5379.240000000001,5,[],0.0 7 | 2017-01-06 23:59:00+00:00,9.99067774200546,10.175978507994365,10.200000000000001,10.181583333333359,59,6,10.2,1.4402369974664968,-0.1959159149999985,-12.587722600092285,0.016463046157883188,0.05617747941484457,6.5292877250752674,0.0,5.8804250000000176,4014.540000000001,4014.540000000001,0.0,1.668318059049757,5360.9400000000005,5360.9400000000005,1,-0.25342051658946535,1.668318059049757,0.9985373606791385,[],2017-01-06 23:59:00+00:00,2017-01,2017-01-06 00:00:00+00:00,-649.6199999999994,4020.4204250000007,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 893.49}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.2}]",-0.139103720927638,-5.620717066575118,-1346.3999999999999,-1346.3999999999999,1,-6.3842337674782605,5.8804250000000176,4664.16,4664.16,6,[],0.0 8 | 2017-01-07 23:59:00+00:00,9.67500276053733,9.923965989462646,10.049999999999999,10.026333333333342,68,7,10.05,1.3597317766681372,-0.17526391500000038,-8.352027142886207,0.016463046157883188,0.05383594218578734,3.9641603261721796,0.0,5.8804250000000176,4117.799999999999,4117.799999999999,0.0,1.6419798098200107,5444.4,5444.4,1,-0.25342051658946535,1.668318059049757,0.998573986246764,[],2017-01-07 23:59:00+00:00,2017-01,2017-01-07 00:00:00+00:00,103.25999999999885,4123.680425,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 907.4}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.05}]",0.025683881058282676,-4.422999418512168,-1326.6000000000001,-1326.6000000000001,1,-5.12302667818816,5.8804250000000176,4014.540000000001,4014.540000000001,7,[],0.0 9 | 2017-01-08 23:59:00+00:00,10.03418671671531,10.165985158284466,10.42,10.278083333333331,167,9,10.42,1.2646884366253217,-0.1771359149999998,-6.937441095755038,0.016463046157883188,0.05154413028874283,3.107490278888933,0.0,5.8804250000000176,4108.4400000000005,4108.4400000000005,0.0,1.6671817679343723,5483.88,5483.88,1,-0.25342051658946535,1.668318059049757,0.998570742092845,[],2017-01-08 23:59:00+00:00,2017-01,2017-01-08 00:00:00+00:00,-9.359999999998763,4114.320425000001,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 913.98}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.42}]",-0.0022698170166756126,-4.2175055388358995,-1375.44,-1375.44,1,-4.856936753133122,5.8804250000000176,4117.799999999999,4117.799999999999,8,[],0.0 10 | 2017-01-09 23:59:00+00:00,10.423694594171101,10.645258530828825,10.379999999999999,10.348416666666687,178,11,10.38,1.1835024020325289,-0.18923191499999947,-5.8858513455979855,0.013107974002117606,0.05590786581657495,2.0013555284676707,0.0,5.8804250000000176,4047.96,4047.96,0.0,1.674530639671146,5418.12,5418.12,1,-0.25342051658946535,1.674530639671146,0.9985494187280448,[],2017-01-09 23:59:00+00:00,2017-01,2017-01-09 00:00:00+00:00,-60.48000000000093,4053.840425,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 903.02}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.38}]",-0.014699875982556287,-4.353839226023117,-1370.16,-1370.16,1,-4.9627100911351105,5.8804250000000176,4108.4400000000005,4108.4400000000005,9,[],0.0 11 | 2017-01-10 23:59:00+00:00,10.458049235339931,10.595966389659932,10.67,10.69175000000001,190,13,10.67,1.1185433761538153,-0.19320391500000111,-5.342013637027109,0.013107974002117606,0.05321307558572865,1.7625972072434188,0.0,5.8804250000000176,4028.1,4028.1,0.0,1.6968302467655132,5436.54,5436.54,1,-0.25342051658946535,1.6968302467655132,0.9985422772595631,[],2017-01-10 23:59:00+00:00,2017-01,2017-01-10 00:00:00+00:00,-19.860000000000127,4033.9804249999997,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 906.09}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 10.67}]",-0.004899058156688119,-4.256390615601364,-1408.44,-1408.44,1,-4.831868520092666,5.8804250000000176,4047.96,4047.96,10,[],0.0 12 | 2017-01-11 23:59:00+00:00,9.916638239298495,10.32126801070167,9.97,9.872500000000002,197,14,9.97,1.271073092285016,-0.3263919150000011,-8.027182898229908,0.015971012028732856,0.05100241180843514,-0.22734819260468958,0.0,5.8804250000000176,3362.1600000000008,3362.1600000000008,0.0,1.7797411086596444,4678.200000000001,4678.200000000001,1,-0.3745654397320179,1.7797411086596444,0.9982540515379948,[],2017-01-11 23:59:00+00:00,2017-01,2017-01-11 00:00:00+00:00,-665.9399999999991,3368.0404250000006,"[{'sid': Equity(0 [BTCUSD]), 'amount': 6, 'cost_basis': 1019.9192778073376, 'last_sale_price': 779.7}, {'sid': Equity(1 [ETHUSD]), 'amount': -132, 'cost_basis': 9.07266629965961, 'last_sale_price': 9.97}]",-0.16508260572434508,-6.380463625438262,-1316.0400000000002,-1316.0400000000002,1,-6.606576507659419,5.8804250000000176,4028.1,4028.1,11,[],0.0 13 | -------------------------------------------------------------------------------- /section 0006/SEC 0006 VID 0003 Bayesian Value at Risk.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "ename": "ValueError", 10 | "evalue": "index must be monotonic increasing or decreasing", 11 | "output_type": "error", 12 | "traceback": [ 13 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 14 | "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", 15 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_line_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'load_ext'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'zipline'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msystem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'zipline ingest'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 16 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumpy_utils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy_version\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpandas_utils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnew_pandas\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 29\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_algo\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mrun_algorithm\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 30\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_version\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mget_versions\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 17 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/utils/run_algo.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mbundles\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata_portal\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mDataPortal\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfinance\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mmetrics\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfinance\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrading\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mTradingEnvironment\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpipeline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mUSEquityPricing\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 18 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/metrics/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[0m_ClassicRiskMetrics\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 42\u001b[0m )\n\u001b[0;32m---> 43\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mtracker\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mMetricsTracker\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 44\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 19 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/metrics/tracker.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mlogbook\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mledger\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mLedger\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 20\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexploding_object\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mNamedExplodingObject\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 20 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/ledger.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massets\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mFuture\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 28\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfinance\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransaction\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mTransaction\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 29\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprotocol\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mzp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msentinel\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msentinel\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 21 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/transaction.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massets\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mAsset\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprotocol\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mDATASOURCE_TYPE\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minput_validation\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mexpect_types\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 22 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/protocol.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0massets\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mAsset\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0menum\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0menum\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_protocol\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mBarData\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mInnerPosition\u001b[0m \u001b[0;31m# noqa\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 23 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/utils/enum.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 41\u001b[0m pd.Series(_inttypes_map).reindex(\n\u001b[1;32m 42\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_inttypes_map\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 43\u001b[0;31m \u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'bfill'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 44\u001b[0m ),\n\u001b[1;32m 45\u001b[0m )\n", 24 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/series.py\u001b[0m in \u001b[0;36mreindex\u001b[0;34m(self, index, **kwargs)\u001b[0m\n\u001b[1;32m 3732\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mAppender\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgeneric\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNDFrame\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreindex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3733\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mreindex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3734\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mSeries\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreindex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3735\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3736\u001b[0m def drop(self, labels=None, axis=0, index=None, columns=None,\n", 25 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/generic.py\u001b[0m in \u001b[0;36mreindex\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 4354\u001b[0m \u001b[0;31m# perform the reindex on the axes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4355\u001b[0m return self._reindex_axes(axes, level, limit, tolerance, method,\n\u001b[0;32m-> 4356\u001b[0;31m fill_value, copy).__finalize__(self)\n\u001b[0m\u001b[1;32m 4357\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4358\u001b[0m def _reindex_axes(self, axes, level, limit, tolerance, method, fill_value,\n", 26 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/generic.py\u001b[0m in \u001b[0;36m_reindex_axes\u001b[0;34m(self, axes, level, limit, tolerance, method, fill_value, copy)\u001b[0m\n\u001b[1;32m 4367\u001b[0m \u001b[0max\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_axis\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4368\u001b[0m new_index, indexer = ax.reindex(labels, level=level, limit=limit,\n\u001b[0;32m-> 4369\u001b[0;31m tolerance=tolerance, method=method)\n\u001b[0m\u001b[1;32m 4370\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4371\u001b[0m \u001b[0maxis\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_axis_number\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 27 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36mreindex\u001b[0;34m(self, target, method, level, limit, tolerance)\u001b[0m\n\u001b[1;32m 3132\u001b[0m indexer = self.get_indexer(target, method=method,\n\u001b[1;32m 3133\u001b[0m \u001b[0mlimit\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlimit\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3134\u001b[0;31m tolerance=tolerance)\n\u001b[0m\u001b[1;32m 3135\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3136\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mlimit\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 28 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36mget_indexer\u001b[0;34m(self, target, method, limit, tolerance)\u001b[0m\n\u001b[1;32m 2741\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2742\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'pad'\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'backfill'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2743\u001b[0;31m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_fill_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtarget\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlimit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtolerance\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2744\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'nearest'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2745\u001b[0m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_nearest_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtarget\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlimit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtolerance\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 29 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36m_get_fill_indexer\u001b[0;34m(self, target, method, limit, tolerance)\u001b[0m\n\u001b[1;32m 2771\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2772\u001b[0m indexer = self._get_fill_indexer_searchsorted(target, method,\n\u001b[0;32m-> 2773\u001b[0;31m limit)\n\u001b[0m\u001b[1;32m 2774\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtolerance\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2775\u001b[0m indexer = self._filter_indexer_tolerance(target._ndarray_values,\n", 30 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36m_get_fill_indexer_searchsorted\u001b[0;34m(self, target, method, limit)\u001b[0m\n\u001b[1;32m 2793\u001b[0m \u001b[0mnonexact\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mindexer\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2794\u001b[0m indexer[nonexact] = self._searchsorted_monotonic(target[nonexact],\n\u001b[0;32m-> 2795\u001b[0;31m side)\n\u001b[0m\u001b[1;32m 2796\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mside\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'left'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2797\u001b[0m \u001b[0;31m# searchsorted returns \"indices into a sorted array such that,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 31 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/pandas/core/indexes/base.py\u001b[0m in \u001b[0;36m_searchsorted_monotonic\u001b[0;34m(self, label, side)\u001b[0m\n\u001b[1;32m 4762\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mpos\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4763\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 4764\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'index must be monotonic increasing or decreasing'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4765\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4766\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_get_loc_only_exact_matches\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 32 | "\u001b[0;31mValueError\u001b[0m: index must be monotonic increasing or decreasing" 33 | ] 34 | } 35 | ], 36 | "source": [ 37 | "import zipline\n", 38 | "%load_ext zipline\n", 39 | "!zipline ingest" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 3, 45 | "metadata": {}, 46 | "outputs": [ 47 | { 48 | "ename": "ImportError", 49 | "evalue": "cannot import name 'run_algorithm'", 50 | "output_type": "error", 51 | "traceback": [ 52 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 53 | "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", 54 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mos\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_algo\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mload_extensions\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m load_extensions(\n", 55 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/utils/run_algo.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mbundles\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata_portal\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mDataPortal\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfinance\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mmetrics\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfinance\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrading\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mTradingEnvironment\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpipeline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mUSEquityPricing\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 56 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/metrics/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[0m_ClassicRiskMetrics\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 42\u001b[0m )\n\u001b[0;32m---> 43\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mtracker\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mMetricsTracker\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 44\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 57 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/metrics/tracker.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mlogbook\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mledger\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mLedger\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 20\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexploding_object\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mNamedExplodingObject\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 58 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/ledger.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massets\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mFuture\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 28\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfinance\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtransaction\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mTransaction\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 29\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprotocol\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mzp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msentinel\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msentinel\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 59 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/finance/transaction.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massets\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mAsset\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprotocol\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mDATASOURCE_TYPE\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mzipline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minput_validation\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mexpect_types\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 60 | "\u001b[0;32m~/.local/lib/python3.6/site-packages/zipline/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumpy_utils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy_version\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpandas_utils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnew_pandas\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 29\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_algo\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mrun_algorithm\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 30\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_version\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mget_versions\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 61 | "\u001b[0;31mImportError\u001b[0m: cannot import name 'run_algorithm'" 62 | ] 63 | } 64 | ], 65 | "source": [ 66 | "import os\n", 67 | "\n", 68 | "from zipline.utils.run_algo import load_extensions\n", 69 | "\n", 70 | "load_extensions(\n", 71 | " default=True,\n", 72 | " extensions=[],\n", 73 | " strict=True,\n", 74 | " environ=os.environ,\n", 75 | ")" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 4, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "name": "stderr", 85 | "output_type": "stream", 86 | "text": [ 87 | "UsageError: Cell magic `%%zipline` not found.\n" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "%%zipline --start 2004-1-1 --end 2010-1-1 -o results.pickle\n", 93 | "\n", 94 | "# Zipline trading algorithm\n", 95 | "# Taken from zipline.examples.olmar\n", 96 | "\n", 97 | "import numpy as np\n", 98 | "\n", 99 | "from zipline.finance import commission, slippage\n", 100 | "\n", 101 | "STOCKS = ['AMD', 'CERN', 'COST', 'DELL', 'GPS', 'INTC', 'MMM']\n", 102 | "\n", 103 | "\n", 104 | "# On-Line Portfolio Moving Average Reversion\n", 105 | "\n", 106 | "# More info can be found in the corresponding paper:\n", 107 | "# http://icml.cc/2012/papers/168.pdf\n", 108 | "def initialize(algo, eps=1, window_length=5):\n", 109 | " algo.stocks = STOCKS\n", 110 | " algo.sids = [algo.symbol(symbol) for symbol in algo.stocks]\n", 111 | " algo.m = len(algo.stocks)\n", 112 | " algo.price = {}\n", 113 | " algo.b_t = np.ones(algo.m) / algo.m\n", 114 | " algo.eps = eps\n", 115 | " algo.window_length = window_length\n", 116 | "\n", 117 | " algo.set_commission(commission.PerShare(cost=0))\n", 118 | " algo.set_slippage(slippage.FixedSlippage(spread=0))\n", 119 | "\n", 120 | "\n", 121 | "def handle_data(algo, data):\n", 122 | " m = algo.m\n", 123 | "\n", 124 | " x_tilde = np.zeros(m)\n", 125 | " b = np.zeros(m)\n", 126 | "\n", 127 | " # find relative moving average price for each asset\n", 128 | " mavgs = data.history(algo.sids, 'price', algo.window_length, '1d').mean()\n", 129 | " for i, sid in enumerate(algo.sids):\n", 130 | " price = data.current(sid, \"price\")\n", 131 | " # Relative mean deviation\n", 132 | " x_tilde[i] = mavgs[sid] / price\n", 133 | "\n", 134 | " ###########################\n", 135 | " # Inside of OLMAR (algo 2)\n", 136 | " x_bar = x_tilde.mean()\n", 137 | "\n", 138 | " # market relative deviation\n", 139 | " mark_rel_dev = x_tilde - x_bar\n", 140 | "\n", 141 | " # Expected return with current portfolio\n", 142 | " exp_return = np.dot(algo.b_t, x_tilde)\n", 143 | " weight = algo.eps - exp_return\n", 144 | " variability = (np.linalg.norm(mark_rel_dev)) ** 2\n", 145 | "\n", 146 | " # test for divide-by-zero case\n", 147 | " if variability == 0.0:\n", 148 | " step_size = 0\n", 149 | " else:\n", 150 | " step_size = max(0, weight / variability)\n", 151 | "\n", 152 | " b = algo.b_t + step_size * mark_rel_dev\n", 153 | " b_norm = simplex_projection(b)\n", 154 | " np.testing.assert_almost_equal(b_norm.sum(), 1)\n", 155 | "\n", 156 | " rebalance_portfolio(algo, data, b_norm)\n", 157 | "\n", 158 | " # update portfolio\n", 159 | " algo.b_t = b_norm\n", 160 | "\n", 161 | "\n", 162 | "def rebalance_portfolio(algo, data, desired_port):\n", 163 | " # rebalance portfolio\n", 164 | " for i, sid in enumerate(algo.sids):\n", 165 | " algo.order_target_percent(sid, desired_port[i])\n", 166 | "\n", 167 | "\n", 168 | "def simplex_projection(v, b=1):\n", 169 | " \"\"\"Projection vectors to the simplex domain\n", 170 | " Implemented according to the paper: Efficient projections onto the\n", 171 | " l1-ball for learning in high dimensions, John Duchi, et al. ICML 2008.\n", 172 | " Implementation Time: 2011 June 17 by Bin@libin AT pmail.ntu.edu.sg\n", 173 | " Optimization Problem: min_{w}\\| w - v \\|_{2}^{2}\n", 174 | " s.t. sum_{i=1}^{m}=z, w_{i}\\geq 0\n", 175 | " Input: A vector v \\in R^{m}, and a scalar z > 0 (default=1)\n", 176 | " Output: Projection vector w\n", 177 | " :Example:\n", 178 | " >>> proj = simplex_projection([.4 ,.3, -.4, .5])\n", 179 | " >>> print(proj)\n", 180 | " array([ 0.33333333, 0.23333333, 0. , 0.43333333])\n", 181 | " >>> print(proj.sum())\n", 182 | " 1.0\n", 183 | " Original matlab implementation: John Duchi (jduchi@cs.berkeley.edu)\n", 184 | " Python-port: Copyright 2013 by Thomas Wiecki (thomas.wiecki@gmail.com).\n", 185 | " \"\"\"\n", 186 | "\n", 187 | " v = np.asarray(v)\n", 188 | " p = len(v)\n", 189 | "\n", 190 | " # Sort v into u in descending order\n", 191 | " v = (v > 0) * v\n", 192 | " u = np.sort(v)[::-1]\n", 193 | " sv = np.cumsum(u)\n", 194 | "\n", 195 | " rho = np.where(u > (sv - b) / np.arange(1, p + 1))[0][-1]\n", 196 | " theta = np.max([0, (sv[rho] - b) / (rho + 1)])\n", 197 | " w = (v - theta)\n", 198 | " w[w < 0] = 0\n", 199 | " return w" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": null, 205 | "metadata": {}, 206 | "outputs": [], 207 | "source": [] 208 | } 209 | ], 210 | "metadata": { 211 | "kernelspec": { 212 | "display_name": "Python 3", 213 | "language": "python", 214 | "name": "python3" 215 | }, 216 | "language_info": { 217 | "codemirror_mode": { 218 | "name": "ipython", 219 | "version": 3 220 | }, 221 | "file_extension": ".py", 222 | "mimetype": "text/x-python", 223 | "name": "python", 224 | "nbconvert_exporter": "python", 225 | "pygments_lexer": "ipython3", 226 | "version": "3.6.7" 227 | } 228 | }, 229 | "nbformat": 4, 230 | "nbformat_minor": 2 231 | } 232 | -------------------------------------------------------------------------------- /section 0006/estimator.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/section 0006/estimator.joblib -------------------------------------------------------------------------------- /section 0006/extension.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from zipline.data.bundles import register 4 | from zipline.data.bundles.csvdir import csvdir_equities 5 | 6 | start_session = pd.Timestamp('2017-01-01 00:00:00', tz='utc') 7 | end_session = pd.Timestamp('2017-12-31 23:59:00', tz='utc') 8 | 9 | register( 10 | 'crypto-bundle', 11 | csvdir_equities( 12 | ['minute'], 13 | '/path/to/your/csvs', 14 | ), 15 | calendar_name='NYSE', # US equities 16 | start_session=start_session, 17 | end_session=end_session 18 | ) -------------------------------------------------------------------------------- /section 0006/main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from matplotlib import pyplot as plt 3 | import numpy as np 4 | from strategies.run_zipline import run_strategy 5 | 6 | 7 | def main(): 8 | print("*** PackPub - Hands-on Machine Learning for Algorithmic Trading Bots ***") 9 | print("*** SEC005/VID002: Implement Scalping Strategy ***") 10 | perf = run_strategy("scalping") 11 | perf.to_csv("scalping.csv") 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /section 0006/strategies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/section 0006/strategies/__init__.py -------------------------------------------------------------------------------- /section 0006/strategies/auto_correlation.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | from scipy.stats.stats import pearsonr 6 | 7 | 8 | class AutoCorrelation: 9 | 10 | stocks = ['APL', 'MSFT', 'TSLA'] 11 | lag = 1 12 | steps = 3 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol(self.stocks[-1]) 18 | 19 | def handle_data(self, context, data): 20 | # loop stocks in portfolio 21 | for stock in context.stocks: 22 | # fetch history up to steps 23 | s1 = data.history( 24 | symbol(stock), 25 | 'price', 26 | bar_count=self.steps, 27 | frequency='1d') 28 | 29 | # fetch history up to steps + lag and drop extra values 30 | s2 = data.history( 31 | symbol(stock), 32 | 'price', 33 | bar_count=self.steps+self.lag, 34 | frequency='1d').iloc[:-1 * self.lag] 35 | 36 | # convert to numpy arrays 37 | np_s1 = np.array(s1.values) 38 | np_s2 = np.array(s2.values) 39 | 40 | # calculate auto-correlation 41 | corr, hypothesis = pearsonr(np_s1, np_s2) 42 | 43 | # fetch our basket status 44 | cpp = context.portfolio.positions 45 | 46 | # map basket to symbol:shares pairs 47 | cpp_symbols = map(lambda x: x.symbol, cpp) 48 | 49 | # what is today price 50 | curr_price = data.current(symbol(stock), 'price') 51 | 52 | # what was yesterday closing price 53 | last_price = data.history( 54 | symbol(stock), 55 | 'price', 56 | bar_count=2, 57 | frequency='1d').iloc[0:1].values 58 | 59 | # go short or long positions 60 | if corr < -0.75 and hypothesis < 0.85: 61 | # is stock falling? exit position 62 | if curr_price < last_price: 63 | order(symbol(stock), -1 * cpp[symbol(stock)].amount) 64 | # is stock rising? enter position 65 | elif curr_price > last_price: 66 | order(symbol(stock), 1000) 67 | 68 | record(ASSETME=data.current(context.asset, 'price')) 69 | record(CORR=corr) 70 | 71 | def _test_args(self): 72 | return { 73 | 'start': pd.Timestamp('2017', tz='utc'), 74 | 'end': pd.Timestamp('2018', tz='utc'), 75 | 'capital_base': 1e7 76 | } 77 | 78 | def analyze(self, context, perf): 79 | # init figure 80 | fig = plt.figure() 81 | 82 | # plot stock price 83 | ax1 = fig.add_subplot(211) 84 | perf['ASSETME'].plot(ax=ax1) 85 | ax1.set_ylabel('price in $') 86 | 87 | # plot correlation 88 | ax2 = fig.add_subplot(212) 89 | perf['CORR'].plot(ax=ax2) 90 | ax2.set_ylabel('correlation') 91 | 92 | # plot confidence levels 93 | ax2.axhline(0.75, linestyle='dashed', color='k') 94 | ax2.axhline(0, linestyle='dashed', color='b') 95 | ax2.axhline(-0.75, linestyle='dashed', color='k') 96 | 97 | # add spacing between plots 98 | plt.subplots_adjust(hspace=1) 99 | 100 | # display plot 101 | plt.show() 102 | -------------------------------------------------------------------------------- /section 0006/strategies/buy_and_hold.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | from joblib import load 5 | import numpy as np 6 | 7 | 8 | class BuyAndHold: 9 | 10 | stocks = ['AAPL', 'MSFT', 'TSLA'] 11 | lag = 33 12 | forecast = 8 13 | 14 | def initialize(self, context): 15 | context.has_ordered = False 16 | context.stocks = self.stocks 17 | context.asset = symbol('AAPL') 18 | context.regressor = load('./strategies/models/rf_regressor.joblib') 19 | 20 | def handle_data(self, context, data): 21 | for stock in context.stocks: 22 | timeseries = data.history( 23 | symbol(stock), 24 | 'price', 25 | bar_count=self.lag, 26 | frequency='1d') 27 | np_timeseries = np.array(timeseries.values).reshape(1, -1) 28 | preds = context.regressor.predict(np_timeseries) 29 | max_price = np.max(preds) 30 | historical_mean = np.mean(np_timeseries) 31 | 32 | if max_price > historical_mean: 33 | order(symbol(stock), 1000) 34 | 35 | if max_price < historical_mean: 36 | order(symbol(stock), -1000) 37 | 38 | record(AAPL=data.current(context.asset, 'price')) 39 | 40 | def _test_args(self): 41 | return { 42 | 'start': pd.Timestamp('2017', tz='utc'), 43 | 'end': pd.Timestamp('2018', tz='utc'), 44 | 'capital_base': 1e7 45 | } 46 | 47 | def analyze(self, context, perf): 48 | fig = plt.figure() 49 | ax1 = fig.add_subplot(211) 50 | perf.portfolio_value.plot(ax=ax1) 51 | ax1.set_ylabel('portfolio value in $') 52 | 53 | ax2 = fig.add_subplot(212) 54 | perf['AAPL'].plot(ax=ax2) 55 | 56 | ax2.set_ylabel('price in $') 57 | plt.legend(loc=0) 58 | plt.show() 59 | -------------------------------------------------------------------------------- /section 0006/strategies/calendar.py: -------------------------------------------------------------------------------- 1 | from zipline.utils.calendars import TradingCalendar 2 | from datetime import time 3 | from pandas.tseries.offsets import CustomBusinessDay 4 | from pytz import timezone 5 | from zipline.utils.memoize import lazyval 6 | 7 | 8 | class CryptoCalendar(TradingCalendar): 9 | """ 10 | Exchange calendar for 24/7 trading. 11 | 12 | Open Time: 12am, UTC 13 | Close Time: 11:59pm, UTC 14 | 15 | """ 16 | @property 17 | def name(self): 18 | return "cryptocalendar" 19 | 20 | @property 21 | def tz(self): 22 | return timezone("UTC") 23 | 24 | @property 25 | def open_time(self): 26 | return time(0, 0) 27 | 28 | @property 29 | def close_time(self): 30 | return time(23, 59) 31 | 32 | @property 33 | def open_times(self): 34 | return [(None, time(0, 0))] 35 | 36 | @property 37 | def close_times(self): 38 | return [(None, time(23, 59))] 39 | 40 | @lazyval 41 | def day(self): 42 | return CustomBusinessDay( 43 | weekmask='Mon Tue Wed Thu Fri Sat Sun', 44 | ) -------------------------------------------------------------------------------- /section 0006/strategies/models/rf_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/section 0006/strategies/models/rf_regressor.joblib -------------------------------------------------------------------------------- /section 0006/strategies/models/sv_regressor.joblib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Machine-Learning-for-Algorithmic-Trading-Bots-with-Python/c01f1799cc85baaada1dd13b1fe91d885cfd69a3/section 0006/strategies/models/sv_regressor.joblib -------------------------------------------------------------------------------- /section 0006/strategies/run_zipline.py: -------------------------------------------------------------------------------- 1 | from toolz import merge 2 | from zipline import run_algorithm 3 | from zipline.utils.calendars import register_calendar, get_calendar 4 | from strategies.buy_and_hold import BuyAndHold 5 | from strategies.auto_correlation import AutoCorrelation 6 | from os import environ 7 | from strategies.scalping import ScalpBollingerBand 8 | import pandas as pd 9 | import os 10 | import pytz 11 | from collections import OrderedDict 12 | from strategies.calendar import CryptoCalendar 13 | 14 | 15 | # Columns that we expect to be able to reliably deterministic 16 | # Doesn't include fields that have UUIDS. 17 | _cols_to_check = [ 18 | 'algo_volatility', 19 | 'algorithm_period_return', 20 | 'alpha', 21 | 'benchmark_period_return', 22 | 'benchmark_volatility', 23 | 'beta', 24 | 'capital_used', 25 | 'ending_cash', 26 | 'ending_exposure', 27 | 'ending_value', 28 | 'excess_return', 29 | 'gross_leverage', 30 | 'long_exposure', 31 | 'long_value', 32 | 'longs_count', 33 | 'max_drawdown', 34 | 'max_leverage', 35 | 'net_leverage', 36 | 'period_close', 37 | 'period_label', 38 | 'period_open', 39 | 'pnl', 40 | 'portfolio_value', 41 | 'positions', 42 | 'returns', 43 | 'short_exposure', 44 | 'short_value', 45 | 'shorts_count', 46 | 'sortino', 47 | 'starting_cash', 48 | 'starting_exposure', 49 | 'starting_value', 50 | 'trading_days', 51 | 'treasury_period_return', 52 | ] 53 | 54 | 55 | def prepareCSV(csv_pth): 56 | files = os.listdir(csv_pth) 57 | start = end = None 58 | 59 | dd = OrderedDict() 60 | for f in files: 61 | fp = os.path.join(csv_pth, f) 62 | n1 = os.path.splitext(fp)[0] 63 | key = n1.split('/')[1] 64 | df = pd.read_csv(fp) 65 | df.index = pd.DatetimeIndex(df.date) 66 | df = df.sort_index() 67 | dd[key] = df.drop(columns=['date']) 68 | start = df.index.values[0] 69 | end = df.index.values[10*24*60] 70 | 71 | panel = pd.Panel(dd) 72 | 73 | panel.major_axis = panel.major_axis.tz_localize(pytz.utc) 74 | 75 | return panel, pd.to_datetime(start).tz_localize(pytz.utc), pd.to_datetime(end).tz_localize(pytz.utc) 76 | 77 | 78 | def run_strategy(strategy_name): 79 | mod = None 80 | 81 | if strategy_name == "buy_and_hold": 82 | mod = BuyAndHold() 83 | elif strategy_name == "auto_correlation": 84 | mod = AutoCorrelation() 85 | elif strategy_name == "scalping": 86 | mod = ScalpBollingerBand() 87 | 88 | # register_calendar("YAHOO", get_calendar("NYSE"), force=True) 89 | data_panel, start, end = prepareCSV('csv') 90 | print(data_panel, type(start)) 91 | 92 | return run_algorithm( 93 | data=data_panel, 94 | trading_calendar=CryptoCalendar(), 95 | initialize=getattr(mod, 'initialize', None), 96 | handle_data=getattr(mod, 'handle_data', None), 97 | before_trading_start=getattr(mod, 'before_trading_start', None), 98 | analyze=getattr(mod, 'analyze', None), 99 | # bundle='quandl', 100 | environ=environ, 101 | data_frequency='minute', 102 | # Provide a default capital base, but allow the test to override. 103 | **merge({ 104 | 'capital_base': 1000, 105 | 'start': start, 106 | 'end': end 107 | }, mod._test_args()) 108 | ) 109 | -------------------------------------------------------------------------------- /section 0006/strategies/scalping.py: -------------------------------------------------------------------------------- 1 | from zipline.api import order, symbol, record 2 | from matplotlib import pyplot as plt 3 | import pandas as pd 4 | import numpy as np 5 | from joblib import load 6 | 7 | 8 | class ScalpBollingerBand: 9 | 10 | stocks = ['BTCUSD', 'ETHUSD'] 11 | ma1 = 10 12 | ma2 = 120 13 | steps = 1280 14 | stop_loss = 0.005 15 | stdv = 0.5 16 | 17 | 18 | def initialize(self, context): 19 | context.stocks = self.stocks 20 | context.asset = symbol(self.stocks[-1]) 21 | 22 | context.burndown = 0 23 | context.number_shorts = 0 24 | context.number_longs = 0 25 | 26 | context.position = {} 27 | for stock in self.stocks: 28 | context.position[stock] = None 29 | 30 | # VaR 31 | context.historical_returns = [] 32 | 33 | #SVR 34 | context.regressor = load('./strategies/models/sv_regressor.joblib') 35 | 36 | 37 | def handle_data(self, context, data): 38 | # wait till enough historical data arrives for calculations 39 | context.burndown += 1 40 | 41 | # log while backtesting 42 | if context.burndown % 1000 == 0: 43 | print(context.burndown) 44 | 45 | # calculate VaR only when there is enough data 46 | if len(context.historical_returns) > 15: 47 | 48 | # Non-Parametric Historical Value at Risk 49 | 50 | # history 51 | historical_returns = np.array(context.historical_returns) 52 | 53 | # forecast 54 | forecast_returns = context.regressor.predict( 55 | historical_returns[-15:].reshape(1, -1) 56 | ) 57 | 58 | # VaR 59 | lowest_percentile = np.percentile( 60 | np.concatenate( 61 | ( 62 | historical_returns, 63 | forecast_returns[0] 64 | ), axis=0 65 | ), 0.05) 66 | expected_shortfall = np.mean( 67 | np.where( 68 | historical_returns <= lowest_percentile 69 | ) 70 | ) 71 | 72 | # stop loss value 73 | value_at_risk = expected_shortfall / 60 / 24 74 | 75 | # exit all positions 76 | if ( context.portfolio.returns <= value_at_risk ): 77 | # loop stocks in portfolio 78 | for i, stock in enumerate(context.stocks): 79 | # are we in a trade? 80 | if context.position[stock] == 'trade': 81 | # short position 82 | order(symbol(stock), 0) 83 | context.position[stock] = None 84 | context.number_shorts += 1 85 | print('Stop Loss: {} @ VaR {} for {}'.format( 86 | context.portfolio.returns, 87 | value_at_risk, 88 | stock 89 | ) 90 | ) 91 | 92 | 93 | # trade only when there is enough data 94 | if context.burndown > self.steps: 95 | 96 | # loop stocks in portfolio 97 | for i, stock in enumerate(context.stocks): 98 | # history 99 | hist = data.history( 100 | symbol(stock), 101 | 'price', 102 | bar_count=self.steps, 103 | frequency='1m') 104 | 105 | # bollinger bands 106 | blw = hist.mean() - self.stdv * hist.std() 107 | bhi = hist.mean() + self.stdv * hist.std() 108 | 109 | # moving average short 110 | short_term = data.history( 111 | symbol(stock), 112 | 'price', 113 | bar_count=self.ma1, 114 | frequency='1m').mean() 115 | 116 | # moving average long 117 | long_term = data.history( 118 | symbol(stock), 119 | 'price', 120 | bar_count=self.ma2, 121 | frequency='1m').mean() 122 | 123 | # fetch our basket status 124 | cpp = context.portfolio.positions 125 | 126 | # map basket to symbol:shares pairs 127 | cpp_symbols = map(lambda x: x.symbol, cpp) 128 | 129 | # check indicator signal 130 | if short_term >= long_term and context.position[stock] != 'trade': 131 | context.position[stock] = 'long' 132 | elif short_term <= long_term and context.position[stock] == 'trade': 133 | context.position[stock] = 'short' 134 | 135 | 136 | # what is current price 137 | current_price = data.current(symbol(stock), 'price') 138 | 139 | 140 | # check bollinger bands 141 | if short_term >= bhi and context.position[stock] == 'long': 142 | # how many shares I can afford? 143 | num_shares = context.portfolio.cash // current_price 144 | 145 | # long position 146 | order(symbol(stock), num_shares) # order_value 147 | context.position[stock] = 'trade' 148 | context.number_longs += 1 149 | print('Enter Trade: ', stock) 150 | 151 | elif (current_price <= blw and context.position[stock] == 'trade') \ 152 | or (short_term <= blw and context.position[stock] == 'short'): 153 | # short position 154 | order(symbol(stock), 0) 155 | context.position[stock] = None 156 | context.number_shorts += 1 157 | print('Exit Trade: ', stock) 158 | 159 | 160 | # what is the price paid on beginning of trade 161 | last_price = cpp[symbol(stock)].last_sale_price 162 | 163 | # stop loss value 164 | val = last_price - last_price * self.stop_loss 165 | 166 | # are we in a trade? 167 | if context.position[stock] == 'trade': 168 | # stop loss violated 169 | if current_price < val: 170 | # short position 171 | order(symbol(stock), 0) 172 | context.position[stock] = None 173 | context.number_shorts += 1 174 | print('Stop Loss: ', stock) 175 | 176 | # is last stock? 177 | if i == len(self.stocks) - 1: 178 | 179 | # record price, ma1, ma2, Bollinger bands 180 | record(REC_PRICE=current_price) 181 | record(REC_MA1=short_term) 182 | record(REC_MA2=long_term) 183 | record(REC_BB1=blw) 184 | record(REC_BB2=bhi) 185 | 186 | context.historical_returns.append(context.portfolio.returns) 187 | 188 | # record positions count 189 | record(REC_NUM_SHORTS=context.number_shorts) 190 | record(REC_NUM_LONGS=context.number_longs) 191 | 192 | def _test_args(self): 193 | return { 194 | # 'start': pd.Timestamp('2017', tz='utc'), 195 | # 'end': pd.Timestamp('2018', tz='utc'), 196 | # 'capital_base': 1e7, 197 | # 'data_frequency': 'minute' 198 | } 199 | 200 | def analyze(self, context, perf): 201 | # init figure 202 | fig = plt.figure() 203 | 204 | # plot recorded data 205 | ax1 = fig.add_subplot(211) 206 | perf.plot(y=[ 207 | 'REC_PRICE', 208 | 'REC_MA1', 209 | 'REC_MA2' 210 | ], ax=ax1) 211 | ax1.set_ylabel('price in $') 212 | 213 | # plot recorded data 214 | ax2 = fig.add_subplot(212) 215 | perf.plot(y=[ 216 | 'REC_PRICE', 217 | 'REC_BB1', 218 | 'REC_BB2' 219 | ], ax=ax2) 220 | ax2.set_ylabel('Bollinger Bands') 221 | 222 | # add spacing between plots 223 | plt.subplots_adjust(hspace=1) 224 | 225 | # display plot 226 | plt.show() 227 | --------------------------------------------------------------------------------