Updated examples

This commit is contained in:
Conner Fromknecht
2017-06-30 12:34:25 -07:00
parent 4b15df7806
commit 8fef0757d8
10 changed files with 21 additions and 3113 deletions
+2 -2
View File
@@ -101,7 +101,7 @@ def analyze(context=None, results=None):
ax3 = plt.subplot(513, sharex=ax1)
results[['leverage', 'alpha', 'beta']].plot(ax=ax3)
ax3.set_ylabel('Leverage (USD)')
ax3.set_ylabel('Leverage ')
ax4 = plt.subplot(514, sharex=ax1)
results[['starting_cash', 'cash']].plot(ax=ax4)
@@ -123,7 +123,7 @@ def analyze(context=None, results=None):
'algorithm',
'benchmark',
]].plot(ax=ax5)
ax5.set_ylabel('Dollars (USD)')
ax5.set_ylabel('Percent Change')
plt.legend(loc=3)
File diff suppressed because one or more lines are too long
-54
View File
@@ -1,54 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2014 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from catalyst.api import order, record, symbol
def initialize(context):
context.asset = symbol('AAPL')
def handle_data(context, data):
order(context.asset, 10)
record(AAPL=data.current(context.asset, 'price'))
# Note: this function can be removed if running
# this algorithm on quantopian.com
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
# Plot the portfolio and asset data.
ax1 = plt.subplot(211)
results.portfolio_value.plot(ax=ax1)
ax1.set_ylabel('Portfolio value (USD)')
ax2 = plt.subplot(212, sharex=ax1)
results.AAPL.plot(ax=ax2)
ax2.set_ylabel('AAPL price (USD)')
# Show the plot.
plt.gcf().set_size_inches(18, 8)
plt.show()
def _test_args():
"""Extra arguments to use when catalyst's automated tests run this example.
"""
import pandas as pd
return {
'start': pd.Timestamp('2014-01-01', tz='utc'),
'end': pd.Timestamp('2014-11-01', tz='utc'),
}
-67
View File
@@ -1,67 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2014 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from catalyst.api import (
order_target_percent,
record,
symbol,
get_open_orders,
)
def initialize(context):
context.asset = symbol('USDT_BTC')
def handle_data(context, data):
if context.asset not in get_open_orders() and data.can_trade(context.asset):
order_target_percent(context.asset, 1.0)
record(
USDT_BTC=data.current(context.asset, 'price'),
leverage=context.account.leverage,
)
# Note: this function can be removed if running
# this algorithm on quantopian.com
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
# Plot the portfolio and asset data.
ax1 = plt.subplot(311)
results.portfolio_value.plot(ax=ax1)
ax1.set_ylabel('Portfolio value (USD)')
ax2 = plt.subplot(312, sharex=ax1)
results.USDT_BTC.plot(ax=ax2)
ax2.set_ylabel('USDT_BTC price (USD)')
ax3 = plt.subplot(313, sharex=ax1)
results.leverage.plot(ax=ax3)
ax3.set_ylabel('Leverage (USD)')
# Show the plot.
plt.gcf().set_size_inches(18, 8)
plt.show()
def _test_args():
"""Extra arguments to use when catalyst's automated tests run this example.
"""
import pandas as pd
return {
'start': pd.Timestamp('2014-01-01', tz='utc'),
'end': pd.Timestamp('2014-11-01', tz='utc'),
}
-109
View File
@@ -1,109 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2014 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Dual Moving Average Crossover algorithm.
This algorithm buys apple once its short moving average crosses
its long moving average (indicating upwards momentum) and sells
its shares once the averages cross again (indicating downwards
momentum).
"""
from catalyst.api import order, record, symbol
# Import exponential moving average from talib wrapper
from talib import EMA
def initialize(context):
context.asset = symbol('AAPL')
# To keep track of whether we invested in the stock or not
context.invested = False
def handle_data(context, data):
trailing_window = data.history(context.asset, 'price', 40, '1d')
if trailing_window.isnull().values.any():
return
short_ema = EMA(trailing_window.values, timeperiod=20)
long_ema = EMA(trailing_window.values, timeperiod=40)
buy = False
sell = False
if (short_ema[-1] > long_ema[-1]) and not context.invested:
order(context.asset, 100)
context.invested = True
buy = True
elif (short_ema[-1] < long_ema[-1]) and context.invested:
order(context.asset, -100)
context.invested = False
sell = True
record(AAPL=data.current(context.asset, "price"),
short_ema=short_ema[-1],
long_ema=long_ema[-1],
buy=buy,
sell=sell)
# Note: this function can be removed if running
# this algorithm on quantopian.com
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
import logbook
logbook.StderrHandler().push_application()
log = logbook.Logger('Algorithm')
fig = plt.figure()
ax1 = fig.add_subplot(211)
results.portfolio_value.plot(ax=ax1)
ax1.set_ylabel('Portfolio value (USD)')
ax2 = fig.add_subplot(212)
ax2.set_ylabel('Price (USD)')
# If data has been record()ed, then plot it.
# Otherwise, log the fact that no data has been recorded.
if 'AAPL' in results and 'short_ema' in results and 'long_ema' in results:
results[['AAPL', 'short_ema', 'long_ema']].plot(ax=ax2)
ax2.plot(results.ix[results.buy].index, results.short_ema[results.buy],
'^', markersize=10, color='m')
ax2.plot(results.ix[results.sell].index,
results.short_ema[results.sell],
'v', markersize=10, color='k')
plt.legend(loc=0)
plt.gcf().set_size_inches(18, 8)
else:
msg = 'AAPL, short_ema and long_ema data not captured using record().'
ax2.annotate(msg, xy=(0.1, 0.5))
log.info(msg)
plt.show()
def _test_args():
"""Extra arguments to use when catalyst's automated tests run this example.
"""
import pandas as pd
return {
'start': pd.Timestamp('2014-01-01', tz='utc'),
'end': pd.Timestamp('2014-11-01', tz='utc'),
}
-108
View File
@@ -1,108 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2014 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Dual Moving Average Crossover algorithm.
This algorithm buys apple once its short moving average crosses
its long moving average (indicating upwards momentum) and sells
its shares once the averages cross again (indicating downwards
momentum).
"""
from catalyst.api import order_target, record, symbol
def initialize(context):
context.sym = symbol('AAPL')
context.i = 0
def handle_data(context, data):
# Skip first 300 days to get full windows
context.i += 1
if context.i < 300:
return
# Compute averages
# history() has to be called with the same params
# from above and returns a pandas dataframe.
short_mavg = data.history(context.sym, 'price', 100, '1d').mean()
long_mavg = data.history(context.sym, 'price', 300, '1d').mean()
# Trading logic
if short_mavg > long_mavg:
# order_target orders as many shares as needed to
# achieve the desired number of shares.
order_target(context.sym, 100)
elif short_mavg < long_mavg:
order_target(context.sym, 0)
# Save values for later inspection
record(AAPL=data.current(context.sym, "price"),
short_mavg=short_mavg,
long_mavg=long_mavg)
# Note: this function can be removed if running
# this algorithm on quantopian.com
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
import logbook
logbook.StderrHandler().push_application()
log = logbook.Logger('Algorithm')
fig = plt.figure()
ax1 = fig.add_subplot(211)
results.portfolio_value.plot(ax=ax1)
ax1.set_ylabel('Portfolio value (USD)')
ax2 = fig.add_subplot(212)
ax2.set_ylabel('Price (USD)')
# If data has been record()ed, then plot it.
# Otherwise, log the fact that no data has been recorded.
if ('AAPL' in results and 'short_mavg' in results and
'long_mavg' in results):
results['AAPL'].plot(ax=ax2)
results[['short_mavg', 'long_mavg']].plot(ax=ax2)
trans = results.ix[[t != [] for t in results.transactions]]
buys = trans.ix[[t[0]['amount'] > 0 for t in
trans.transactions]]
sells = trans.ix[
[t[0]['amount'] < 0 for t in trans.transactions]]
ax2.plot(buys.index, results.short_mavg.ix[buys.index],
'^', markersize=10, color='m')
ax2.plot(sells.index, results.short_mavg.ix[sells.index],
'v', markersize=10, color='k')
plt.legend(loc=0)
else:
msg = 'AAPL, short_mavg & long_mavg data not captured using record().'
ax2.annotate(msg, xy=(0.1, 0.5))
log.info(msg)
plt.show()
def _test_args():
"""Extra arguments to use when catalyst's automated tests run this example.
"""
import pandas as pd
return {
'start': pd.Timestamp('2011', tz='utc'),
'end': pd.Timestamp('2013', tz='utc'),
}
@@ -14,8 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
from catalyst.api import (
order_target_percent,
record,
@@ -33,27 +31,21 @@ from catalyst.api import (
from catalyst.pipeline import Pipeline
from catalyst.pipeline.data import CryptoPricing
from catalyst.pipeline.factors.crypto import (
VWAP,
SimpleMovingAverage,
)
from catalyst.pipeline.factors.crypto import VWAP
from catalyst.finance.commission import PerDollar
from catalyst.finance.slippage import VolumeShareSlippage
ASSET = 'USDT_BTC'
TARGET_INVESTMENT_RATIO = 0.8
SHORT_WINDOW = 30
LONG_WINDOW = 100
def initialize(context):
context.asset = symbol('USDT_BTC')
context.i = 0
context.asset = symbol(ASSET)
set_commission(PerDollar(cost=0.001))
set_slippage(VolumeShareSlippage())
set_max_leverage(1.0)
attach_pipeline(make_pipeline(), 'my_pipeline')
attach_pipeline(make_pipeline(), 'vwap_pipeline')
schedule_function(
rebalance,
@@ -62,21 +54,17 @@ def initialize(context):
def before_trading_start(context, data):
context.pipeline_data = pipeline_output('my_pipeline')
context.pipeline_data = pipeline_output('vwap_pipeline')
def make_pipeline():
return Pipeline(
columns={
'price': CryptoPricing.close.latest,
'price': CryptoPricing.open.latest,
'short_mavg': VWAP(window_length=SHORT_WINDOW),
'long_mavg': VWAP(window_length=LONG_WINDOW),
}
)
def handle_data(context, data):
pass
def rebalance(context, data):
context.i += 1
@@ -98,24 +86,14 @@ def rebalance(context, data):
if context.asset not in open_orders:
# check that the asset of interest can currently be traded
if data.can_trade(context.asset):
# adjust portfolio based on moving averages
# adjust portfolio based on comparison of long and short vwap
if short_mavg > long_mavg:
order_target_percent(
context.asset,
TARGET_INVESTMENT_RATIO,
#limit_price=(2 * price),
#stop_price=(0.5 * price),
)
order_target_percent(context.asset, TARGET_INVESTMENT_RATIO)
elif short_mavg < long_mavg:
order_target_percent(
context.asset,
0.0,
#limit_price=(2 * price),
#stop_price=(0.5 * price),
)
order_target_percent(context.asset, 0.0)
record(
USDT_BTC=price,
price=price,
cash=context.portfolio.cash,
leverage=context.account.leverage,
short_mavg=short_mavg,
@@ -135,27 +113,29 @@ def analyze(context=None, results=None):
ax1.set_ylabel('Portfolio value (USD)')
ax2 = plt.subplot(512, sharex=ax1)
ax2.set_ylabel('USDT_BTC (USD)')
results[['USDT_BTC', 'short_mavg', 'long_mavg']].plot(ax=ax2)
ax2.set_ylabel('{asset} (USD)'.format(asset=ASSET))
results[['price', 'short_mavg', 'long_mavg']].plot(ax=ax2)
trans = results.ix[[t != [] for t in results.transactions]]
amounts = [t[0]['amount'] for t in trans.transactions]
print 'amounts:\n', amounts
buys = trans.ix[
[t[0]['amount'] > 0 for t in trans.transactions]
]
sells = trans.ix[
[t[0]['amount'] < 0 for t in trans.transactions]
]
print 'buys:', buys.head()
ax2.plot(
buys.index, results.USDT_BTC[buys.index],
buys.index,
results.price[buys.index],
'^',
markersize=10,
color='m',
)
ax2.plot(
sells.index, results.USDT_BTC[sells.index],
sells.index,
results.price[sells.index],
'v',
markersize=10,
color='k',
@@ -185,7 +165,7 @@ def analyze(context=None, results=None):
'algorithm',
'benchmark',
]].plot(ax=ax5)
ax5.set_ylabel('Dollars (USD)')
ax5.set_ylabel('Percent Change')
plt.legend(loc=3)
-110
View File
@@ -1,110 +0,0 @@
"""
A simple Pipeline algorithm that longs the top 3 stocks by RSI and shorts
the bottom 3 each day.
"""
from six import viewkeys
from catalyst.api import (
attach_pipeline,
date_rules,
order_target_percent,
pipeline_output,
record,
schedule_function,
symbol,
)
from catalyst.pipeline import Pipeline
from catalyst.pipeline.factors.crypto import RSI
def make_pipeline():
rsi = RSI()
return Pipeline(
columns={
'longs': rsi.top(3),
'shorts': rsi.bottom(3),
},
)
def rebalance(context, data):
# Pipeline data will be a dataframe with boolean columns named 'longs' and
# 'shorts'.
pipeline_data = context.pipeline_data
all_assets = pipeline_data.index
longs = all_assets[pipeline_data.longs]
shorts = all_assets[pipeline_data.shorts]
record(
universe_size=len(all_assets),
leverage=context.account.leverage,
)
# Build a 2x-leveraged, equal-weight, long-short portfolio.
one_third = 1.0 / 3.0
for asset in longs:
order_target_percent(asset, one_third)
for asset in shorts:
order_target_percent(asset, -one_third)
# Remove any assets that should no longer be in our portfolio.
portfolio_assets = longs | shorts
positions = context.portfolio.positions
for asset in viewkeys(positions) - set(portfolio_assets):
# This will fail if the asset was removed from our portfolio because it
# was delisted.
if data.can_trade(asset):
order_target_percent(asset, 0)
def initialize(context):
attach_pipeline(make_pipeline(), 'my_pipeline')
# Rebalance each day. In daily mode, this is equivalent to putting
# `rebalance` in our handle_data, but in minute mode, it's equivalent to
# running at the start of the day each day.
schedule_function(rebalance, date_rules.every_day())
def before_trading_start(context, data):
context.pipeline_data = pipeline_output('my_pipeline')
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
ax1 = plt.subplot(311)
results.portfolio_value.plot(ax=ax1)
ax1.set_ylabel('Portfolio value (USD)')
ax2 = plt.subplot(312, sharex=ax1)
results.universe_size.plot(ax=ax2)
ax2.set_ylabel('Universe Size')
ax3 = plt.subplot(313, sharex=ax1)
results.leverage.plot(ax=ax3)
ax3.set_ylabel('Leverage (USD)')
plt.gcf().set_size_inches(18, 8)
plt.show()
def _test_args():
"""
Extra arguments to use when catalyst's automated tests run this example.
Notes for testers:
Gross leverage should be roughly 2.0 on every day except the first.
Net leverage should be roughly 2.0 on every day except the first.
Longs Count should always be 3 after the first day.
Shorts Count should be 3 after the first day, except on 2013-10-30, when it
dips to 2 for a day because DELL is delisted.
"""
import pandas as pd
return {
# We run through october of 2013 because DELL is in the test data and
# it went private on 2013-10-29.
'start': pd.Timestamp('2013-10-07', tz='utc'),
'end': pd.Timestamp('2013-11-30', tz='utc'),
'capital_base': 100000,
}
-167
View File
@@ -1,167 +0,0 @@
import sys
import logbook
import numpy as np
from catalyst.finance import commission
catalyst_logging = logbook.NestedSetup([
logbook.NullHandler(),
logbook.StreamHandler(sys.stdout, level=logbook.INFO),
logbook.StreamHandler(sys.stderr, level=logbook.ERROR),
])
catalyst_logging.push_application()
STOCKS = ['AMD', 'CERN', 'COST', 'DELL', 'GPS', 'INTC', 'MMM']
# On-Line Portfolio Moving Average Reversion
# More info can be found in the corresponding paper:
# http://icml.cc/2012/papers/168.pdf
def initialize(algo, eps=1, window_length=5):
algo.stocks = STOCKS
algo.sids = [algo.symbol(symbol) for symbol in algo.stocks]
algo.m = len(algo.stocks)
algo.price = {}
algo.b_t = np.ones(algo.m) / algo.m
algo.last_desired_port = np.ones(algo.m) / algo.m
algo.eps = eps
algo.init = True
algo.days = 0
algo.window_length = window_length
algo.set_commission(commission.PerShare(cost=0))
def handle_data(algo, data):
algo.days += 1
if algo.days < algo.window_length:
return
if algo.init:
rebalance_portfolio(algo, data, algo.b_t)
algo.init = False
return
m = algo.m
x_tilde = np.zeros(m)
# find relative moving average price for each asset
mavgs = data.history(algo.sids, 'price', algo.window_length, '1d').mean()
for i, sid in enumerate(algo.sids):
price = data.current(sid, "price")
# Relative mean deviation
x_tilde[i] = mavgs[sid] / price
###########################
# Inside of OLMAR (algo 2)
x_bar = x_tilde.mean()
# market relative deviation
mark_rel_dev = x_tilde - x_bar
# Expected return with current portfolio
exp_return = np.dot(algo.b_t, x_tilde)
weight = algo.eps - exp_return
variability = (np.linalg.norm(mark_rel_dev)) ** 2
# test for divide-by-zero case
if variability == 0.0:
step_size = 0
else:
step_size = max(0, weight / variability)
b = algo.b_t + step_size * mark_rel_dev
b_norm = simplex_projection(b)
np.testing.assert_almost_equal(b_norm.sum(), 1)
rebalance_portfolio(algo, data, b_norm)
# update portfolio
algo.b_t = b_norm
def rebalance_portfolio(algo, data, desired_port):
# rebalance portfolio
desired_amount = np.zeros_like(desired_port)
current_amount = np.zeros_like(desired_port)
prices = np.zeros_like(desired_port)
if algo.init:
positions_value = algo.portfolio.starting_cash
else:
positions_value = algo.portfolio.positions_value + \
algo.portfolio.cash
for i, sid in enumerate(algo.sids):
current_amount[i] = algo.portfolio.positions[sid].amount
prices[i] = data.current(sid, "price")
desired_amount = np.round(desired_port * positions_value / prices)
algo.last_desired_port = desired_port
diff_amount = desired_amount - current_amount
for i, sid in enumerate(algo.sids):
algo.order(sid, diff_amount[i])
def simplex_projection(v, b=1):
"""Projection vectors to the simplex domain
Implemented according to the paper: Efficient projections onto the
l1-ball for learning in high dimensions, John Duchi, et al. ICML 2008.
Implementation Time: 2011 June 17 by Bin@libin AT pmail.ntu.edu.sg
Optimization Problem: min_{w}\| w - v \|_{2}^{2}
s.t. sum_{i=1}^{m}=z, w_{i}\geq 0
Input: A vector v \in R^{m}, and a scalar z > 0 (default=1)
Output: Projection vector w
:Example:
>>> proj = simplex_projection([.4 ,.3, -.4, .5])
>>> proj # doctest: +NORMALIZE_WHITESPACE
array([ 0.33333333, 0.23333333, 0. , 0.43333333])
>>> print(proj.sum())
1.0
Original matlab implementation: John Duchi (jduchi@cs.berkeley.edu)
Python-port: Copyright 2013 by Thomas Wiecki (thomas.wiecki@gmail.com).
"""
v = np.asarray(v)
p = len(v)
# Sort v into u in descending order
v = (v > 0) * v
u = np.sort(v)[::-1]
sv = np.cumsum(u)
rho = np.where(u > (sv - b) / np.arange(1, p + 1))[0][-1]
theta = np.max([0, (sv[rho] - b) / (rho + 1)])
w = (v - theta)
w[w < 0] = 0
return w
# Note: this function can be removed if running
# this algorithm on quantopian.com
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
results.portfolio_value.plot(ax=ax)
ax.set_ylabel('Portfolio value (USD)')
plt.show()
def _test_args():
"""Extra arguments to use when catalyst's automated tests run this example.
"""
import pandas as pd
return {
'start': pd.Timestamp('2004', tz='utc'),
'end': pd.Timestamp('2008', tz='utc'),
}
-232
View File
@@ -1,232 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2014 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
from catalyst.api import (
order_target_percent,
record,
symbol,
get_open_orders,
set_commission,
set_slippage,
set_max_leverage,
schedule_function,
date_rules,
time_rules,
attach_pipeline,
pipeline_output,
)
from catalyst.pipeline import Pipeline
from catalyst.pipeline.data import CryptoPricing
from catalyst.pipeline.factors.crypto import (
VWAP,
SimpleMovingAverage,
MACDSignal,
)
from catalyst.finance.commission import PerDollar
from catalyst.finance.slippage import VolumeShareSlippage
TARGET_INVESTMENT_RATIO = 0.2
SHORT_WINDOW = 30
LONG_WINDOW = 100
def initialize(context):
context.asset = symbol('USDT_BTC')
context.i = 0
context.macd_cur = None
context.macd_last = None
set_commission(PerDollar(cost=0.001))
set_slippage(VolumeShareSlippage())
set_max_leverage(1.0)
attach_pipeline(make_pipeline(), 'my_pipeline')
schedule_function(
rebalance,
date_rules.every_day(),
)
def before_trading_start(context, data):
context.pipeline_data = pipeline_output('my_pipeline')
def make_pipeline():
return Pipeline(
columns={
'price': CryptoPricing.close.latest,
'short_mavg': VWAP(window_length=SHORT_WINDOW),
'long_mavg': VWAP(window_length=LONG_WINDOW),
'macd': MACDSignal(
fast_period=24,
slow_period=52,
signal_period=18,
),
},
)
def handle_data(context, data):
pass
def rebalance(context, data):
context.i += 1
# get pipeline data for asset of interest
pipeline_data = context.pipeline_data
pipeline_data = pipeline_data[pipeline_data.index == context.asset].iloc[0]
context.macd_last = context.macd_cur
context.macd_cur = pipeline_data.macd
# skip first LONG_WINDOW bars to fill windows
if context.i < 2:
return
# retrieve long and short moving averages from pipeline
short_mavg = pipeline_data.short_mavg
long_mavg = pipeline_data.long_mavg
price = pipeline_data.price
# check that order has not already been placed
open_orders = get_open_orders()
if context.asset not in open_orders:
# check that the asset of interest can currently be traded
if data.can_trade(context.asset):
if context.macd_cur < (0.98 * context.macd_last):
order_target_percent(
context.asset,
TARGET_INVESTMENT_RATIO,
#limit_price=(2 * price),
#stop_price=(0.5 * price),
)
elif context.macd_cur > (1.02 * context.macd_last):
order_target_percent(
context.asset,
0.0,
#limit_price=(2 * price),
#stop_price=(0.5 * price),
)
"""
# adjust portfolio based on moving averages
if short_mavg > long_mavg:
order_target_percent(
context.asset,
TARGET_INVESTMENT_RATIO,
#limit_price=(2 * price),
#stop_price=(0.5 * price),
)
elif short_mavg < long_mavg:
order_target_percent(
context.asset,
0.0,
#limit_price=(2 * price),
#stop_price=(0.5 * price),
)
"""
record(
USDT_BTC=price,
cash=context.portfolio.cash,
leverage=context.account.leverage,
short_mavg=short_mavg,
long_mavg=long_mavg,
)
# Note: this function can be removed if running
# this algorithm on quantopian.com
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
# Plot the portfolio and asset data.
ax1 = plt.subplot(511)
results[['portfolio_value']].plot(ax=ax1)
ax1.set_ylabel('Portfolio value (USD)')
ax2 = plt.subplot(512, sharex=ax1)
ax2.set_ylabel('USDT_BTC (USD)')
results[['USDT_BTC', 'short_mavg', 'long_mavg']].plot(ax=ax2)
trans = results.ix[[t != [] for t in results.transactions]]
amounts = [t[0]['amount'] for t in trans.transactions]
print 'amounts:\n', amounts
buys = trans.ix[
[t[0]['amount'] > 0 for t in trans.transactions]
]
sells = trans.ix[
[t[0]['amount'] < 0 for t in trans.transactions]
]
print 'buys:', buys.head()
ax2.plot(
buys.index, results.USDT_BTC[buys.index],
'^',
markersize=10,
color='m',
)
ax2.plot(
sells.index, results.USDT_BTC[sells.index],
'v',
markersize=10,
color='k',
)
ax3 = plt.subplot(513, sharex=ax1)
results[['leverage', 'alpha', 'beta']].plot(ax=ax3)
ax3.set_ylabel('Leverage (USD)')
ax4 = plt.subplot(514, sharex=ax1)
results[['cash']].plot(ax=ax4)
ax4.set_ylabel('Cash (USD)')
results[[
'treasury',
'algorithm',
'benchmark',
]] = results[[
'treasury_period_return',
'algorithm_period_return',
'benchmark_period_return',
]]
ax5 = plt.subplot(515, sharex=ax1)
results[[
'treasury',
'algorithm',
'benchmark',
]].plot(ax=ax5)
ax5.set_ylabel('Dollars (USD)')
plt.legend(loc=3)
# Show the plot.
plt.gcf().set_size_inches(18, 8)
plt.show()
def _test_args():
"""Extra arguments to use when catalyst's automated tests run this example.
"""
import pandas as pd
return {
'start': pd.Timestamp('2014-01-01', tz='utc'),
'end': pd.Timestamp('2014-11-01', tz='utc'),
}