Compare commits

...
26 Commits
Author SHA1 Message Date
AvishaiW c571c1c2ae TST: fixing zipline tests (WIP) 2018-02-13 11:53:05 +02:00
Victor Grau Serrat f279101393 TST: adapting zipline tests to catalyst: risk, events + data (WIP) 2017-12-04 23:06:06 -07:00
fredfortier 96a27d083c BLD: more live trading tests and fixed related issues 2017-12-03 00:04:15 -05:00
fredfortier f995f451a7 BLD: some refactoring to simplify the integration logic and tested several algos 2017-12-02 21:27:03 -05:00
fredfortier a3838fc00f BLD: tested ccxt with manual data ingestion 2017-12-02 20:20:57 -05:00
fredfortier 4db8131397 BLD: paper trading adjustments 2017-12-01 00:06:11 -05:00
fredfortier 207bce6216 Merge remote-tracking branch 'origin/develop' into develop 2017-11-30 23:16:16 -05:00
fredfortier 8fb8b80a12 BLD: first rough test of CCXT in live trading 2017-11-30 23:15:10 -05:00
fredfortier b762689225 BLD: all exchange operations now implemented an unit tested with CCXT 2017-11-30 22:45:52 -05:00
fredfortier 7bbb6e0b42 BLD: tested creating orders and viewing open orders with CCXT 2017-11-30 20:18:16 -05:00
Victor Grau Serrat b587804e3e DOC: fix video links to algos 2017-11-30 17:11:15 -07:00
fredfortier 5660247da2 BLD: tested all public APIs with CCXT 2017-11-30 17:08:13 -05:00
fredfortier fc2c44a6b7 Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	catalyst/examples/mean_reversion_simple.py
2017-11-29 22:33:46 -05:00
fredfortier 4eb8a6eb0f BLD: populating assets with help from CCXT 2017-11-29 22:31:44 -05:00
Victor Grau Serrat c8eaa11f80 DOC: added portfolio_optimization to documented examples 2017-11-29 09:37:46 -07:00
Victor Grau Serrat 55a9d76b9b Merge branch 'master' into develop 2017-11-29 09:24:59 -07:00
Victor Grau Serrat 7abd992d17 DOC: added portfolio_optimization example 2017-11-29 09:19:41 -07:00
Victor Grau Serrat daeccaed36 DOC: video - live trading 2017-11-28 16:44:13 -07:00
Victor Grau Serrat 25358a4077 Merge branch 'master' into develop 2017-11-28 12:44:19 -07:00
Victor Grau Serrat 7cf4f84e89 DOC: documented 4 example algorithms 2017-11-28 12:35:50 -07:00
Victor Grau Serrat b63199e4e1 DOC: adjusting example params to match video tutorial 2017-11-28 12:24:53 -07:00
Victor Grau Serrat 4af08be7e8 Merge branch 'develop' of github.com:enigmampc/catalyst into develop 2017-11-28 12:23:19 -07:00
fredfortier 606148e19c DOC: Integrating with ccxt 2017-11-28 13:42:58 -05:00
Victor Grau Serrat d38e560265 Merge branch 'master' into develop 2017-11-28 11:23:31 -07:00
Victor Grau Serrat ffd1bc07cc DOC: making example algos consistent with doc website 2017-11-28 11:22:41 -07:00
fredfortier dfcfe5a370 merging from develop 2017-11-28 01:44:46 -05:00
86 changed files with 2405 additions and 1023 deletions
+35 -13
View File
@@ -396,11 +396,15 @@ cdef class Future(Asset):
cdef class TradingPair(Asset):
cdef readonly float leverage
cdef readonly object market_currency
cdef readonly object quote_currency
cdef readonly object base_currency
cdef readonly object end_daily
cdef readonly object end_minute
cdef readonly object exchange_symbol
cdef readonly float maker
cdef readonly float taker
cdef readonly int trading_state
cdef readonly object data_source
_kwargnames = frozenset({
'sid',
@@ -413,12 +417,16 @@ cdef class TradingPair(Asset):
'exchange',
'exchange_full',
'leverage',
'market_currency',
'quote_currency',
'base_currency',
'end_daily',
'end_minute',
'exchange_symbol',
'min_trade_size'
'min_trade_size',
'maker',
'taker',
'trading_state',
'data_source'
})
def __init__(self,
object symbol,
@@ -434,10 +442,14 @@ cdef class TradingPair(Asset):
object first_traded=None,
object auto_close_date=None,
object exchange_full=None,
object min_trade_size=None):
float min_trade_size=0.0001,
float maker=0.0015,
float taker=0.0025,
int trading_state=0,
object data_source='catalyst'):
"""
Replicates the Asset constructor with some built-in conventions
and a new 'leverage' attribute.
and adds properties for leverage and fees.
Symbol
------
@@ -469,8 +481,6 @@ cdef class TradingPair(Asset):
highest volume and market cap generally benefit from high leverage.
New currencies from ICO generally cannot be leveraged.
The leverage value is either None or and integer.
Leverage allows you to open a larger position with a smaller amount
of funds. For example, if you open a $5,000 position in BTC/USD
with 5:1 leverage, only one-fifth of this amount, or $1000, will be
@@ -480,6 +490,11 @@ cdef class TradingPair(Asset):
the position. If you open with 1:1 leverage, $5,000 of your balance
will be tied to the position.
Fees
----
Exchanges generally charge a taker (taking from the order book) or
maker (adding to the order book) fee.
:param symbol:
:param exchange:
:param start_date:
@@ -494,11 +509,14 @@ cdef class TradingPair(Asset):
:param auto_close_date:
:param exchange_full:
:param min_trade_size:
:param maker:
:param taker:
:param data_source
"""
symbol = symbol.lower()
try:
self.market_currency, self.base_currency = symbol.split('_')
self.base_currency, self.quote_currency = symbol.split('_')
except Exception as e:
raise InvalidSymbolError(symbol=symbol, error=e)
@@ -512,7 +530,7 @@ cdef class TradingPair(Asset):
asset_name = ' / '.join(symbol.split('_')).upper()
if start_date is None:
start_date = pd.Timestamp.utcnow()
start_date = pd.to_datetime('2009-1-1', utc=True)
if end_date is None:
end_date = pd.Timestamp.utcnow() + timedelta(days=365)
@@ -527,19 +545,23 @@ cdef class TradingPair(Asset):
first_traded=first_traded,
auto_close_date=auto_close_date,
exchange_full=exchange_full,
min_trade_size=min_trade_size
min_trade_size=min_trade_size,
)
self.maker = maker
self.taker = taker
self.leverage = leverage
self.end_daily = end_daily
self.end_minute = end_minute
self.exchange_symbol = exchange_symbol
self.trading_state = trading_state
self.data_source = data_source
def __repr__(self):
return 'Trading Pair {symbol}({sid}) Exchange: {exchange}, ' \
'Introduced On: {start_date}, ' \
'Market Currency: {market_currency}, ' \
'Base Currency: {base_currency}, ' \
'Quote Currency: {quote_currency}, ' \
'Exchange Leverage: {leverage}, ' \
'Minimum Trade Size: {min_trade_size} ' \
'Last daily ingestion: {end_daily} ' \
@@ -548,7 +570,7 @@ cdef class TradingPair(Asset):
sid=self.sid,
exchange=self.exchange,
start_date=self.start_date,
market_currency=self.market_currency,
quote_currency=self.quote_currency,
base_currency=self.base_currency,
leverage=self.leverage,
min_trade_size=self.min_trade_size,
@@ -578,7 +600,7 @@ cdef class TradingPair(Asset):
-------
boolean: whether the asset's exchange is open at the given minute.
"""
#TODO: consider implementing to spot holds
#TODO: make more dymanic to catch holds
return True
cpdef __reduce__(self):
+2 -1
View File
@@ -7,7 +7,8 @@ import logbook
For example, if you want to see the DEBUG messages, run:
$ export CATALYST_LOG_LEVEL=10
'''
LOG_LEVEL = int(os.environ.get('CATALYST_LOG_LEVEL', logbook.INFO))
# LOG_LEVEL = int(os.environ.get('CATALYST_LOG_LEVEL', logbook.INFO))
LOG_LEVEL = logbook.DEBUG
SYMBOLS_URL = 'https://s3.amazonaws.com/enigmaco/catalyst-exchanges/' \
'{exchange}/symbols.json'
+4 -2
View File
@@ -142,8 +142,10 @@ def load_crypto_market_data(trading_day=None, trading_days=None,
if exchange is None:
# This is exceptional, since placing the import at the module scope
# breaks things and it's only needed here
from catalyst.exchange.poloniex.poloniex import Poloniex
exchange = Poloniex('', '', '')
from catalyst.exchange.factory import get_exchange
exchange = get_exchange(
exchange_name='poloniex', base_currency='usdt'
)
benchmark_asset = exchange.get_asset(bm_symbol)
+3
View File
@@ -0,0 +1,3 @@
An overview of most of the trading strategies in this folder can be found in the
`Examples Algorithms <https://enigmampc.github.io/catalyst/example-algos.html>`_
section of our documentation website.
+12 -12
View File
@@ -83,15 +83,15 @@ def place_orders(context, amount, buying_price, selling_price, action):
else:
raise ValueError('invalid order action')
base_currency = enter_exchange.base_currency
base_currency_amount = enter_exchange.portfolio.cash
quote_currency = enter_exchange.quote_currency
quote_currency_amount = enter_exchange.portfolio.cash
exit_balances = exit_exchange.get_balances()
exit_currency = context.trading_pairs[
context.selling_exchange].market_currency
context.selling_exchange].quote_currency
if exit_currency in exit_balances:
market_currency_amount = exit_balances[exit_currency]
quote_currency_amount = exit_balances[exit_currency]
else:
log.warn(
'the selling exchange {exchange_name} does not hold '
@@ -102,25 +102,25 @@ def place_orders(context, amount, buying_price, selling_price, action):
)
return
if base_currency_amount < (amount * entry_price):
adj_amount = base_currency_amount / entry_price
if quote_currency_amount < (amount * entry_price):
adj_amount = quote_currency_amount / entry_price
log.warn(
'not enough {base_currency} ({base_currency_amount}) to buy '
'not enough {quote_currency} ({quote_currency_amount}) to buy '
'{amount}, adjusting the amount to {adj_amount}'.format(
base_currency=base_currency,
base_currency_amount=base_currency_amount,
quote_currency=quote_currency,
quote_currency_amount=quote_currency_amount,
amount=amount,
adj_amount=adj_amount
)
)
amount = adj_amount
elif market_currency_amount < amount:
elif quote_currency_amount < amount:
log.warn(
'not enough {currency} ({currency_amount}) to sell '
'{amount}, aborting'.format(
currency=exit_currency,
currency_amount=market_currency_amount,
currency_amount=quote_currency_amount,
amount=amount
)
)
@@ -270,6 +270,6 @@ run_algorithm(
exchange_name='poloniex,bitfinex',
live=True,
algo_namespace=algo_namespace,
base_currency='btc',
quote_currency='btc',
live_graph=False
)
+10 -15
View File
@@ -15,15 +15,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import pandas as pd
import matplotlib.pyplot as plt
from catalyst import run_algorithm
from catalyst.api import (
order_target_value,
symbol,
record,
cancel_order,
get_open_orders,
)
from catalyst.api import (order_target_value, symbol, record,
cancel_order, get_open_orders, )
def initialize(context):
@@ -78,15 +74,14 @@ def handle_data(context, data):
def analyze(context=None, results=None):
import matplotlib.pyplot as plt
# Plot the portfolio and asset data.
ax1 = plt.subplot(611)
results[['portfolio_value']].plot(ax=ax1)
ax1.set_ylabel('Portfolio Value (USD)')
ax1.set_ylabel('Portfolio\nValue\n(USD)')
ax2 = plt.subplot(612, sharex=ax1)
ax2.set_ylabel('{asset} (USD)'.format(asset=context.ASSET_NAME))
ax2.set_ylabel('{asset}\n(USD)'.format(asset=context.ASSET_NAME))
results[['price']].plot(ax=ax2)
trans = results.ix[[t != [] for t in results.transactions]]
@@ -126,11 +121,11 @@ def analyze(context=None, results=None):
'algorithm',
'benchmark',
]].plot(ax=ax5)
ax5.set_ylabel('Percent Change')
ax5.set_ylabel('Percent\nChange')
ax6 = plt.subplot(616, sharex=ax1)
results[['volume']].plot(ax=ax6)
ax6.set_ylabel('Volume (mCoins/5min)')
ax6.set_ylabel('Volume')
plt.legend(loc=3)
@@ -142,13 +137,13 @@ def analyze(context=None, results=None):
if __name__ == '__main__':
run_algorithm(
capital_base=10000,
data_frequency='minute',
data_frequency='daily',
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='bitfinex',
algo_namespace='buy_and_hodl',
base_currency='usd',
start=pd.to_datetime('2017-11-01', utc=True),
end=pd.to_datetime('2017-11-10', utc=True),
start=pd.to_datetime('2015-03-01', utc=True),
end=pd.to_datetime('2017-10-31', utc=True),
)
+3 -2
View File
@@ -3,7 +3,8 @@
https://enigmampc.github.io/catalyst/beginner-tutorial.html
Run this example, by executing the following from your terminal:
catalyst run -f buy_btc_simple.py -x bitfinex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle
catalyst ingest-exchange -x bitfinex -f daily -i btc_usdt
catalyst run -f buy_btc_simple.py -x bitfinex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle
If you want to run this code using another exchange, make sure that
the asset is available on that exchange. For example, if you were to run
@@ -12,7 +13,7 @@
context.asset = symbol('btc_usdt') # note 'usdt' instead of 'usd'
and specify exchange poloniex as follows:
catalyst ingest-exchange -x poloniex -f daily -i btc_usdt
catalyst run -f buy_btc_simple.py -x poloniex --start 2016-1-1 --end 2017-9-30 -o buy_btc_simple_out.pickle
To see which assets are available on each exchange, visit:
+18 -14
View File
@@ -5,6 +5,7 @@ import os
import tempfile
import time
import numpy as np
import pandas as pd
import talib
from logbook import Logger
@@ -31,13 +32,13 @@ def initialize(context):
# trading pairs) you want to backtest. You'll also want to define any
# parameters or values you're going to use.
# In our example, we're looking at Ether in USD Tether.
# In our example, we're looking at Neo in Ether.
context.neo_eth = symbol('neo_eth')
context.base_price = None
context.current_day = None
context.RSI_OVERSOLD = 50
context.RSI_OVERBOUGHT = 80
context.RSI_OVERSOLD = 55
context.RSI_OVERBOUGHT = 82
context.CANDLE_SIZE = '5T'
context.start_time = time.time()
@@ -160,13 +161,13 @@ def analyze(context=None, perf=None):
# Plot the portfolio value over time.
ax1 = plt.subplot(611)
perf.loc[:, 'portfolio_value'].plot(ax=ax1)
ax1.set_ylabel('Portfolio Value ({})'.format(base_currency))
ax1.set_ylabel('Portfolio\nValue\n({})'.format(base_currency))
# Plot the price increase or decrease over time.
ax2 = plt.subplot(612, sharex=ax1)
perf.loc[:, 'price'].plot(ax=ax2, label='Price')
ax2.set_ylabel('{asset} ({base})'.format(
ax2.set_ylabel('{asset}\n({base})'.format(
asset=context.neo_eth.symbol, base=base_currency
))
@@ -195,18 +196,19 @@ def analyze(context=None, perf=None):
perf.loc[:, 'cash'].plot(
ax=ax4, label='Base Currency ({})'.format(base_currency)
)
ax4.set_ylabel('Cash ({})'.format(base_currency))
ax4.set_ylabel('Cash\n({})'.format(base_currency))
perf['algorithm'] = perf.loc[:, 'algorithm_period_return']
ax5 = plt.subplot(614, sharex=ax1)
perf.loc[:, ['algorithm', 'price_change']].plot(ax=ax5)
ax5.set_ylabel('Percent Change')
ax5.set_ylabel('Percent\nChange')
ax6 = plt.subplot(615, sharex=ax1)
perf.loc[:, 'rsi'].plot(ax=ax6, label='RSI')
ax6.axhline(70, color='darkgoldenrod')
ax6.axhline(30, color='darkgoldenrod')
ax6.set_ylabel('RSI')
ax6.axhline(context.RSI_OVERBOUGHT, color='darkgoldenrod')
ax6.axhline(context.RSI_OVERSOLD, color='darkgoldenrod')
if not transaction_df.empty:
ax6.scatter(
@@ -226,6 +228,8 @@ def analyze(context=None, perf=None):
label=''
)
plt.legend(loc=3)
start, end = ax6.get_ylim()
ax6.yaxis.set_ticks(np.arange(0, end, end/5))
# Show the plot.
plt.gcf().set_size_inches(18, 8)
@@ -235,7 +239,7 @@ def analyze(context=None, perf=None):
if __name__ == '__main__':
# The execution mode: backtest or live
MODE = 'backtest'
MODE = 'live'
if MODE == 'backtest':
folder = os.path.join(
@@ -245,16 +249,16 @@ if __name__ == '__main__':
timestr = time.strftime('%Y%m%d-%H%M%S')
out = os.path.join(folder, '{}.p'.format(timestr))
# catalyst run -f catalyst/examples/mean_reversion_simple.py -x poloniex -s 2017-10-1 -e 2017-11-10 -c usdt -n mean-reversion --data-frequency minute --capital-base 10000
# catalyst run -f catalyst/examples/mean_reversion_simple.py -x bitfinex -s 2017-10-1 -e 2017-11-10 -c usdt -n mean-reversion --data-frequency minute --capital-base 10000
run_algorithm(
capital_base=10000,
capital_base=0.1,
data_frequency='minute',
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='bitfinex',
algo_namespace=NAMESPACE,
base_currency='usd',
base_currency='eth',
start=pd.to_datetime('2017-10-01', utc=True),
end=pd.to_datetime('2017-11-10', utc=True),
output=out
@@ -263,7 +267,7 @@ if __name__ == '__main__':
elif MODE == 'live':
run_algorithm(
capital_base=0.5,
capital_base=0.1,
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
+133
View File
@@ -0,0 +1,133 @@
'''Use this code to execute a portfolio optimization model. This code
will select the portfolio with the maximum Sharpe Ratio. The parameters
are set to use 180 days of historical data and rebalance every 30 days.
This is the code used in the following article:
https://blog.enigma.co/markowitz-portfolio-optimization-for-cryptocurrencies-in-catalyst-b23c38652556
You can run this code using the Python interpreter:
$ python portfolio_optimization.py
'''
from __future__ import division
import os
import pytz
import numpy as np
import pandas as pd
from scipy.optimize import minimize
import matplotlib.pyplot as plt
from datetime import datetime
from catalyst.api import record, symbol, symbols, order_target_percent
from catalyst.utils.run_algo import run_algorithm
np.set_printoptions(threshold='nan', suppress=True)
def initialize(context):
# Portfolio assets list
context.assets = symbols('btc_usdt', 'eth_usdt', 'ltc_usdt', 'dash_usdt',
'xmr_usdt')
context.nassets = len(context.assets)
# Set the time window that will be used to compute expected return
# and asset correlations
context.window = 180
# Set the number of days between each portfolio rebalancing
context.rebalance_period = 30
context.i = 0
def handle_data(context, data):
# Only rebalance at the beggining of the algorithm execution and
# every multiple of the rebalance period
if context.i == 0 or context.i%context.rebalance_period == 0:
n = context.window
prices = data.history(context.assets, fields='price',
bar_count=n+1, frequency='1d')
pr = np.asmatrix(prices)
t_prices = prices.iloc[1:n+1]
t_val = t_prices.values
tminus_prices = prices.iloc[0:n]
tminus_val = tminus_prices.values
# Compute daily returns (r)
r = np.asmatrix(t_val/tminus_val-1)
# Compute the expected returns of each asset with the average
# daily return for the selected time window
m = np.asmatrix(np.mean(r, axis=0))
# ###
stds = np.std(r, axis=0)
# Compute excess returns matrix (xr)
xr = r - m
# Matrix algebra to get variance-covariance matrix
cov_m = np.dot(np.transpose(xr),xr)/n
# Compute asset correlation matrix (informative only)
corr_m = cov_m/np.dot(np.transpose(stds),stds)
# Define portfolio optimization parameters
n_portfolios = 50000
results_array = np.zeros((3+context.nassets,n_portfolios))
for p in xrange(n_portfolios):
weights = np.random.random(context.nassets)
weights /= np.sum(weights)
w = np.asmatrix(weights)
p_r = np.sum(np.dot(w,np.transpose(m)))*365
p_std = np.sqrt(np.dot(np.dot(w,cov_m),np.transpose(w)))*np.sqrt(365)
#store results in results array
results_array[0,p] = p_r
results_array[1,p] = p_std
#store Sharpe Ratio (return / volatility) - risk free rate element
#excluded for simplicity
results_array[2,p] = results_array[0,p] / results_array[1,p]
i = 0
for iw in weights:
results_array[3+i,p] = weights[i]
i += 1
#convert results array to Pandas DataFrame
results_frame = pd.DataFrame(np.transpose(results_array),
columns=['r','stdev','sharpe']+context.assets)
#locate position of portfolio with highest Sharpe Ratio
max_sharpe_port = results_frame.iloc[results_frame['sharpe'].idxmax()]
#locate positon of portfolio with minimum standard deviation
min_vol_port = results_frame.iloc[results_frame['stdev'].idxmin()]
#order optimal weights for each asset
for asset in context.assets:
if data.can_trade(asset):
order_target_percent(asset, max_sharpe_port[asset])
#create scatter plot coloured by Sharpe Ratio
plt.scatter(results_frame.stdev,results_frame.r,c=results_frame.sharpe,cmap='RdYlGn')
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#plot red star to highlight position of portfolio with highest Sharpe Ratio
plt.scatter(max_sharpe_port[1],max_sharpe_port[0],marker='o',color='b',s=200)
#plot green star to highlight position of minimum variance portfolio
plt.show()
print(max_sharpe_port)
record(pr=pr,r=r, m=m, stds=stds ,max_sharpe_port=max_sharpe_port, corr_m=corr_m)
context.i += 1
def analyze(context=None, results=None):
# Form DataFrame with selected data
data = results[['pr','r','m','stds','max_sharpe_port','corr_m','portfolio_value']]
# Save results in CSV file
filename = os.path.splitext(os.path.basename(__file__))[0]
data.to_csv(filename + '.csv')
# Bitcoin data is available from 2015-3-2. Dates vary for other tokens.
start = datetime(2017, 1, 1, 0, 0, 0, 0, pytz.utc)
end = datetime(2017, 8, 16, 0, 0, 0, 0, pytz.utc)
results = run_algorithm(initialize=initialize,
handle_data=handle_data,
analyze=analyze,
start=start,
end=end,
exchange_name='poloniex',
capital_base=100000, )
+12 -14
View File
@@ -9,7 +9,7 @@ from catalyst.exchange.stats_utils import get_pretty_stats, \
def initialize(context):
print('initializing')
context.asset = symbol('neo_usd')
context.asset = symbol('neo_eth')
context.base_price = None
@@ -19,17 +19,14 @@ def handle_data(context, data):
price = data.current(context.asset, 'close')
print('got price {price}'.format(price=price))
try:
prices = data.history(
context.asset,
fields='price',
bar_count=14,
frequency='15T'
)
rsi = talib.RSI(prices.values, timeperiod=14)[-1]
print('got rsi: {}'.format(rsi))
except Exception as e:
print(e)
prices = data.history(
context.asset,
fields='price',
bar_count=20,
frequency='15T'
)
rsi = talib.RSI(prices.values, timeperiod=14)[-1]
print('got rsi: {}'.format(rsi))
# If base_price is not set, we use the current value. This is the
# price at the first bar which we reference to calculate price_change.
@@ -126,8 +123,9 @@ run_algorithm(
# initialize=initialize,
# handle_data=handle_data,
# analyze=None,
# exchange_name='poloniex',
# exchange_name='binance',
# live=True,
# algo_namespace='simple_loop',
# base_currency='eth',
# live_graph=False
# live_graph=False,
# )
View File
+600
View File
@@ -0,0 +1,600 @@
import re
from collections import defaultdict
import ccxt
import pandas as pd
from ccxt import ExchangeNotAvailable
from six import string_types
from catalyst.finance.order import Order, ORDER_STATUS
from catalyst.algorithm import MarketOrder
from catalyst.assets._assets import TradingPair
from logbook import Logger
from catalyst.constants import LOG_LEVEL
from catalyst.exchange.exchange import Exchange, ExchangeLimitOrder
from catalyst.exchange.exchange_bundle import ExchangeBundle
from catalyst.exchange.exchange_errors import InvalidHistoryFrequencyError, \
ExchangeSymbolsNotFound, ExchangeRequestError, InvalidOrderStyle, \
ExchangeNotFoundError
from catalyst.exchange.exchange_utils import mixin_market_params, \
from_ms_timestamp
log = Logger('CCXT', level=LOG_LEVEL)
SUPPORTED_EXCHANGES = dict(
binance=ccxt.binance,
bitfinex=ccxt.bitfinex,
bittrex=ccxt.bittrex,
poloniex=ccxt.poloniex,
bitmex=ccxt.bitmex,
gdax=ccxt.gdax,
)
class CCXT(Exchange):
def __init__(self, exchange_name, key, secret, base_currency,
portfolio=None):
log.debug(
'finding {} in CCXT exchanges:\n{}'.format(
exchange_name, ccxt.exchanges
)
)
try:
# Making instantiation as explicit as possible for code tracking.
if exchange_name in SUPPORTED_EXCHANGES:
exchange_attr = SUPPORTED_EXCHANGES[exchange_name]
else:
exchange_attr = getattr(ccxt, exchange_name)
self.api = exchange_attr({
'apiKey': key,
'secret': secret,
})
except Exception:
raise ExchangeNotFoundError(exchange_name=exchange_name)
self._symbol_maps = [None, None]
markets_symbols = self.api.load_markets()
log.debug('the markets:\n{}'.format(markets_symbols))
self.name = exchange_name
self.markets = self.api.fetch_markets()
self.load_assets()
self.base_currency = base_currency
self._portfolio = portfolio
self.transactions = defaultdict(list)
self.num_candles_limit = 2000
self.max_requests_per_minute = 60
self.request_cpt = dict()
self.bundle = ExchangeBundle(self.name)
def account(self):
return None
def time_skew(self):
return None
def get_market(self, symbol):
"""
The CCXT market.
Parameters
----------
symbol:
The CCXT symbol.
Returns
-------
dict[str, Object]
"""
s = self.get_symbol(symbol)
market = next(
(market for market in self.markets if market['symbol'] == s),
None,
)
return market
def get_symbol(self, asset_or_symbol):
"""
The CCXT symbol.
Parameters
----------
asset_or_symbol
Returns
-------
"""
symbol = asset_or_symbol if isinstance(
asset_or_symbol, string_types
) else asset_or_symbol.symbol
parts = symbol.split('_')
return '{}/{}'.format(parts[0].upper(), parts[1].upper())
def get_catalyst_symbol(self, market_or_symbol):
"""
The Catalyst symbol.
Parameters
----------
market_or_symbol
Returns
-------
"""
if isinstance(market_or_symbol, string_types):
parts = market_or_symbol.split('/')
return '{}_{}'.format(parts[0].lower(), parts[1].lower())
else:
return '{}_{}'.format(
market_or_symbol['base'].lower(),
market_or_symbol['quote'].lower(),
)
def get_timeframe(self, freq):
"""
The CCXT timeframe from the Catalyst frequency.
Parameters
----------
freq: str
The Catalyst frequency (Pandas convention)
Returns
-------
str
"""
freq_match = re.match(r'([0-9].*)?(m|M|d|D|h|H|T)', freq, re.M | re.I)
if freq_match:
candle_size = int(freq_match.group(1)) \
if freq_match.group(1) else 1
unit = freq_match.group(2)
else:
raise InvalidHistoryFrequencyError(frequency=freq)
if unit.lower() == 'd':
timeframe = '{}d'.format(candle_size)
elif unit.lower() == 'm' or unit == 'T':
timeframe = '{}m'.format(candle_size)
elif unit.lower() == 'h' or unit == 'T':
timeframe = '{}h'.format(candle_size)
return timeframe
def get_candles(self, freq, assets, bar_count=None, start_dt=None,
end_dt=None):
symbols = self.get_symbols(assets)
timeframe = self.get_timeframe(freq)
delta = start_dt - pd.to_datetime('1970-1-1', utc=True)
ms = int(delta.total_seconds()) * 1000
candles = dict()
for asset in assets:
ohlcvs = self.api.fetch_ohlcv(
symbol=symbols[0],
timeframe=timeframe,
since=ms,
limit=bar_count,
params={}
)
candles[asset] = []
for ohlcv in ohlcvs:
candles[asset].append(dict(
last_traded=pd.to_datetime(ohlcv[0], unit='ms', utc=True),
open=ohlcv[1],
high=ohlcv[2],
low=ohlcv[3],
close=ohlcv[4],
volume=ohlcv[5]
))
return candles
def _fetch_symbol_map(self, is_local):
try:
return self.fetch_symbol_map(is_local)
except ExchangeSymbolsNotFound:
return None
def get_asset_defs(self, market):
"""
The local and Catalyst definitions of the specified market.
Parameters
----------
market: dict[str, Object]
The CCXT market dicts.
Returns
-------
dict[str, Object]
The asset definition.
"""
asset_defs = []
for is_local in (False, True):
asset_def = self.get_asset_def(market, is_local)
asset_defs.append((asset_def, is_local))
return asset_defs
def get_asset_def(self, market, is_local=False):
"""
The asset definition (in symbols.json files) corresponding
to the the specified market.
Parameters
----------
market: dict[str, Object]
The CCXT market dict.
is_local
Whether to search in local or Catalyst asset definitions.
Returns
-------
dict[str, Object]
The asset definition.
"""
exchange_symbol = market['id']
symbol_map = self._fetch_symbol_map(is_local)
if symbol_map is not None:
assets_lower = {k.lower(): v for k, v in symbol_map.items()}
key = exchange_symbol.lower()
asset = assets_lower[key] if key in assets_lower else None
if asset is not None:
return asset
else:
return None
else:
return None
def create_trading_pair(self, market, asset_def, is_local):
"""
Creating a TradingPair from market and asset data.
Parameters
----------
market: dict[str, Object]
asset_def: dict[str, Object]
is_local: bool
Returns
-------
"""
data_source = 'local' if is_local else 'catalyst'
params = dict(
exchange=self.name,
data_source=data_source,
exchange_symbol=market['id'],
)
mixin_market_params(self.name, params, market)
if asset_def is not None:
params['symbol'] = asset_def['symbol']
params['start_date'] = asset_def['start_date'] \
if 'start_date' in asset_def else None
params['end_date'] = asset_def['end_date'] \
if 'end_date' in asset_def else None
params['leverage'] = asset_def['leverage'] \
if 'leverage' in asset_def else 1.0
params['asset_name'] = asset_def['asset_name'] \
if 'asset_name' in asset_def else None
params['end_daily'] = asset_def['end_daily'] \
if 'end_daily' in asset_def \
and asset_def['end_daily'] != 'N/A' else None
params['end_minute'] = asset_def['end_minute'] \
if 'end_minute' in asset_def \
and asset_def['end_minute'] != 'N/A' else None
else:
params['symbol'] = self.get_catalyst_symbol(market)
# TODO: add as an optional column
params['leverage'] = 1.0
return TradingPair(**params)
def load_assets(self):
self.assets = []
for market in self.markets:
asset_defs = self.get_asset_defs(market)
for asset_def in asset_defs:
if asset_def[0] is not None or not asset_defs[1]:
try:
asset = self.create_trading_pair(
market=market,
asset_def=asset_def[0],
is_local=asset_def[1]
)
self.assets.append(asset)
except TypeError:
pass
def get_balances(self):
try:
log.debug('retrieving wallets balances')
balances = self.api.fetch_balance()
balances_lower = dict()
for key in balances:
balances_lower[key.lower()] = balances[key]
except Exception as e:
log.debug('error retrieving balances: {}', e)
raise ExchangeRequestError(error=e)
return balances_lower
def _create_order(self, order_status):
"""
Create a Catalyst order object from a CCXT order dictionary
Parameters
----------
order_status: dict[str, Object]
The order dict from the CCXT api.
Returns
-------
Order
The Catalyst order object
"""
if order_status['status'] == 'canceled':
status = ORDER_STATUS.CANCELLED
elif order_status['status'] == 'closed' and order_status['filled'] > 0:
log.debug('found executed order {}'.format(order_status))
status = ORDER_STATUS.FILLED
elif order_status['status'] == 'open':
status = ORDER_STATUS.OPEN
else:
raise ValueError('invalid state for order')
amount = order_status['amount']
filled = order_status['filled']
if order_status['side'] == 'sell':
amount = -amount
filled = -filled
price = order_status['price']
order_type = order_status['type']
limit_price = price if order_type == 'limit' else None
stop_price = None # TODO: add support
executed_price = order_status['cost'] / order_status['amount']
commission = order_status['fee']
date = from_ms_timestamp(order_status['timestamp'])
# order_id = str(order_status['info']['clientOrderId'])
order_id = order_status['id']
# TODO: this won't work, redo the packages with a different key.
symbol = order_status['info']['symbol'] \
if 'symbol' in order_status['info'] \
else order_status['info']['Exchange']
order = Order(
dt=date,
asset=self.get_asset(symbol, is_exchange_symbol=True),
amount=amount,
stop=stop_price,
limit=limit_price,
filled=filled,
id=order_id,
commission=commission
)
order.status = status
return order, executed_price
def create_order(self, asset, amount, is_buy, style):
symbol = self.get_symbol(asset)
if isinstance(style, ExchangeLimitOrder):
price = style.get_limit_price(is_buy)
order_type = 'limit'
elif isinstance(style, MarketOrder):
price = None
order_type = 'market'
else:
raise InvalidOrderStyle(
exchange=self.name,
style=style.__class__.__name__
)
side = 'buy' if amount > 0 else 'sell'
try:
result = self.api.create_order(
symbol=symbol,
type=order_type,
side=side,
amount=abs(amount),
price=price
)
except ExchangeNotAvailable as e:
log.debug('unable to create order: {}'.format(e))
raise ExchangeRequestError(error=e)
if 'info' not in result:
raise ValueError('cannot use order without info attribute')
order_id = result['id']
order = Order(
dt=pd.Timestamp.utcnow(),
asset=asset,
amount=amount,
stop=style.get_stop_price(is_buy),
limit=style.get_limit_price(is_buy),
id=order_id
)
return order
def get_open_orders(self, asset):
try:
symbol = self.get_symbol(asset)
result = self.api.fetch_open_orders(
symbol=symbol,
since=None,
limit=None,
params=dict()
)
except Exception as e:
raise ExchangeRequestError(error=e)
orders = []
for order_status in result:
order, executed_price = self._create_order(order_status)
if asset is None or asset == order.sid:
orders.append(order)
return orders
def _get_asset_from_order(self, order_id):
open_orders = self.portfolio.open_orders
order = next(
(open_orders[id] for id in open_orders if id == order_id),
None
) # type: Order
return order.asset if order is not None else None
def get_order(self, order_id, asset_or_symbol=None):
if asset_or_symbol is None and self.portfolio is not None:
asset_or_symbol = self._get_asset_from_order(order_id)
if asset_or_symbol is None:
log.debug(
'order not found in memory, the request might fail '
'on some exchanges.'
)
try:
symbol = self.get_symbol(asset_or_symbol) \
if asset_or_symbol is not None else None
order_status = self.api.fetch_order(id=order_id, symbol=symbol)
order, executed_price = self._create_order(order_status)
except Exception as e:
raise ExchangeRequestError(error=e)
return order, executed_price
def cancel_order(self, order_param, asset_or_symbol=None):
order_id = order_param.id \
if isinstance(order_param, Order) else order_param
if asset_or_symbol is None and self.portfolio is not None:
asset_or_symbol = self._get_asset_from_order(order_id)
if asset_or_symbol is None:
log.debug(
'order not found in memory, cancelling order might fail '
'on some exchanges.'
)
try:
symbol = self.get_symbol(asset_or_symbol) \
if asset_or_symbol is not None else None
self.api.cancel_order(id=order_id, symbol=symbol)
except Exception as e:
raise ExchangeRequestError(error=e)
def tickers(self, assets):
"""
Retrieve current tick data for the given assets
Parameters
----------
assets: list[TradingPair]
Returns
-------
list[dict[str, float]
"""
tickers = dict()
for asset in assets:
ccxt_symbol = self.get_symbol(asset)
ticker = self.api.fetch_ticker(ccxt_symbol)
ticker['last_traded'] = from_ms_timestamp(ticker['timestamp'])
if 'last_price' not in ticker:
# TODO: any more exceptions?
ticker['last_price'] = ticker['last']
# Using the volume represented in the base currency
ticker['volume'] = ticker['baseVolume'] \
if 'baseVolume' in ticker else 0
tickers[asset] = ticker
return tickers
def get_account(self):
return None
def get_orderbook(self, asset, order_type='all', limit=None):
ccxt_symbol = self.get_symbol(asset)
params = dict()
if limit is not None:
params['depth'] = limit
order_book = self.api.fetch_order_book(ccxt_symbol, params)
order_types = ['bids', 'asks'] if order_type == 'all' else [order_type]
result = dict(last_traded=from_ms_timestamp(order_book['timestamp']))
for index, order_type in enumerate(order_types):
if limit is not None and index > limit - 1:
break
result[order_type] = []
for entry in order_book[order_type]:
result[order_type].append(dict(
rate=float(entry[0]),
quantity=float(entry[1])
))
return result
+118 -123
View File
@@ -8,15 +8,16 @@ import pandas as pd
from catalyst.assets._assets import TradingPair
from logbook import Logger
from catalyst.algorithm import MarketOrder
from catalyst.constants import LOG_LEVEL
from catalyst.data.data_portal import BASE_FIELDS
from catalyst.exchange.bundle_utils import get_start_dt, \
get_delta, get_periods, get_periods_range
from catalyst.exchange.exchange_bundle import ExchangeBundle
from catalyst.exchange.exchange_errors import MismatchingBaseCurrencies, \
InvalidOrderStyle, BaseCurrencyNotFoundError, SymbolNotFoundOnExchange, \
BaseCurrencyNotFoundError, SymbolNotFoundOnExchange, \
PricingDataNotLoadedError, \
NoDataAvailableOnExchange, ExchangeSymbolsNotFound
NoDataAvailableOnExchange, NoValueForField
from catalyst.exchange.exchange_execution import ExchangeStopLimitOrder, \
ExchangeLimitOrder, ExchangeStopOrder
from catalyst.exchange.exchange_portfolio import ExchangePortfolio
@@ -33,8 +34,8 @@ class Exchange:
def __init__(self):
self.name = None
self.assets = dict()
self.local_assets = dict()
self.assets = []
self._symbol_maps = [None, None]
self._portfolio = None
self.minute_writer = None
self.minute_reader = None
@@ -145,9 +146,9 @@ class Exchange:
"""
symbol = None
for key in self.assets:
if not symbol and self.assets[key].symbol == asset.symbol:
symbol = key
for a in self.assets:
if not symbol and a.symbol == asset.symbol:
symbol = a.symbol
if not symbol:
raise ValueError('Currency %s not supported by exchange %s' %
@@ -174,72 +175,103 @@ class Exchange:
return symbols
def get_assets(self, symbols=None, data_frequency=None):
def get_assets(self, symbols=None, data_frequency=None,
is_exchange_symbol=False,
is_local=None):
"""
The list of markets for the specified symbols.
Parameters
----------
symbols: list[str]
data_frequency: str
is_exchange_symbol: bool
is_local: bool
Returns
-------
list[TradingPair]
A list of asset objects.
Notes
-----
See get_asset for details of each parameter.
"""
if symbols is None:
# Make a distinct list of all symbols
symbols = list(set([asset.symbol for asset in self.assets]))
is_exchange_symbol = False
assets = []
if symbols is not None:
for symbol in symbols:
asset = self.get_asset(symbol, data_frequency)
assets.append(asset)
else:
for key in self.assets:
assets.append(self.assets[key])
for symbol in symbols:
asset = self.get_asset(
symbol, data_frequency, is_exchange_symbol, is_local
)
assets.append(asset)
return assets
def _find_asset(self, asset, symbol, data_frequency, is_local=False):
assets = self.assets if not is_local else self.local_assets
for key in assets:
has_data = (data_frequency == 'minute'
and assets[key].end_minute is not None) \
or (data_frequency == 'daily'
and assets[key].end_daily is not None)
if not asset and assets[key].symbol.lower() == symbol.lower() \
and (not data_frequency or has_data):
asset = assets[key]
return asset
def get_asset(self, symbol, data_frequency=None):
def get_asset(self, symbol, data_frequency=None, is_exchange_symbol=False,
is_local=None):
"""
The market for the specified symbol.
Parameters
----------
symbol: str
The Catalyst or exchange symbol.
data_frequency: str
Check for asset corresponding to the specified data_frequency.
The same asset might exist in the Catalyst repository or
locally (following a CSV ingestion). Filtering by
data_frequency picks the right asset.
is_exchange_symbol: bool
Whether the symbol uses the Catalyst or exchange convention.
is_local: bool
For the local or Catalyst asset.
Returns
-------
TradingPair
The asset object.
"""
asset = None
log.debug('searching asset {} on the server'.format(symbol))
asset = self._find_asset(asset, symbol, data_frequency, False)
log.debug(
'searching assets for: {} {}'.format(
self.name, symbol
)
)
for a in self.assets:
if asset is not None:
break
log.debug('asset {} not found on the server, searching local '
'assets'.format(symbol))
asset = self._find_asset(asset, symbol, data_frequency, True)
if is_local is not None:
data_source = 'local' if is_local else 'catalyst'
applies = (a.data_source == data_source)
if not asset:
all_values = list(self.assets.values()) + \
list(self.local_assets.values())
elif data_frequency is not None:
applies = (
(data_frequency == 'minute' and a.end_minute is not None)
or (data_frequency == 'daily' and a.end_daily is not None)
)
else:
applies = True
# The symbol provided may use the Catalyst or the exchange
# convention
key = a.exchange_symbol if is_exchange_symbol else a.symbol
if not asset and key.lower() == symbol.lower() and applies:
asset = a
if asset is None:
supported_symbols = sorted([
asset.symbol for asset in all_values
asset.symbol for asset in self.assets
])
raise SymbolNotFoundOnExchange(
@@ -248,11 +280,20 @@ class Exchange:
supported_symbols=supported_symbols
)
log.debug('found asset: {}'.format(asset))
return asset
def fetch_symbol_map(self, is_local=False):
return get_exchange_symbols(self.name, is_local)
index = 1 if is_local else 0
if self._symbol_maps[index] is not None:
return self._symbol_maps[index]
else:
symbol_map = get_exchange_symbols(self.name, is_local)
self._symbol_maps[index] = symbol_map
return symbol_map
@abstractmethod
def load_assets(self, is_local=False):
"""
Populate the 'assets' attribute with a dictionary of Assets.
@@ -270,66 +311,7 @@ class Exchange:
via its api.
"""
try:
symbol_map = self.fetch_symbol_map(is_local)
except ExchangeSymbolsNotFound:
return None
for exchange_symbol in symbol_map:
asset = symbol_map[exchange_symbol]
if 'start_date' in asset:
start_date = pd.to_datetime(asset['start_date'], utc=True)
else:
start_date = None
if 'end_date' in asset:
end_date = pd.to_datetime(asset['end_date'], utc=True)
else:
end_date = None
if 'leverage' in asset:
leverage = asset['leverage']
else:
leverage = 1.0
if 'asset_name' in asset:
asset_name = asset['asset_name']
else:
asset_name = None
if 'min_trade_size' in asset:
min_trade_size = asset['min_trade_size']
else:
min_trade_size = 0.0000001
if 'end_daily' in asset and asset['end_daily'] != 'N/A':
end_daily = pd.to_datetime(asset['end_daily'], utc=True)
else:
end_daily = None
if 'end_minute' in asset and asset['end_minute'] != 'N/A':
end_minute = pd.to_datetime(asset['end_minute'], utc=True)
else:
end_minute = None
trading_pair = TradingPair(
symbol=asset['symbol'],
exchange=self.name,
start_date=start_date,
end_date=end_date,
leverage=leverage,
asset_name=asset_name,
min_trade_size=min_trade_size,
end_daily=end_daily,
end_minute=end_minute,
exchange_symbol=exchange_symbol
)
if is_local:
self.local_assets[exchange_symbol] = trading_pair
else:
self.assets[exchange_symbol] = trading_pair
pass
def check_open_orders(self):
"""
@@ -348,9 +330,11 @@ class Exchange:
log.debug('found open order: {}'.format(order_id))
order, executed_price = self.get_order(order_id)
log.debug('got updated order {} {}'.format(
order, executed_price))
log.debug(
'got updated order {} {}'.format(
order, executed_price
)
)
if order.status == ORDER_STATUS.FILLED:
transaction = Transaction(
asset=order.asset,
@@ -412,12 +396,15 @@ class Exchange:
if field not in BASE_FIELDS:
raise KeyError('Invalid column: {}'.format(field))
values = []
for asset in assets:
value = self.get_single_spot_value(asset, field, data_frequency)
values.append(value)
tickers = self.tickers(assets)
if field == 'close' or field == 'price':
return [tickers[asset]['last'] for asset in tickers]
return values
elif field == 'volume':
return [tickers[asset]['volume'] for asset in tickers]
else:
raise NoValueForField(field=field)
def get_single_spot_value(self, asset, field, data_frequency):
"""
@@ -691,7 +678,7 @@ class Exchange:
log.debug('synchronizing portfolio with exchange {}'.format(self.name))
balances = self.get_balances()
base_position_available = balances[self.base_currency] \
base_position_available = balances[self.base_currency]['free'] \
if self.base_currency in balances else None
if base_position_available is None:
@@ -716,8 +703,9 @@ class Exchange:
# TODO: convert if the position is not in the base currency
ticker = tickers[asset]
position = portfolio.positions[asset]
position.last_sale_price = ticker['last_price']
position.last_sale_date = ticker['timestamp']
position.last_sale_date = ticker['last_traded']
portfolio.positions_value += \
position.amount * position.last_sale_price
@@ -774,28 +762,30 @@ class Exchange:
log.warn('skipping order amount of 0')
return None
if asset.base_currency != self.base_currency.lower():
if self.base_currency is None:
raise ValueError('no base_currency defined for this exchange')
if asset.quote_currency != self.base_currency.lower():
raise MismatchingBaseCurrencies(
base_currency=asset.base_currency,
base_currency=asset.quote_currency,
algo_currency=self.base_currency
)
is_buy = (amount > 0)
if limit_price is not None and stop_price is not None:
style = ExchangeStopLimitOrder(limit_price, stop_price,
exchange=self.name)
style = ExchangeStopLimitOrder(
limit_price, stop_price, exchange=self.name
)
elif limit_price is not None:
style = ExchangeLimitOrder(limit_price, exchange=self.name)
elif stop_price is not None:
style = ExchangeStopOrder(stop_price, exchange=self.name)
elif style is not None:
raise InvalidOrderStyle(exchange=self.name.title(),
style=style.__class__.__name__)
else:
raise ValueError('Incomplete order data.')
style = MarketOrder(exchange=self.name)
display_price = limit_price if limit_price is not None else stop_price
log.debug(
@@ -804,9 +794,10 @@ class Exchange:
amount=amount,
symbol=asset.symbol,
type=style.__class__.__name__,
price='{}{}'.format(display_price, asset.base_currency)
price='{}{}'.format(display_price, asset.quote_currency)
)
)
order = self.create_order(asset, amount, is_buy, style)
if order:
self._portfolio.create_order(order)
@@ -875,7 +866,7 @@ class Exchange:
pass
@abstractmethod
def get_order(self, order_id):
def get_order(self, order_id, symbol_or_asset=None):
"""Lookup an order based on the order id returned from one of the
order functions.
@@ -883,6 +874,8 @@ class Exchange:
----------
order_id : str
The unique identifier for the order.
symbol_or_asset: str|TradingPair
The catalyst symbol, some exchanges need this
Returns
-------
@@ -894,13 +887,15 @@ class Exchange:
pass
@abstractmethod
def cancel_order(self, order_param):
def cancel_order(self, order_param, symbol_or_asset=None):
"""Cancel an open order.
Parameters
----------
order_param : str or Order
The order_id or order object to cancel.
symbol_or_asset: str|TradingPair
The catalyst symbol, some exchanges need this
"""
pass
+1
View File
@@ -289,6 +289,7 @@ class ExchangeTradingAlgorithmLive(ExchangeTradingAlgorithmBase):
def __init__(self, *args, **kwargs):
self.algo_namespace = kwargs.pop('algo_namespace', None)
self.live_graph = kwargs.pop('live_graph', None)
self.simulate_orders = kwargs.pop('simulate_orders', None)
self._clock = None
self.frame_stats = deque(maxlen=60)
+37 -35
View File
@@ -1,5 +1,4 @@
import os
import os
import shutil
from datetime import datetime, timedelta
from functools import partial
@@ -28,10 +27,9 @@ from catalyst.exchange.exchange_bcolz import BcolzExchangeBarReader, \
from catalyst.exchange.exchange_errors import EmptyValuesInBundleError, \
TempBundleNotFoundError, \
NoDataAvailableOnExchange, \
PricingDataNotLoadedError, DataCorruptionError, ExchangeSymbolsNotFound, \
PricingDataValueError
PricingDataNotLoadedError, DataCorruptionError, PricingDataValueError
from catalyst.exchange.exchange_utils import get_exchange_folder, \
get_exchange_symbols, save_exchange_symbols
save_exchange_symbols, mixin_market_params
from catalyst.utils.cli import maybe_show_progress
from catalyst.utils.paths import ensure_directory
@@ -667,12 +665,11 @@ class ExchangeBundle:
"""
log.info('ingesting csv file: {}'.format(path))
try:
symbols_def = get_exchange_symbols(
self.exchange_name, is_local=True
)
except ExchangeSymbolsNotFound:
symbols_def = dict()
if self.exchange is None:
# Avoid circular dependencies
from catalyst.exchange.factory import get_exchange
self.exchange = get_exchange(self.exchange_name)
problems = []
df = pd.read_csv(
@@ -705,24 +702,40 @@ class ExchangeBundle:
end_dt = df.index.get_level_values(1).max()
end_dt_key = 'end_{}'.format(data_frequency)
if symbol is symbols_def:
symbol_def = symbols_def[symbol]
market = self.exchange.get_market(symbol)
if market is None:
raise ValueError('symbol not available in the exchange.')
start_dt = symbol_def['start_date'] \
if symbol_def['start_date'] < start_dt else start_dt
params = dict(
exchange=self.exchange.name,
data_source='local',
exchange_symbol=market['id'],
)
mixin_market_params(self.exchange_name, params, market)
end_dt = symbol_def[end_dt_key] \
if symbol_def[end_dt_key] > end_dt else end_dt
asset_def = self.exchange.get_asset_def(market, True)
if asset_def is not None:
params['symbol'] = asset_def['symbol']
end_daily = end_dt \
if data_frequency == 'daily' else symbol_def['end_daily']
params['start_date'] = asset_def['start_date'] \
if asset_def['start_date'] < start_dt else start_dt
end_minute = end_dt \
if data_frequency == 'minute' else symbol_def['end_minute']
params['end_date'] = asset_def[end_dt_key] \
if asset_def[end_dt_key] > end_dt else end_dt
params['end_daily'] = end_dt \
if data_frequency == 'daily' else asset_def['end_daily']
params['end_minute'] = end_dt \
if data_frequency == 'minute' else asset_def['end_minute']
else:
end_daily = end_dt if data_frequency == 'daily' else 'N/A'
end_minute = end_dt if data_frequency == 'minute' else 'N/A'
params['symbol'] = self.exchange.get_catalyst_symbol(market)
params['end_daily'] = end_dt \
if data_frequency == 'daily' else 'N/A'
params['end_minute'] = end_dt \
if data_frequency == 'minute' else 'N/A'
if min_start_dt is None or start_dt < min_start_dt:
min_start_dt = start_dt
@@ -730,19 +743,8 @@ class ExchangeBundle:
if max_end_dt is None or end_dt > max_end_dt:
max_end_dt = end_dt
asset = TradingPair(
symbol=symbol,
exchange=self.exchange_name,
start_date=start_dt,
end_date=end_dt,
leverage=0, # TODO: add as an optional column
asset_name=symbol,
min_trade_size=0, # TODO: add as an optional column
end_daily=end_daily,
end_minute=end_minute,
exchange_symbol=symbol
)
assets[symbol] = asset
asset = TradingPair(**params)
assets[market['id']] = asset
save_exchange_symbols(self.exchange_name, assets, True)
+4
View File
@@ -240,3 +240,7 @@ class NoDataAvailableOnExchange(ZiplineError):
'Requested data for trading pair {symbol} is not available on exchange {exchange} '
'in `{data_frequency}` frequency at this time. '
'Check `http://enigma.co/catalyst/status` for market coverage.').strip()
class NoValueForField(ZiplineError):
msg = ('Value not found for field: {field}.').strip()
+1 -1
View File
@@ -1,4 +1,4 @@
from catalyst.finance.execution import LimitOrder, StopOrder, StopLimitOrder
from catalyst.finance.execution import LimitOrder, StopOrder, StopLimitOrder, MarketOrder
class ExchangeLimitOrder(LimitOrder):
+2 -28
View File
@@ -3,7 +3,6 @@ from logbook import Logger
from catalyst.constants import LOG_LEVEL
from catalyst.protocol import Portfolio, Positions, Position
from catalyst.utils.deprecate import deprecated
log = Logger('ExchangePortfolio', level=LOG_LEVEL)
@@ -11,7 +10,8 @@ log = Logger('ExchangePortfolio', level=LOG_LEVEL)
class ExchangePortfolio(Portfolio):
"""
Since the goal is to support multiple exchanges, it makes sense to
include additional stats in the portfolio object.
include additional stats in the portfolio object. This fills the role
of Blotter and Portfolio in live mode.
Instead of relying on the performance tracker, each exchange portfolio
tracks its own holding. This offers a separation between tracking an
@@ -89,32 +89,6 @@ class ExchangePortfolio(Portfolio):
log.debug('updated portfolio with executed order')
@deprecated
def execute_transaction(self, transaction):
# TODO: almost duplicate of execute_order. Not sure why Poloniex needs this.
log.debug('executing transaction {}'.format(transaction.order_id))
order_position = self.positions[transaction.asset] \
if transaction.asset in self.positions else None
if order_position is None:
raise ValueError(
'Trying to execute transaction for a position not held: %s' % transaction.order_id
)
self.capital_used += transaction.amount * transaction.price
if transaction.amount > 0:
if order_position.cost_basis > 0:
order_position.cost_basis = np.average(
[order_position.cost_basis, transaction.price],
weights=[order_position.amount, transaction.amount]
)
else:
order_position.cost_basis = transaction.price
log.debug('updated portfolio with executed order')
def remove_order(self, order):
"""
Removing an open order.
+58 -2
View File
@@ -8,6 +8,7 @@ from datetime import date, datetime
import pandas as pd
from catalyst.assets._assets import TradingPair
from six import string_types
from six.moves.urllib import request
from catalyst.constants import DATE_FORMAT, SYMBOLS_URL
@@ -100,6 +101,20 @@ def download_exchange_symbols(exchange_name, environ=None):
return response
def symbols_parser(asset_def):
for key, value in asset_def.items():
match = isinstance(value, string_types) \
and re.search(r'(\d{4}-\d{2}-\d{2})', value)
if match:
try:
asset_def[key] = pd.to_datetime(value, utc=True)
except ValueError:
pass
return asset_def
def get_exchange_symbols(exchange_name, is_local=False, environ=None):
"""
The de-serialized content of the exchange's symbols.json.
@@ -125,10 +140,10 @@ def get_exchange_symbols(exchange_name, is_local=False, environ=None):
if os.path.isfile(filename):
with open(filename) as data_file:
try:
data = json.load(data_file)
data = json.load(data_file, object_hook=symbols_parser)
return data
except ValueError:
except ValueError as e:
return dict()
else:
raise ExchangeSymbolsNotFound(
@@ -571,3 +586,44 @@ def resample_history_df(df, freq, field):
resampled_df = df.resample(freq).agg(agg)
return resampled_df
def mixin_market_params(exchange_name, params, market):
"""
Applies a CCXT market dict to parameters of TradingPair init.
Parameters
----------
params: dict[Object]
market: dict[Object]
Returns
-------
"""
# TODO: make this more externalized / configurable
if 'lot' in market:
params['min_trade_size'] = market['lot']
if exchange_name == 'bitfinex':
params['maker'] = 0.001
params['taker'] = 0.002
elif 'maker' in market and 'taker' in market \
and market['maker'] is not None and market['taker'] is not None:
params['maker'] = market['maker']
params['taker'] = market['taker']
else:
# TODO: default commission, make configurable
params['maker'] = 0.0015
params['taker'] = 0.0025
info = market['info'] if 'info' in market else None
if info:
if 'minimum_order_size' in info:
params['min_trade_size'] = float(info['minimum_order_size'])
def from_ms_timestamp(ms):
return pd.to_datetime(ms, unit='ms', utc=True)
+23 -30
View File
@@ -1,38 +1,31 @@
from catalyst.exchange.bitfinex.bitfinex import Bitfinex
from catalyst.exchange.bittrex.bittrex import Bittrex
from catalyst.exchange.exchange_errors import ExchangeNotFoundError
from catalyst.exchange.exchange_utils import get_exchange_auth
from catalyst.exchange.poloniex.poloniex import Poloniex
import os
from catalyst.exchange.ccxt.ccxt_exchange import CCXT
from catalyst.exchange.exchange_errors import ExchangeAuthEmpty
from catalyst.exchange.exchange_utils import get_exchange_auth, \
get_exchange_folder
def get_exchange(exchange_name, base_currency=None):
def get_exchange(exchange_name, base_currency=None, portfolio=None,
must_authenticate=False):
exchange_auth = get_exchange_auth(exchange_name)
if exchange_name == 'bitfinex':
return Bitfinex(
key=exchange_auth['key'],
secret=exchange_auth['secret'],
base_currency=base_currency,
portfolio=None
has_auth = (exchange_auth['key'] != '' and exchange_auth['secret'] != '')
if must_authenticate and not has_auth:
raise ExchangeAuthEmpty(
exchange=exchange_name.title(),
filename=os.path.join(
get_exchange_folder(exchange_name), 'auth.json'
)
)
elif exchange_name == 'bittrex':
return Bittrex(
key=exchange_auth['key'],
secret=exchange_auth['secret'],
base_currency=base_currency,
portfolio=None
)
elif exchange_name == 'poloniex':
return Poloniex(
key=exchange_auth['key'],
secret=exchange_auth['secret'],
base_currency=base_currency,
portfolio=None
)
else:
raise ExchangeNotFoundError(exchange_name=exchange_name)
return CCXT(
exchange_name=exchange_name,
key=exchange_auth['key'],
secret=exchange_auth['secret'],
base_currency=base_currency,
portfolio=portfolio
)
def get_exchanges(exchange_names):
+3 -3
View File
@@ -153,11 +153,11 @@ def get_pretty_stats(stats_df, recorded_cols=None, num_rows=10):
def format_positions(positions):
parts = []
for position in positions:
msg = '{amount:.2f}{market} cost basis {cost_basis:.4f}{base}'.format(
msg = '{amount:.2f}{base} cost basis {cost_basis:.4f}{quote}'.format(
amount=position['amount'],
market=position['sid'].market_currency,
base=position['sid'].base_currency,
cost_basis=position['cost_basis'],
base=position['sid'].base_currency
quote=position['sid'].quote_currency
)
parts.append(msg)
return ', '.join(parts)
+1 -1
View File
@@ -55,4 +55,4 @@ from .core import ( # noqa
write_bcolz_minute_data,
write_compressed,
)
from .fixtures import ZiplineTestCase # noqa
from .fixtures import CatalystTestCase # noqa
+1 -1
View File
@@ -643,7 +643,7 @@ def create_data_portal_from_trade_history(asset_finder, trading_calendar,
return DataPortal(
asset_finder, trading_calendar,
first_trading_day=equity_daily_reader.first_trading_day,
equity_daily_reader=equity_daily_reader,
daily_reader=equity_daily_reader,
)
else:
minutes = trading_calendar.minutes_in_range(
+28 -28
View File
@@ -62,7 +62,7 @@ from catalyst.utils.paths import ensure_directory
catalyst_dir = os.path.dirname(catalyst.__file__)
class ZiplineTestCase(with_metaclass(FinalMeta, TestCase)):
class CatalystTestCase(with_metaclass(FinalMeta, TestCase)):
"""
Shared extensions to core unittest.TestCase.
@@ -92,7 +92,7 @@ class ZiplineTestCase(with_metaclass(FinalMeta, TestCase)):
cls._base_init_fixtures_was_called = False
cls.init_class_fixtures()
assert cls._base_init_fixtures_was_called, (
"ZiplineTestCase.init_class_fixtures() was not called.\n"
"CatalystTestCase.init_class_fixtures() was not called.\n"
"This probably means that you overrode init_class_fixtures"
" without calling super()."
)
@@ -170,7 +170,7 @@ class ZiplineTestCase(with_metaclass(FinalMeta, TestCase)):
self._init_instance_fixtures_was_called = False
self.init_instance_fixtures()
assert self._init_instance_fixtures_was_called, (
"ZiplineTestCase.init_instance_fixtures() was not"
"CatalystTestCase.init_instance_fixtures() was not"
" called.\n"
"This probably means that you overrode"
" init_instance_fixtures without calling super()."
@@ -251,7 +251,7 @@ def alias(attr_name):
class WithDefaultDateBounds(object):
"""
ZiplineTestCase mixin which makes it possible to synchronize date bounds
CatalystTestCase mixin which makes it possible to synchronize date bounds
across fixtures.
This fixture should always be the last fixture in bases of any fixture or
@@ -264,13 +264,13 @@ class WithDefaultDateBounds(object):
The date bounds to be used for fixtures that want to have consistent
dates.
"""
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-12-29', tz='utc')
START_DATE = pd.Timestamp('2016-01-03', tz='utc')
END_DATE = pd.Timestamp('2016-12-29', tz='utc')
class WithLogger(object):
"""
ZiplineTestCase mixin providing cls.log_handler as an instance-level
CatalystTestCase mixin providing cls.log_handler as an instance-level
fixture.
After init_instance_fixtures has been called `self.log_handler` will be a
@@ -295,7 +295,7 @@ class WithLogger(object):
class WithAssetFinder(WithDefaultDateBounds):
"""
ZiplineTestCase mixin providing cls.asset_finder as a class-level fixture.
CatalystTestCase mixin providing cls.asset_finder as a class-level fixture.
After init_class_fixtures has been called, `cls.asset_finder` is populated
with an AssetFinder.
@@ -402,7 +402,7 @@ class WithAssetFinder(WithDefaultDateBounds):
class WithTradingCalendars(object):
"""
ZiplineTestCase mixin providing cls.trading_calendar,
CatalystTestCase mixin providing cls.trading_calendar,
cls.all_trading_calendars, cls.trading_calendar_for_asset_type as a
class-level fixture.
@@ -423,7 +423,7 @@ class WithTradingCalendars(object):
with that asset type.
"""
TRADING_CALENDAR_STRS = ('NYSE',)
TRADING_CALENDAR_FOR_ASSET_TYPE = {Equity: 'NYSE', Future: 'us_futures'}
TRADING_CALENDAR_FOR_ASSET_TYPE = {Equity: 'NYSE', Future: 'us_futures', }
TRADING_CALENDAR_FOR_EXCHANGE = {}
# For backwards compatibility, exisitng tests and fixtures refer to
# `trading_calendar` with the assumption that the value is the NYSE
@@ -460,7 +460,7 @@ class WithTradingEnvironment(WithAssetFinder,
WithTradingCalendars,
WithDefaultDateBounds):
"""
ZiplineTestCase mixin providing cls.env as a class-level fixture.
CatalystTestCase mixin providing cls.env as a class-level fixture.
After ``init_class_fixtures`` has been called, `cls.env` is populated
with a trading environment whose `asset_finder` is the result of
@@ -560,7 +560,7 @@ class WithTradingEnvironment(WithAssetFinder,
class WithSimParams(WithTradingEnvironment):
"""
ZiplineTestCase mixin providing cls.sim_params as a class level fixture.
CatalystTestCase mixin providing cls.sim_params as a class level fixture.
The arguments used to construct the trading environment may be overridded
by putting ``SIM_PARAMS_{argname}`` in the class dict except for the
@@ -615,7 +615,7 @@ class WithSimParams(WithTradingEnvironment):
class WithTradingSessions(WithTradingCalendars, WithDefaultDateBounds):
"""
ZiplineTestCase mixin providing cls.trading_days, cls.all_trading_sessions
CatalystTestCase mixin providing cls.trading_days, cls.all_trading_sessions
as a class-level fixture.
After init_class_fixtures has been called, `cls.all_trading_sessions`
@@ -668,7 +668,7 @@ class WithTradingSessions(WithTradingCalendars, WithDefaultDateBounds):
class WithTmpDir(object):
"""
ZiplineTestCase mixing providing cls.tmpdir as a class-level fixture.
CatalystTestCase mixing providing cls.tmpdir as a class-level fixture.
After init_class_fixtures has been called, `cls.tmpdir` is populated with
a `testfixtures.TempDirectory` object whose path is `cls.TMP_DIR_PATH`.
@@ -691,7 +691,7 @@ class WithTmpDir(object):
class WithInstanceTmpDir(object):
"""
ZiplineTestCase mixing providing self.tmpdir as an instance-level fixture.
CatalystTestCase mixing providing self.tmpdir as an instance-level fixture.
After init_instance_fixtures has been called, `self.tmpdir` is populated
with a `testfixtures.TempDirectory` object whose path is
@@ -714,7 +714,7 @@ class WithInstanceTmpDir(object):
class WithEquityDailyBarData(WithTradingEnvironment):
"""
ZiplineTestCase mixin providing cls.make_equity_daily_bar_data.
CatalystTestCase mixin providing cls.make_equity_daily_bar_data.
Attributes
----------
@@ -810,7 +810,7 @@ class WithEquityDailyBarData(WithTradingEnvironment):
class WithBcolzEquityDailyBarReader(WithEquityDailyBarData, WithTmpDir):
"""
ZiplineTestCase mixin providing cls.bcolz_daily_bar_path,
CatalystTestCase mixin providing cls.bcolz_daily_bar_path,
cls.bcolz_daily_bar_ctable, and cls.bcolz_equity_daily_bar_reader
class level fixtures.
@@ -895,7 +895,7 @@ class WithBcolzEquityDailyBarReader(WithEquityDailyBarData, WithTmpDir):
class WithBcolzEquityDailyBarReaderFromCSVs(WithBcolzEquityDailyBarReader):
"""
ZiplineTestCase mixin that provides
CatalystTestCase mixin that provides
cls.bcolz_equity_daily_bar_reader from a mapping of sids to CSV
file paths.
"""
@@ -925,7 +925,7 @@ class _WithMinuteBarDataBase(WithTradingEnvironment):
class WithEquityMinuteBarData(_WithMinuteBarDataBase):
"""
ZiplineTestCase mixin providing cls.equity_minute_bar_days.
CatalystTestCase mixin providing cls.equity_minute_bar_days.
After init_class_fixtures has been called:
- `cls.equity_minute_bar_days` has the range over which data has been
@@ -984,7 +984,7 @@ class WithEquityMinuteBarData(_WithMinuteBarDataBase):
class WithFutureMinuteBarData(_WithMinuteBarDataBase):
"""
ZiplineTestCase mixin providing cls.future_minute_bar_days.
CatalystTestCase mixin providing cls.future_minute_bar_days.
After init_class_fixtures has been called:
- `cls.future_minute_bar_days` has the range over which data has been
@@ -1044,7 +1044,7 @@ class WithFutureMinuteBarData(_WithMinuteBarDataBase):
class WithBcolzEquityMinuteBarReader(WithEquityMinuteBarData, WithTmpDir):
"""
ZiplineTestCase mixin providing cls.bcolz_minute_bar_path,
CatalystTestCase mixin providing cls.bcolz_minute_bar_path,
cls.bcolz_minute_bar_ctable, and cls.bcolz_equity_minute_bar_reader
class level fixtures.
@@ -1103,7 +1103,7 @@ class WithBcolzEquityMinuteBarReader(WithEquityMinuteBarData, WithTmpDir):
class WithBcolzFutureMinuteBarReader(WithFutureMinuteBarData, WithTmpDir):
"""
ZiplineTestCase mixin providing cls.bcolz_minute_bar_path,
CatalystTestCase mixin providing cls.bcolz_minute_bar_path,
cls.bcolz_minute_bar_ctable, and cls.bcolz_equity_minute_bar_reader
class level fixtures.
@@ -1227,7 +1227,7 @@ class WithConstantFutureMinuteBarData(WithFutureMinuteBarData):
class WithAdjustmentReader(WithBcolzEquityDailyBarReader):
"""
ZiplineTestCase mixin providing cls.adjustment_reader as a class level
CatalystTestCase mixin providing cls.adjustment_reader as a class level
fixture.
After init_class_fixtures has been called, `cls.adjustment_reader` will be
@@ -1359,7 +1359,7 @@ class WithEquityPricingPipelineEngine(WithAdjustmentReader,
class WithSeededRandomPipelineEngine(WithTradingSessions, WithAssetFinder):
"""
ZiplineTestCase mixin providing class-level fixtures for running pipelines
CatalystTestCase mixin providing class-level fixtures for running pipelines
against deterministically-generated random data.
Attributes
@@ -1434,7 +1434,7 @@ class WithDataPortal(WithAdjustmentReader,
WithBcolzEquityMinuteBarReader,
WithBcolzFutureMinuteBarReader):
"""
ZiplineTestCase mixin providing self.data_portal as an instance level
CatalystTestCase mixin providing self.data_portal as an instance level
fixture.
After init_instance_fixtures has been called, `self.data_portal` will be
@@ -1485,12 +1485,12 @@ class WithDataPortal(WithAdjustmentReader,
self.env.asset_finder,
self.trading_calendar,
first_trading_day=self.DATA_PORTAL_FIRST_TRADING_DAY,
equity_daily_reader=(
daily_reader=(
self.bcolz_equity_daily_bar_reader
if self.DATA_PORTAL_USE_DAILY_DATA else
None
),
equity_minute_reader=(
minute_reader=(
self.bcolz_equity_minute_bar_reader
if self.DATA_PORTAL_USE_MINUTE_DATA else
None
@@ -1526,7 +1526,7 @@ class WithDataPortal(WithAdjustmentReader,
class WithResponses(object):
"""
ZiplineTestCase mixin that provides self.responses as an instance
CatalystTestCase mixin that provides self.responses as an instance
fixture.
After init_instance_fixtures has been called, `self.responses` will be
+1 -1
View File
@@ -37,7 +37,7 @@ from catalyst.utils.input_validation import expect_types
__all__ = ['load_from_yahoo', 'load_bars_from_yahoo']
def create_simulation_parameters(year=2006, start=None, end=None,
def create_simulation_parameters(year=2016, start=None, end=None,
capital_base=float("1.0e5"),
num_days=None,
data_frequency='daily',
+19 -46
View File
@@ -11,9 +11,7 @@ import pandas as pd
from catalyst.data.bundles import load
from catalyst.data.data_portal import DataPortal
from catalyst.exchange.bittrex.bittrex import Bittrex
from catalyst.exchange.bitfinex.bitfinex import Bitfinex
from catalyst.exchange.poloniex.poloniex import Poloniex
from catalyst.exchange.factory import get_exchange
try:
from pygments import highlight
@@ -39,11 +37,9 @@ from catalyst.exchange.exchange_data_portal import DataPortalExchangeLive, \
from catalyst.exchange.asset_finder_exchange import AssetFinderExchange
from catalyst.exchange.exchange_portfolio import ExchangePortfolio
from catalyst.exchange.exchange_errors import (
ExchangeRequestError, ExchangeAuthEmpty,
ExchangeRequestErrorTooManyAttempts,
BaseCurrencyNotFoundError, ExchangeNotFoundError)
from catalyst.exchange.exchange_utils import get_exchange_auth, \
get_algo_object, get_exchange_folder
ExchangeRequestError, ExchangeRequestErrorTooManyAttempts,
BaseCurrencyNotFoundError)
from catalyst.exchange.exchange_utils import get_algo_object
from logbook import Logger
from catalyst.constants import LOG_LEVEL
@@ -94,7 +90,8 @@ def _run(handle_data,
exchange,
algo_namespace,
base_currency,
live_graph):
live_graph,
simulate_orders):
"""Run a backtest for the given algorithm.
This is shared between the cli and :func:`catalyst.run_algo`.
@@ -164,42 +161,15 @@ def _run(handle_data,
if portfolio is None:
portfolio = ExchangePortfolio(
start_date=pd.Timestamp.utcnow()
start if start is not None else pd.Timestamp.utcnow()
)
# This corresponds to the json file containing api token info
exchange_auth = get_exchange_auth(exchange_name)
if live and (exchange_auth['key'] == '' \
or exchange_auth['secret'] == ''):
raise ExchangeAuthEmpty(
exchange=exchange_name.title(),
filename=os.path.join(
get_exchange_folder(exchange_name, environ), 'auth.json'))
if exchange_name == 'bitfinex':
exchanges[exchange_name] = Bitfinex(
key=exchange_auth['key'],
secret=exchange_auth['secret'],
base_currency=base_currency,
portfolio=portfolio
)
elif exchange_name == 'bittrex':
exchanges[exchange_name] = Bittrex(
key=exchange_auth['key'],
secret=exchange_auth['secret'],
base_currency=base_currency,
portfolio=portfolio
)
elif exchange_name == 'poloniex':
exchanges[exchange_name] = Poloniex(
key=exchange_auth['key'],
secret=exchange_auth['secret'],
base_currency=base_currency,
portfolio=portfolio
)
else:
raise ExchangeNotFoundError(exchange_name=exchange_name)
exchanges[exchange_name] = get_exchange(
exchange_name=exchange_name,
base_currency=base_currency,
portfolio=portfolio,
must_authenticate=live,
)
open_calendar = get_calendar('OPEN')
@@ -263,7 +233,7 @@ def _run(handle_data,
)
if base_currency in balances:
base_currency_available = balances[base_currency]
base_currency_available = balances[base_currency]['free']
log.info(
'base currency available in the account: {} {}'.format(
base_currency_available, base_currency
@@ -308,7 +278,8 @@ def _run(handle_data,
ExchangeTradingAlgorithmLive,
exchanges=exchanges,
algo_namespace=algo_namespace,
live_graph=live_graph
live_graph=live_graph,
simulate_orders=simulate_orders
)
elif exchanges:
# Removed the existing Poloniex fork to keep things simple
@@ -470,6 +441,7 @@ def run_algorithm(initialize,
base_currency=None,
algo_namespace=None,
live_graph=False,
simulate_orders=True,
output=os.devnull):
"""Run a trading algorithm.
@@ -591,5 +563,6 @@ def run_algorithm(initialize,
exchange=exchange_name,
algo_namespace=algo_namespace,
base_currency=base_currency,
live_graph=live_graph
live_graph=live_graph,
simulate_orders=simulate_orders
)
+1
View File
@@ -546,6 +546,7 @@ only bought bitcoin every chance it got.
sudo apt install python-tk
.. _history:
Access to previous prices using ``history``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
File diff suppressed because it is too large Load Diff
+17 -1
View File
@@ -32,7 +32,9 @@ Where things don't:
Backtesting a Strategy
----------------------
This algorithm is based on a simple momentum strategy. When the cryptoasset
This is the first video of a two-part series on using Catalyst for algorithmic
trading. This video implements a simple momentum strategy based on
`mean reversion <example-algos.html#mean-reversion>`_: when the cryptoasset
goes up quickly, were going to buy; when it goes down quickly, were going to
sell. Hopefully, well ride the waves.
@@ -40,3 +42,17 @@ sell. Hopefully, well ride the waves.
<iframe width="560" height="315" src="https://www.youtube.com/embed/JOBRwst9jUY" frameborder="0" allowfullscreen></iframe>
|
|
Live Trading a Strategy
-----------------------
This is the second part of the two-part series on using Catalyst for algorithmic
trading. Having backtested `our strategy <example-algos.html#mean-reversion>`_
in the previous video, we now take it to trade live against the Bittrex exchange.
.. raw:: html
<iframe width="560" height="315" src="https://www.youtube.com/embed/NupiE-Xuglw" frameborder="0" allowfullscreen></iframe>
|
|
+1 -1
View File
@@ -105,7 +105,7 @@ None
Miscellaneous
~~~~~~~~~~~~~
* Adds :class:`~zipline.testing.fixtures.ZiplineTestCase` which provides hooks
* Adds :class:`~zipline.testing.fixtures.CatalystTestCase` which provides hooks
to consume test fixtures. Fixtures are things like:
:class:`~zipline.testing.fixtures.WithAssetFinder` which will make
``self.asset_finder`` available to your test with some mock data
+3
View File
@@ -80,3 +80,6 @@ empyrical==0.2.1
tables==3.3.0
#Catalyst dependencies
ccxt==1.10.251
+2 -2
View File
@@ -6,12 +6,12 @@ from catalyst.errors import (
CyclicCalendarAlias,
InvalidCalendarName,
)
from catalyst.testing import ZiplineTestCase
from catalyst.testing import CatalystTestCase
from catalyst.utils.calendars.calendar_utils import TradingCalendarDispatcher
from catalyst.utils.calendars.exchange_calendar_ice import ICEExchangeCalendar
class CalendarAliasTestCase(ZiplineTestCase):
class CalendarAliasTestCase(CatalystTestCase):
@classmethod
def init_class_fixtures(cls):
+2 -2
View File
@@ -22,7 +22,7 @@ from catalyst.testing import (
subtest,
str_to_seconds,
)
from catalyst.testing.fixtures import WithInstanceTmpDir, ZiplineTestCase, \
from catalyst.testing.fixtures import WithInstanceTmpDir, CatalystTestCase, \
WithDefaultDateBounds
from catalyst.testing.predicates import (
assert_equal,
@@ -45,7 +45,7 @@ _1_ns = pd.Timedelta(1, unit='ns')
class BundleCoreTestCase(WithInstanceTmpDir,
WithDefaultDateBounds,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2014-01-06', tz='utc')
END_DATE = pd.Timestamp('2014-01-10', tz='utc')
+2 -2
View File
@@ -17,14 +17,14 @@ from catalyst.testing import (
tmp_dir,
patch_read_csv,
)
from catalyst.testing.fixtures import ZiplineTestCase
from catalyst.testing.fixtures import CatalystTestCase
from catalyst.testing.predicates import (
assert_equal,
)
from catalyst.utils.functional import apply
class QuandlBundleTestCase(ZiplineTestCase):
class QuandlBundleTestCase(CatalystTestCase):
symbols = 'AAPL', 'BRK_A', 'MSFT', 'ZEN'
asset_start = pd.Timestamp('2014-01', tz='utc')
asset_end = pd.Timestamp('2015-01', tz='utc')
+2 -2
View File
@@ -10,12 +10,12 @@ from catalyst.data.bundles.core import _make_bundle_core
from catalyst.data.bundles import yahoo_equities
from catalyst.lib.adjustment import Float64Multiply
from catalyst.testing import test_resource_path, tmp_dir, read_compressed
from catalyst.testing.fixtures import WithResponses, ZiplineTestCase
from catalyst.testing.fixtures import WithResponses, CatalystTestCase
from catalyst.testing.predicates import assert_equal
from catalyst.utils.calendars import get_calendar
class YahooBundleTestCase(WithResponses, ZiplineTestCase):
class YahooBundleTestCase(WithResponses, CatalystTestCase):
symbols = 'AAPL', 'IBM', 'MSFT'
columns = 'open', 'high', 'low', 'close', 'volume'
asset_start = pd.Timestamp('2014-01-02', tz='utc')
+10 -3
View File
@@ -11,6 +11,12 @@
# 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.
'''
# ZIPLINE legacy test: Catalyst does not use DispatchBarReader, and thus
# this test suite is irrelevant, and is commented out in its entirety
from numpy import array, nan
from numpy.testing import assert_almost_equal
from pandas import DataFrame, Timestamp
@@ -31,7 +37,7 @@ from catalyst.testing.fixtures import (
WithBcolzEquityDailyBarReader,
WithBcolzFutureMinuteBarReader,
WithTradingSessions,
ZiplineTestCase,
CatalystTestCase,
)
OHLC = ['open', 'high', 'low', 'close']
@@ -40,7 +46,7 @@ OHLC = ['open', 'high', 'low', 'close']
class AssetDispatchSessionBarTestCase(WithBcolzEquityDailyBarReader,
WithBcolzFutureMinuteBarReader,
WithTradingSessions,
ZiplineTestCase):
CatalystTestCase):
TRADING_CALENDAR_STRS = ('us_futures', 'NYSE')
TRADING_CALENDAR_PRIMARY_CAL = 'us_futures'
@@ -169,7 +175,7 @@ class AssetDispatchSessionBarTestCase(WithBcolzEquityDailyBarReader,
class AssetDispatchMinuteBarTestCase(WithBcolzEquityMinuteBarReader,
WithBcolzFutureMinuteBarReader,
ZiplineTestCase):
CatalystTestCase):
TRADING_CALENDAR_STRS = ('us_futures', 'NYSE')
TRADING_CALENDAR_PRIMARY_CAL = 'us_futures'
@@ -330,3 +336,4 @@ class AssetDispatchMinuteBarTestCase(WithBcolzEquityMinuteBarReader,
for i, (sid, expected, msg) in enumerate(expected_per_sid):
for j, result in enumerate(results):
assert_almost_equal(result[:, i], expected[j], err_msg=msg)
'''
+32 -23
View File
@@ -38,8 +38,8 @@ from pandas import (
from catalyst.data.bar_reader import NoDataOnDate
from catalyst.data.minute_bars import (
BcolzMinuteBarMetadata,
BcolzMinuteBarWriter,
BcolzMinuteBarReader,
# BcolzMinuteBarWriter,
# BcolzMinuteBarReader,
BcolzMinuteOverlappingData,
US_EQUITIES_MINUTES_PER_DAY,
BcolzMinuteWriterColumnMismatch,
@@ -47,24 +47,29 @@ from catalyst.data.minute_bars import (
H5MinuteBarUpdateReader,
)
from catalyst.exchange.exchange_bcolz import (
BcolzExchangeBarWriter,
BcolzExchangeBarReader,
)
from catalyst.testing.fixtures import (
WithAssetFinder,
WithInstanceTmpDir,
WithTradingCalendars,
ZiplineTestCase,
CatalystTestCase,
)
# Calendar is set to cover several half days, to check a case where half
# days would be read out of order in cases of windows which spanned over
# multiple half days.
TEST_CALENDAR_START = Timestamp('2014-06-02', tz='UTC')
TEST_CALENDAR_STOP = Timestamp('2015-12-31', tz='UTC')
TEST_CALENDAR_START = Timestamp('2015-06-02', tz='UTC')
TEST_CALENDAR_STOP = Timestamp('2016-12-31', tz='UTC')
class BcolzMinuteBarTestCase(WithTradingCalendars,
WithAssetFinder,
WithInstanceTmpDir,
ZiplineTestCase):
CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = 1, 2
@@ -87,14 +92,14 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
self.dest = self.instance_tmpdir.getpath('minute_bars')
os.makedirs(self.dest)
self.writer = BcolzMinuteBarWriter(
self.dest,
self.trading_calendar,
TEST_CALENDAR_START,
TEST_CALENDAR_STOP,
US_EQUITIES_MINUTES_PER_DAY,
self.writer = BcolzExchangeBarWriter(
rootdir=self.dest,
calendar=self.trading_calendar,
start_session=TEST_CALENDAR_START,
end_session=TEST_CALENDAR_STOP,
data_frequency='minute',
)
self.reader = BcolzMinuteBarReader(self.dest)
self.reader = BcolzExchangeBarReader(self.dest)
def test_version(self):
metadata = self.reader._get_metadata()
@@ -152,7 +157,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
)
# Create a new writer with `ohlc_ratios_per_sid` defined.
writer_with_ratios = BcolzMinuteBarWriter(
writer_with_ratios = BcolzExchangeBarWriter(
self.dest,
self.trading_calendar,
TEST_CALENDAR_START,
@@ -161,7 +166,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
ohlc_ratios_per_sid={sid: 25},
)
writer_with_ratios.write_sid(sid, data)
reader = BcolzMinuteBarReader(self.dest)
reader = BcolzExchangeBarReader(self.dest)
open_price = reader.get_value(sid, minute, 'open')
self.assertEquals(10.0, open_price)
@@ -449,7 +454,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
# of appending new days will be writing to an existing directory.
cday = self.trading_calendar.schedule.index.freq
new_end_session = TEST_CALENDAR_STOP + cday
writer = BcolzMinuteBarWriter.open(self.dest, new_end_session)
writer = BcolzExchangeBarWriter.open(self.dest, new_end_session)
next_day_minute = dt + cday
new_data = DataFrame(
data=ohlcv,
@@ -457,7 +462,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
writer.write_sid(sid, new_data)
# Get a new reader to test updated calendar.
reader = BcolzMinuteBarReader(self.dest)
reader = BcolzExchangeBarReader(self.dest)
second_minute = dt + Timedelta(minutes=1)
@@ -802,7 +807,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
index=minutes)
self.writer.write_sid(sids[1], data_2)
reader = BcolzMinuteBarReader(self.dest)
reader = BcolzExchangeBarReader(self.dest)
columns = ['open', 'high', 'low', 'close', 'volume']
sids = [sids[0], sids[1]]
@@ -854,7 +859,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
index=minutes)
self.writer.write_sid(sids[1], data_2)
reader = BcolzMinuteBarReader(self.dest)
reader = BcolzExchangeBarReader(self.dest)
columns = ['open', 'high', 'low', 'close', 'volume']
sids = [sids[0], sids[1]]
@@ -877,6 +882,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
assert_almost_equal(data[sid].loc[minutes, col],
arrays[i][j][minute_locs])
'''
def test_adjust_non_trading_minutes(self):
start_day = Timestamp('2015-06-01', tz='UTC')
end_day = Timestamp('2015-06-02', tz='UTC')
@@ -922,7 +928,9 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
Timestamp('2015-06-02 20:01:00', tz='UTC'),
'open'
)
'''
'''
def test_adjust_non_trading_minutes_half_days(self):
# half day
start_day = Timestamp('2015-11-27', tz='UTC')
@@ -978,6 +986,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
Timestamp('2015-11-30 21:01:00', tz='UTC'),
'open'
)
'''
def test_set_sid_attrs(self):
"""Confirm that we can set the attributes of a sid's file correctly.
@@ -1023,13 +1032,13 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
# Open a new writer to cover `open` method, also truncating only
# applies to an existing directory.
writer = BcolzMinuteBarWriter.open(self.dest)
writer = BcolzExchangeBarWriter.open(self.dest)
# Truncate to first day with data.
writer.truncate(days[0])
# Refresh the reader since truncate update the metadata.
self.reader = BcolzMinuteBarReader(self.dest)
self.reader = BcolzExchangeBarReader(self.dest)
self.assertEqual(self.writer.last_date_in_output_for_sid(sid), days[0])
@@ -1087,7 +1096,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
self.writer.truncate(self.test_calendar_start)
# Refresh the reader since truncate update the metadata.
self.reader = BcolzMinuteBarReader(self.dest)
self.reader = BcolzExchangeBarReader(self.dest)
self.assertEqual(
self.writer.last_date_in_output_for_sid(sid),
@@ -1198,7 +1207,7 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
self.writer.write(update_reader.read(minutes, sids))
# Refresh the reader since truncate update the metadata.
reader = BcolzMinuteBarReader(self.dest)
reader = BcolzExchangeBarReader(self.dest)
columns = ['open', 'high', 'low', 'close', 'volume']
sids = [sids[0], sids[1]]
+6 -6
View File
@@ -35,7 +35,7 @@ from catalyst.testing.fixtures import (
WithBcolzEquityMinuteBarReader,
WithBcolzEquityDailyBarReader,
WithBcolzFutureMinuteBarReader,
ZiplineTestCase,
CatalystTestCase,
)
OHLC = ['open', 'high', 'low', 'close']
@@ -254,7 +254,7 @@ EXPECTED_SESSIONS = {
class MinuteToDailyAggregationTestCase(WithBcolzEquityMinuteBarReader,
WithBcolzFutureMinuteBarReader,
ZiplineTestCase):
CatalystTestCase):
# March 2016
# Su Mo Tu We Th Fr Sa
@@ -525,7 +525,7 @@ class MinuteToDailyAggregationTestCase(WithBcolzEquityMinuteBarReader,
class TestMinuteToSession(WithEquityMinuteBarData,
ZiplineTestCase):
CatalystTestCase):
# March 2016
# Su Mo Tu We Th Fr Sa
@@ -565,7 +565,7 @@ class TestMinuteToSession(WithEquityMinuteBarData,
class TestResampleSessionBars(WithBcolzFutureMinuteBarReader,
ZiplineTestCase):
CatalystTestCase):
TRADING_CALENDAR_STRS = ('us_futures',)
TRADING_CALENDAR_PRIMARY_CAL = 'us_futures'
@@ -667,7 +667,7 @@ class TestResampleSessionBars(WithBcolzFutureMinuteBarReader,
class TestReindexMinuteBars(WithBcolzEquityMinuteBarReader,
ZiplineTestCase):
CatalystTestCase):
TRADING_CALENDAR_STRS = ('us_futures', 'NYSE')
TRADING_CALENDAR_PRIMARY_CAL = 'us_futures'
@@ -736,7 +736,7 @@ class TestReindexMinuteBars(WithBcolzEquityMinuteBarReader,
class TestReindexSessionBars(WithBcolzEquityDailyBarReader,
ZiplineTestCase):
CatalystTestCase):
TRADING_CALENDAR_STRS = ('us_futures', 'NYSE')
TRADING_CALENDAR_PRIMARY_CAL = 'us_futures'
+3 -3
View File
@@ -50,7 +50,7 @@ from catalyst.testing.fixtures import (
WithBcolzEquityDailyBarReader,
WithTmpDir,
WithTradingCalendars,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.calendars import get_calendar
@@ -86,7 +86,7 @@ EQUITY_INFO['symbol'] = [chr(ord('A') + n) for n in range(len(EQUITY_INFO))]
TEST_QUERY_ASSETS = EQUITY_INFO.index
class BcolzDailyBarTestCase(WithBcolzEquityDailyBarReader, ZiplineTestCase):
class BcolzDailyBarTestCase(WithBcolzEquityDailyBarReader, CatalystTestCase):
EQUITY_DAILY_BAR_START_DATE = TEST_CALENDAR_START
EQUITY_DAILY_BAR_END_DATE = TEST_CALENDAR_STOP
@@ -372,7 +372,7 @@ class BcolzDailyBarNeverReadAllTestCase(BcolzDailyBarTestCase):
class BcolzDailyBarWriterMissingDataTestCase(WithAssetFinder,
WithTmpDir,
WithTradingCalendars,
ZiplineTestCase):
CatalystTestCase):
# Sid 3 is active from 2015-06-02 to 2015-06-30.
MISSING_DATA_SID = 3
# Leave out data for a day in the middle of the query range.
+7
View File
@@ -12,6 +12,11 @@
# 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.
'''
# ZIPLINE legacy test: Catalyst only uses OPEN calendar, and thus
# this test suite is irrelevant, and is commented out in its entirety
from unittest import TestCase
import pandas as pd
@@ -41,3 +46,5 @@ class TestStatelessRulesCME(StatelessRulesTests, TestCase):
class TestStatefulRulesCME(StatefulRulesTests, TestCase):
CALENDAR_STRING = "CME"
'''
+7
View File
@@ -12,6 +12,11 @@
# 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.
'''
# ZIPLINE legacy test: Catalyst only uses OPEN calendar, and thus
# this test suite is irrelevant, and is commented out in its entirety
from unittest import TestCase
from datetime import timedelta
import pandas as pd
@@ -162,3 +167,5 @@ class TestStatelessRulesNYSE(StatelessRulesTests, TestCase):
class TestStatefulRulesNYSE(StatefulRulesTests, TestCase):
CALENDAR_STRING = "NYSE"
'''
+96
View File
@@ -0,0 +1,96 @@
import os
import tempfile
import pandas as pd
from catalyst.exchange.ccxt.ccxt_exchange import CCXT
from catalyst.finance.order import Order
from base import BaseExchangeTestCase
from logbook import Logger
from catalyst.exchange.exchange_utils import get_exchange_auth
from catalyst.utils.paths import ensure_directory
log = Logger('test_ccxt')
class TestCCXT(BaseExchangeTestCase):
@classmethod
def setup(self):
exchange_name = 'gdax'
auth = get_exchange_auth(exchange_name)
self.exchange = CCXT(
exchange_name=exchange_name,
key=auth['key'],
secret=auth['secret'],
base_currency='eth',
portfolio=None
)
def test_order(self):
log.info('creating order')
asset = self.exchange.get_asset('neo_eth')
order_id = self.exchange.order(
asset=asset,
limit_price=0.07,
amount=1,
)
log.info('order created {}'.format(order_id))
assert order_id is not None
pass
def test_open_orders(self):
log.info('retrieving open orders')
asset = self.exchange.get_asset('neo_eth')
orders = self.exchange.get_open_orders(asset)
pass
def test_get_order(self):
log.info('retrieving order')
order = self.exchange.get_order('2631386', 'neo_eth')
# order = self.exchange.get_order('2631386')
assert isinstance(order, Order)
pass
def test_cancel_order(self, ):
log.info('cancel order')
self.exchange.cancel_order('2631386', 'neo_eth')
pass
def test_get_candles(self):
log.info('retrieving candles')
candles = self.exchange.get_candles(
freq='5T',
assets=[self.exchange.get_asset('eth_btc')],
bar_count=200,
start_dt=pd.to_datetime('2017-01-01', utc=True)
)
for asset in candles:
df = pd.DataFrame(candles[asset])
df.set_index('last_traded', drop=True, inplace=True)
pass
def test_tickers(self):
log.info('retrieving tickers')
tickers = self.exchange.tickers([
self.exchange.get_asset('eth_btc'),
])
assert len(tickers) == 1
pass
def test_get_balances(self):
log.info('testing wallet balances')
balances = self.exchange.get_balances()
pass
def test_get_account(self):
log.info('testing account data')
pass
def test_orderbook(self):
log.info('testing order book for bittrex')
asset = self.exchange.get_asset('eth_btc')
orderbook = self.exchange.get_orderbook(asset, 'all', limit=10)
pass
def test_get_fees(self):
pass
+2 -2
View File
@@ -37,7 +37,7 @@ from catalyst.testing.fixtures import (
WithDataPortal,
WithLogger,
WithSimParams,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.classproperty import classproperty
@@ -46,7 +46,7 @@ class BlotterTestCase(WithCreateBarData,
WithLogger,
WithDataPortal,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-05', tz='utc')
END_DATE = pd.Timestamp('2006-01-06', tz='utc')
ASSET_FINDER_EQUITY_SIDS = 24, 25
+3 -3
View File
@@ -19,7 +19,7 @@ from catalyst.finance.commission import (
)
from catalyst.finance.order import Order
from catalyst.finance.transaction import Transaction
from catalyst.testing import ZiplineTestCase, trades_by_sid_to_dfs
from catalyst.testing import CatalystTestCase, trades_by_sid_to_dfs
from catalyst.testing.fixtures import (
WithAssetFinder,
WithSimParams,
@@ -28,7 +28,7 @@ from catalyst.testing.fixtures import (
from catalyst.utils import factory
class CommissionUnitTests(WithAssetFinder, ZiplineTestCase):
class CommissionUnitTests(WithAssetFinder, CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = 1, 2
@classmethod
@@ -272,7 +272,7 @@ class CommissionUnitTests(WithAssetFinder, ZiplineTestCase):
self.assertAlmostEqual(15.3, model.calculate(order, txns[2]))
class CommissionAlgorithmTests(WithDataPortal, WithSimParams, ZiplineTestCase):
class CommissionAlgorithmTests(WithDataPortal, WithSimParams, CatalystTestCase):
# make sure order commissions are properly incremented
sidint, = ASSET_FINDER_EQUITY_SIDS = (133,)
+6 -6
View File
@@ -48,7 +48,7 @@ from catalyst.testing.fixtures import (
WithDataPortal,
WithSimParams,
WithTradingEnvironment,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.classproperty import classproperty
@@ -59,7 +59,7 @@ TestOrder = namedtuple('TestOrder', 'limit direction')
class SlippageTestCase(WithCreateBarData,
WithSimParams,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-05 14:31', tz='utc')
END_DATE = pd.Timestamp('2006-01-05 14:36', tz='utc')
SIM_PARAMS_CAPITAL_BASE = 1.0e5
@@ -566,7 +566,7 @@ class SlippageTestCase(WithCreateBarData,
class VolumeShareSlippageTestCase(WithCreateBarData,
WithSimParams,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-05 14:31', tz='utc')
END_DATE = pd.Timestamp('2006-01-05 14:36', tz='utc')
@@ -743,7 +743,7 @@ class VolumeShareSlippageTestCase(WithCreateBarData,
class VolatilityVolumeShareTestCase(WithCreateBarData,
WithSimParams,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
ASSET_START_DATE = pd.Timestamp('2006-02-10')
@@ -890,7 +890,7 @@ class VolatilityVolumeShareTestCase(WithCreateBarData,
self.assertIsNone(amount)
class MarketImpactTestCase(WithCreateBarData, ZiplineTestCase):
class MarketImpactTestCase(WithCreateBarData, CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = (1,)
@@ -947,7 +947,7 @@ class MarketImpactTestCase(WithCreateBarData, ZiplineTestCase):
class OrdersStopTestCase(WithSimParams,
WithTradingEnvironment,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-05 14:31', tz='utc')
END_DATE = pd.Timestamp('2006-01-05 14:36', tz='utc')
+2 -2
View File
@@ -18,7 +18,7 @@ from catalyst.testing import (
from catalyst.testing.fixtures import (
WithAssetFinder,
WithTradingSessions,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.functional import dzip_exact
@@ -54,7 +54,7 @@ with_default_shape = with_defaults(shape=lambda self: self.default_shape)
class BasePipelineTestCase(WithTradingSessions,
WithAssetFinder,
ZiplineTestCase):
CatalystTestCase):
START_DATE = Timestamp('2014', tz='UTC')
END_DATE = Timestamp('2014-12-31', tz='UTC')
ASSET_FINDER_EQUITY_SIDS = list(range(20))
+3 -3
View File
@@ -34,7 +34,7 @@ from catalyst.pipeline.loaders.blaze.core import (
NonPipelineField,
)
from catalyst.testing import (
ZiplineTestCase,
CatalystTestCase,
parameter_space,
tmp_asset_finder,
)
@@ -77,7 +77,7 @@ def _utc_localize_index_level_0(df):
return df
class BlazeToPipelineTestCase(WithAssetFinder, ZiplineTestCase):
class BlazeToPipelineTestCase(WithAssetFinder, CatalystTestCase):
START_DATE = pd.Timestamp(0)
END_DATE = pd.Timestamp('2015')
@@ -1927,7 +1927,7 @@ class BlazeToPipelineTestCase(WithAssetFinder, ZiplineTestCase):
)
class MiscTestCase(ZiplineTestCase):
class MiscTestCase(CatalystTestCase):
def test_exprdata_repr(self):
strd = set()
+2 -2
View File
@@ -7,7 +7,7 @@ import pandas as pd
from catalyst.lib.labelarray import LabelArray
from catalyst.pipeline import Classifier
from catalyst.testing import parameter_space
from catalyst.testing.fixtures import ZiplineTestCase
from catalyst.testing.fixtures import CatalystTestCase
from catalyst.testing.predicates import assert_equal
from catalyst.utils.numpy_utils import (
categorical_dtype,
@@ -585,7 +585,7 @@ class ClassifierTestCase(BasePipelineTestCase):
self.assertEqual(result, expected)
class TestPostProcessAndToWorkSpaceValue(ZiplineTestCase):
class TestPostProcessAndToWorkSpaceValue(CatalystTestCase):
def test_reversability_categorical(self):
class F(Classifier):
inputs = ()
+3 -3
View File
@@ -13,7 +13,7 @@ from catalyst.pipeline import (
from catalyst.pipeline.data.testing import TestingDataSet
from catalyst.pipeline.factors.equity import SimpleMovingAverage
from catalyst.pipeline.filters.smoothing import All
from catalyst.testing import ZiplineTestCase, parameter_space
from catalyst.testing import CatalystTestCase, parameter_space
from catalyst.testing.fixtures import (
WithTradingSessions,
WithSeededRandomPipelineEngine,
@@ -44,7 +44,7 @@ class NDaysAgoClassifier(CustomClassifier):
out[:] = cats[0]
class ComputeExtraRowsTestcase(WithTradingSessions, ZiplineTestCase):
class ComputeExtraRowsTestcase(WithTradingSessions, CatalystTestCase):
DATA_MIN_DAY = pd.Timestamp('2012-06', tz='UTC')
DATA_MAX_DAY = pd.Timestamp('2015', tz='UTC')
@@ -555,7 +555,7 @@ class ComputeExtraRowsTestcase(WithTradingSessions, ZiplineTestCase):
class DownsampledPipelineTestCase(WithSeededRandomPipelineEngine,
ZiplineTestCase):
CatalystTestCase):
# Extend into the last few days of 2013 to test year/quarter boundaries.
START_DATE = pd.Timestamp('2013-12-15', tz='UTC')
+9 -9
View File
@@ -81,7 +81,7 @@ from catalyst.testing.fixtures import (
WithEquityPricingPipelineEngine,
WithSeededRandomPipelineEngine,
WithTradingEnvironment,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.testing.predicates import assert_equal
from catalyst.utils.memoize import lazyval
@@ -199,7 +199,7 @@ class WithConstantInputs(WithTradingEnvironment):
cls.assets = cls.asset_finder.retrieve_all(cls.asset_ids)
class ConstantInputTestCase(WithConstantInputs, ZiplineTestCase):
class ConstantInputTestCase(WithConstantInputs, CatalystTestCase):
def test_bad_dates(self):
loader = self.loader
engine = SimplePipelineEngine(
@@ -816,7 +816,7 @@ class ConstantInputTestCase(WithConstantInputs, ZiplineTestCase):
Loader2DataSet.col2)})
class FrameInputTestCase(WithTradingEnvironment, ZiplineTestCase):
class FrameInputTestCase(WithTradingEnvironment, CatalystTestCase):
asset_ids = ASSET_FINDER_EQUITY_SIDS = 1, 2, 3
start = START_DATE = Timestamp('2015-01-01', tz='utc')
end = END_DATE = Timestamp('2015-01-31', tz='utc')
@@ -921,7 +921,7 @@ class FrameInputTestCase(WithTradingEnvironment, ZiplineTestCase):
class SyntheticBcolzTestCase(WithAdjustmentReader,
ZiplineTestCase):
CatalystTestCase):
first_asset_start = Timestamp('2015-04-01', tz='UTC')
START_DATE = Timestamp('2015-01-01', tz='utc')
END_DATE = Timestamp('2015-08-01', tz='utc')
@@ -1079,7 +1079,7 @@ class SyntheticBcolzTestCase(WithAdjustmentReader,
assert_frame_equal(expected, result)
class ParameterizedFactorTestCase(WithTradingEnvironment, ZiplineTestCase):
class ParameterizedFactorTestCase(WithTradingEnvironment, CatalystTestCase):
sids = ASSET_FINDER_EQUITY_SIDS = Int64Index([1, 2, 3])
START_DATE = Timestamp('2015-01-31', tz='UTC')
END_DATE = Timestamp('2015-03-01', tz='UTC')
@@ -1297,7 +1297,7 @@ class ParameterizedFactorTestCase(WithTradingEnvironment, ZiplineTestCase):
class StringColumnTestCase(WithSeededRandomPipelineEngine,
ZiplineTestCase):
CatalystTestCase):
def test_string_classifiers_produce_categoricals(self):
"""
@@ -1327,7 +1327,7 @@ class StringColumnTestCase(WithSeededRandomPipelineEngine,
class WindowSafetyPropagationTestCase(WithSeededRandomPipelineEngine,
ZiplineTestCase):
CatalystTestCase):
SEEDED_RANDOM_PIPELINE_SEED = 5
@@ -1378,7 +1378,7 @@ class WindowSafetyPropagationTestCase(WithSeededRandomPipelineEngine,
assert_equal(expected_result, results[colname])
class PopulateInitialWorkspaceTestCase(WithConstantInputs, ZiplineTestCase):
class PopulateInitialWorkspaceTestCase(WithConstantInputs, CatalystTestCase):
@parameter_space(window_length=[3, 5], pipeline_length=[5, 10])
def test_populate_initial_workspace(self, window_length, pipeline_length):
@@ -1503,7 +1503,7 @@ class PopulateInitialWorkspaceTestCase(WithConstantInputs, ZiplineTestCase):
class ChunkedPipelineTestCase(WithEquityPricingPipelineEngine,
ZiplineTestCase):
CatalystTestCase):
PIPELINE_START_DATE = Timestamp('2006-01-05', tz='UTC')
END_DATE = Timestamp('2006-12-29', tz='UTC')
+5 -5
View File
@@ -24,7 +24,7 @@ from catalyst.pipeline.loaders.utils import (
normalize_timestamp_to_query_time,
previous_event_indexer,
)
from catalyst.testing import check_arrays, ZiplineTestCase
from catalyst.testing import check_arrays, CatalystTestCase
from catalyst.testing.fixtures import (
WithAssetFinder,
WithTradingSessions,
@@ -148,7 +148,7 @@ def make_events(add_nulls):
return pd.concat(event_frames, ignore_index=True)
class EventIndexerTestCase(ZiplineTestCase):
class EventIndexerTestCase(CatalystTestCase):
@classmethod
def init_class_fixtures(cls):
@@ -269,7 +269,7 @@ class EventIndexerTestCase(ZiplineTestCase):
class EventsLoaderEmptyTestCase(WithAssetFinder,
WithTradingSessions,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2014-01-01')
END_DATE = pd.Timestamp('2014-01-30')
@@ -351,7 +351,7 @@ class EventsLoaderEmptyTestCase(WithAssetFinder,
class EventsLoaderTestCase(WithAssetFinder,
WithTradingSessions,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2014-01-01')
END_DATE = pd.Timestamp('2014-01-30')
@@ -586,7 +586,7 @@ class BlazeEventsLoaderTestCase(EventsLoaderTestCase):
)
class EventLoaderUtilsTestCase(ZiplineTestCase):
class EventLoaderUtilsTestCase(CatalystTestCase):
# These cases test the following:
# 1. Shuffling timestamps in DST/EST produces the correct normalized
# timestamps
+2 -2
View File
@@ -40,7 +40,7 @@ from catalyst.testing import (
parameter_space,
permute_rows,
)
from catalyst.testing.fixtures import ZiplineTestCase
from catalyst.testing.fixtures import CatalystTestCase
from catalyst.testing.predicates import assert_equal
from catalyst.utils.numpy_utils import (
categorical_dtype,
@@ -1246,7 +1246,7 @@ class TestWindowSafety(TestCase):
)
class TestPostProcessAndToWorkSpaceValue(ZiplineTestCase):
class TestPostProcessAndToWorkSpaceValue(CatalystTestCase):
@parameter_space(dtype_=(float64_dtype, datetime64ns_dtype))
def test_reversability(self, dtype_):
class F(Factor):
+3 -3
View File
@@ -37,7 +37,7 @@ from catalyst.pipeline.filters import (
StaticAssets,
StaticSids,
)
from catalyst.testing import parameter_space, permute_rows, ZiplineTestCase
from catalyst.testing import parameter_space, permute_rows, CatalystTestCase
from catalyst.testing.fixtures import WithSeededRandomPipelineEngine
from catalyst.testing.predicates import assert_equal
from catalyst.utils.numpy_utils import float64_dtype, int64_dtype
@@ -841,7 +841,7 @@ class SidFactor(CustomFactor):
class SpecificAssetsTestCase(WithSeededRandomPipelineEngine,
ZiplineTestCase):
CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = tuple(range(10))
@@ -887,7 +887,7 @@ class SpecificAssetsTestCase(WithSeededRandomPipelineEngine,
)
class TestPostProcessAndToWorkSpaceValue(ZiplineTestCase):
class TestPostProcessAndToWorkSpaceValue(CatalystTestCase):
def test_reversability(self):
class F(Filter):
inputs = ()
+3 -3
View File
@@ -60,7 +60,7 @@ from catalyst.testing.fixtures import (
WithAdjustmentReader,
WithBcolzEquityDailyBarReaderFromCSVs,
WithDataPortal,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.calendars import get_calendar
@@ -84,7 +84,7 @@ def rolling_vwap(df, length):
return Series(out, index=df.index)
class ClosesOnly(WithDataPortal, ZiplineTestCase):
class ClosesOnly(WithDataPortal, CatalystTestCase):
sids = 1, 2, 3
START_DATE = pd.Timestamp('2014-01-01', tz='utc')
END_DATE = pd.Timestamp('2014-02-01', tz='utc')
@@ -355,7 +355,7 @@ class MockDailyBarSpotReader(object):
class PipelineAlgorithmTestCase(WithBcolzEquityDailyBarReaderFromCSVs,
WithAdjustmentReader,
ZiplineTestCase):
CatalystTestCase):
AAPL = 1
MSFT = 2
BRK_A = 3
+31 -31
View File
@@ -40,7 +40,7 @@ from catalyst.pipeline.loaders.earnings_estimates import (
from catalyst.testing.fixtures import (
WithAdjustmentReader,
WithTradingSessions,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.testing.predicates import assert_equal, assert_raises_regex
from catalyst.testing.predicates import assert_frame_equal
@@ -113,7 +113,7 @@ def create_expected_df_for_factor_compute(start_date,
class WithEstimates(WithTradingSessions, WithAdjustmentReader):
"""
ZiplineTestCase mixin providing cls.loader and cls.events as class
CatalystTestCase mixin providing cls.loader and cls.events as class
level fixtures.
@@ -177,7 +177,7 @@ class WithEstimates(WithTradingSessions, WithAdjustmentReader):
class WithOneDayPipeline(WithEstimates):
"""
ZiplineTestCase mixin providing cls.events as a class level fixture and
CatalystTestCase mixin providing cls.events as a class level fixture and
defining a test for all inheritors to use.
Attributes
@@ -246,7 +246,7 @@ class WithOneDayPipeline(WithEstimates):
assert_frame_equal(results, self.expected_out)
class PreviousWithOneDayPipeline(WithOneDayPipeline, ZiplineTestCase):
class PreviousWithOneDayPipeline(WithOneDayPipeline, CatalystTestCase):
"""
Tests that previous quarter loader correctly breaks if an incorrect
number of quarters is passed.
@@ -271,7 +271,7 @@ class PreviousWithOneDayPipeline(WithOneDayPipeline, ZiplineTestCase):
)
class NextWithOneDayPipeline(WithOneDayPipeline, ZiplineTestCase):
class NextWithOneDayPipeline(WithOneDayPipeline, CatalystTestCase):
"""
Tests that next quarter loader correctly breaks if an incorrect
number of quarters is passed.
@@ -308,7 +308,7 @@ dummy_df = pd.DataFrame({SID_FIELD_NAME: 0},
class WithWrongLoaderDefinition(WithEstimates):
"""
ZiplineTestCase mixin providing cls.events as a class level fixture and
CatalystTestCase mixin providing cls.events as a class level fixture and
defining a test for all inheritors to use.
Attributes
@@ -372,7 +372,7 @@ class WithWrongLoaderDefinition(WithEstimates):
class PreviousWithWrongNumQuarters(WithWrongLoaderDefinition,
ZiplineTestCase):
CatalystTestCase):
"""
Tests that previous quarter loader correctly breaks if an incorrect
number of quarters is passed.
@@ -383,7 +383,7 @@ class PreviousWithWrongNumQuarters(WithWrongLoaderDefinition,
class NextWithWrongNumQuarters(WithWrongLoaderDefinition,
ZiplineTestCase):
CatalystTestCase):
"""
Tests that next quarter loader correctly breaks if an incorrect
number of quarters is passed.
@@ -398,7 +398,7 @@ options = ["split_adjustments_loader",
"split_adjusted_asof"]
class WrongSplitsLoaderDefinition(WithEstimates, ZiplineTestCase):
class WrongSplitsLoaderDefinition(WithEstimates, CatalystTestCase):
"""
Test class that tests that loaders break correctly when incorrectly
instantiated.
@@ -436,7 +436,7 @@ class WrongSplitsLoaderDefinition(WithEstimates, ZiplineTestCase):
class WithEstimatesTimeZero(WithEstimates):
"""
ZiplineTestCase mixin providing cls.events as a class level fixture and
CatalystTestCase mixin providing cls.events as a class level fixture and
defining a test for all inheritors to use.
Attributes
@@ -622,7 +622,7 @@ class WithEstimatesTimeZero(WithEstimates):
sid_estimates)
class NextEstimate(WithEstimatesTimeZero, ZiplineTestCase):
class NextEstimate(WithEstimatesTimeZero, CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
return NextEarningsEstimatesLoader(events, columns)
@@ -662,7 +662,7 @@ class BlazeNextEstimateLoaderTestCase(NextEstimate):
)
class PreviousEstimate(WithEstimatesTimeZero, ZiplineTestCase):
class PreviousEstimate(WithEstimatesTimeZero, CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
return PreviousEarningsEstimatesLoader(events, columns)
@@ -703,7 +703,7 @@ class BlazePreviousEstimateLoaderTestCase(PreviousEstimate):
class WithEstimateMultipleQuarters(WithEstimates):
"""
ZiplineTestCase mixin providing cls.events, cls.make_expected_out as
CatalystTestCase mixin providing cls.events, cls.make_expected_out as
class-level fixtures and self.test_multiple_qtrs_requested as a test.
Attributes
@@ -797,7 +797,7 @@ class WithEstimateMultipleQuarters(WithEstimates):
class NextEstimateMultipleQuarters(
WithEstimateMultipleQuarters, ZiplineTestCase
WithEstimateMultipleQuarters, CatalystTestCase
):
@classmethod
def make_loader(cls, events, columns):
@@ -854,7 +854,7 @@ class BlazeNextEstimateMultipleQuarters(NextEstimateMultipleQuarters):
class PreviousEstimateMultipleQuarters(
WithEstimateMultipleQuarters,
ZiplineTestCase
CatalystTestCase
):
@classmethod
@@ -903,7 +903,7 @@ class BlazePreviousEstimateMultipleQuarters(PreviousEstimateMultipleQuarters):
class WithVaryingNumEstimates(WithEstimates):
"""
ZiplineTestCase mixin providing fixtures and a test to ensure that we
CatalystTestCase mixin providing fixtures and a test to ensure that we
have the correct overwrites when the event date changes. We want to make
sure that if we have a quarter with an event date that gets pushed back,
we don't start overwriting for the next quarter early. Likewise,
@@ -973,7 +973,7 @@ class WithVaryingNumEstimates(WithEstimates):
class PreviousVaryingNumEstimates(
WithVaryingNumEstimates,
ZiplineTestCase
CatalystTestCase
):
def assert_compute(self, estimate, today):
if today == pd.Timestamp('2015-01-13', tz='utc'):
@@ -1003,7 +1003,7 @@ class BlazePreviousVaryingNumEstimates(PreviousVaryingNumEstimates):
class NextVaryingNumEstimates(
WithVaryingNumEstimates,
ZiplineTestCase
CatalystTestCase
):
def assert_compute(self, estimate, today):
@@ -1034,7 +1034,7 @@ class BlazeNextVaryingNumEstimates(NextVaryingNumEstimates):
class WithEstimateWindows(WithEstimates):
"""
ZiplineTestCase mixin providing fixures and a test to test running a
CatalystTestCase mixin providing fixures and a test to test running a
Pipeline with an estimates loader over differently-sized windows.
Attributes
@@ -1198,7 +1198,7 @@ class WithEstimateWindows(WithEstimates):
)
class PreviousEstimateWindows(WithEstimateWindows, ZiplineTestCase):
class PreviousEstimateWindows(WithEstimateWindows, CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
return PreviousEarningsEstimatesLoader(events, columns)
@@ -1279,7 +1279,7 @@ class BlazePreviousEstimateWindows(PreviousEstimateWindows):
return BlazePreviousEstimatesLoader(bz.data(events), columns)
class NextEstimateWindows(WithEstimateWindows, ZiplineTestCase):
class NextEstimateWindows(WithEstimateWindows, CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
return NextEarningsEstimatesLoader(events, columns)
@@ -1394,7 +1394,7 @@ class BlazeNextEstimateWindows(NextEstimateWindows):
class WithSplitAdjustedWindows(WithEstimateWindows):
"""
ZiplineTestCase mixin providing fixures and a test to test running a
CatalystTestCase mixin providing fixures and a test to test running a
Pipeline with an estimates loader over differently-sized windows and with
split adjustments.
"""
@@ -1572,7 +1572,7 @@ class WithSplitAdjustedWindows(WithEstimateWindows):
class PreviousWithSplitAdjustedWindows(WithSplitAdjustedWindows,
ZiplineTestCase):
CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
return PreviousSplitAdjustedEarningsEstimatesLoader(
@@ -1726,7 +1726,7 @@ class BlazePreviousWithSplitAdjustedWindows(PreviousWithSplitAdjustedWindows):
)
class NextWithSplitAdjustedWindows(WithSplitAdjustedWindows, ZiplineTestCase):
class NextWithSplitAdjustedWindows(WithSplitAdjustedWindows, CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
@@ -1951,7 +1951,7 @@ class BlazeNextWithSplitAdjustedWindows(NextWithSplitAdjustedWindows):
class WithSplitAdjustedMultipleEstimateColumns(WithEstimates):
"""
ZiplineTestCase mixin for having multiple estimate columns that are
CatalystTestCase mixin for having multiple estimate columns that are
split-adjusted to make sure that adjustments are applied correctly.
Attributes
@@ -2136,7 +2136,7 @@ class WithSplitAdjustedMultipleEstimateColumns(WithEstimates):
class PreviousWithSplitAdjustedMultipleEstimateColumns(
WithSplitAdjustedMultipleEstimateColumns, ZiplineTestCase
WithSplitAdjustedMultipleEstimateColumns, CatalystTestCase
):
@classmethod
def make_loader(cls, events, columns):
@@ -2218,7 +2218,7 @@ class BlazePreviousWithMultipleEstimateColumns(
class NextWithSplitAdjustedMultipleEstimateColumns(
WithSplitAdjustedMultipleEstimateColumns, ZiplineTestCase
WithSplitAdjustedMultipleEstimateColumns, CatalystTestCase
):
@classmethod
def make_loader(cls, events, columns):
@@ -2295,7 +2295,7 @@ class BlazeNextWithMultipleEstimateColumns(
class WithAdjustmentBoundaries(WithEstimates):
"""
ZiplineTestCase mixin providing class-level attributes, methods,
CatalystTestCase mixin providing class-level attributes, methods,
and a test to make sure that when the split-adjusted-asof-date is not
strictly within the date index, we can still apply adjustments correctly.
@@ -2470,7 +2470,7 @@ class WithAdjustmentBoundaries(WithEstimates):
class PreviousWithAdjustmentBoundaries(WithAdjustmentBoundaries,
ZiplineTestCase):
CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
return partial(PreviousSplitAdjustedEarningsEstimatesLoader,
@@ -2612,7 +2612,7 @@ class BlazePreviousWithAdjustmentBoundaries(PreviousWithAdjustmentBoundaries):
class NextWithAdjustmentBoundaries(WithAdjustmentBoundaries,
ZiplineTestCase):
CatalystTestCase):
@classmethod
def make_loader(cls, events, columns):
return partial(NextSplitAdjustedEarningsEstimatesLoader,
@@ -2720,7 +2720,7 @@ class BlazeNextWithAdjustmentBoundaries(NextWithAdjustmentBoundaries):
split_adjusted_column_names=['estimate'])
class QuarterShiftTestCase(ZiplineTestCase):
class QuarterShiftTestCase(CatalystTestCase):
"""
This tests, in isolation, quarter calculation logic for shifting quarters
backwards/forwards from a starting point.
+2 -2
View File
@@ -31,12 +31,12 @@ from catalyst.testing import (
)
from catalyst.testing.fixtures import (
WithSeededRandomPipelineEngine,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.numpy_utils import datetime64ns_dtype
class SliceTestCase(WithSeededRandomPipelineEngine, ZiplineTestCase):
class SliceTestCase(WithSeededRandomPipelineEngine, CatalystTestCase):
sids = ASSET_FINDER_EQUITY_SIDS = Int64Index([1, 2, 3])
START_DATE = Timestamp('2015-01-31', tz='UTC')
END_DATE = Timestamp('2015-03-01', tz='UTC')
+3 -3
View File
@@ -42,7 +42,7 @@ from catalyst.testing import (
from catalyst.testing.fixtures import (
WithSeededRandomPipelineEngine,
WithTradingEnvironment,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.numpy_utils import (
bool_dtype,
@@ -51,7 +51,7 @@ from catalyst.utils.numpy_utils import (
)
class StatisticalBuiltInsTestCase(WithTradingEnvironment, ZiplineTestCase):
class StatisticalBuiltInsTestCase(WithTradingEnvironment, CatalystTestCase):
sids = ASSET_FINDER_EQUITY_SIDS = Int64Index([1, 2, 3])
START_DATE = Timestamp('2015-01-31', tz='UTC')
END_DATE = Timestamp('2015-03-01', tz='UTC')
@@ -388,7 +388,7 @@ class StatisticalBuiltInsTestCase(WithTradingEnvironment, ZiplineTestCase):
class StatisticalMethodsTestCase(WithSeededRandomPipelineEngine,
ZiplineTestCase):
CatalystTestCase):
sids = ASSET_FINDER_EQUITY_SIDS = Int64Index([1, 2, 3])
START_DATE = Timestamp('2015-01-31', tz='UTC')
END_DATE = Timestamp('2015-03-01', tz='UTC')
+9 -9
View File
@@ -21,7 +21,7 @@ from catalyst.pipeline.factors.equity import (
AnnualizedVolatility,
)
from catalyst.testing import parameter_space
from catalyst.testing.fixtures import ZiplineTestCase
from catalyst.testing.fixtures import CatalystTestCase
from catalyst.testing.predicates import assert_equal
from .base import BasePipelineTestCase
@@ -115,7 +115,7 @@ class BollingerBandsTestCase(BasePipelineTestCase):
self.assertIs(upper, bbands.upper)
class AroonTestCase(ZiplineTestCase):
class AroonTestCase(CatalystTestCase):
window_length = 10
nassets = 5
dtype = [('down', 'f8'), ('up', 'f8')]
@@ -148,7 +148,7 @@ class AroonTestCase(ZiplineTestCase):
assert_equal(out, expected_out)
class TestFastStochasticOscillator(ZiplineTestCase):
class TestFastStochasticOscillator(CatalystTestCase):
"""
Test the Fast Stochastic Oscillator
"""
@@ -218,7 +218,7 @@ class TestFastStochasticOscillator(ZiplineTestCase):
assert_equal(out, expected_out_k, array_decimal=6)
class IchimokuKinkoHyoTestCase(ZiplineTestCase):
class IchimokuKinkoHyoTestCase(CatalystTestCase):
def test_ichimoku_kinko_hyo(self):
window_length = 52
today = pd.Timestamp('2014', tz='utc')
@@ -334,7 +334,7 @@ class IchimokuKinkoHyoTestCase(ZiplineTestCase):
)
class TestRateOfChangePercentage(ZiplineTestCase):
class TestRateOfChangePercentage(CatalystTestCase):
@parameterized.expand([
('constant', [2.] * 10, 0.0),
('step', [2.] + [1.] * 9, -50.0),
@@ -358,7 +358,7 @@ class TestRateOfChangePercentage(ZiplineTestCase):
assert_equal(out, np.full((len(assets),), expected))
class TestLinearWeightedMovingAverage(ZiplineTestCase):
class TestLinearWeightedMovingAverage(CatalystTestCase):
def test_wma1(self):
wma1 = LinearWeightedMovingAverage(
inputs=(USEquityPricing.close,),
@@ -390,7 +390,7 @@ class TestLinearWeightedMovingAverage(ZiplineTestCase):
assert_equal(out, np.array([30., 31., 32., 33., 34.]))
class TestTrueRange(ZiplineTestCase):
class TestTrueRange(CatalystTestCase):
def test_tr_basic(self):
tr = TrueRange()
@@ -407,7 +407,7 @@ class TestTrueRange(ZiplineTestCase):
assert_equal(out, np.full((3,), 2.))
class MovingAverageConvergenceDivergenceTestCase(ZiplineTestCase):
class MovingAverageConvergenceDivergenceTestCase(CatalystTestCase):
def expected_ewma(self, data_df, window):
# Comment copied from `test_engine.py`:
@@ -532,7 +532,7 @@ class MovingAverageConvergenceDivergenceTestCase(ZiplineTestCase):
)
class AnnualizedVolatilityTestCase(ZiplineTestCase):
class AnnualizedVolatilityTestCase(CatalystTestCase):
"""
Test Annualized Volatility
"""
+2 -2
View File
@@ -34,7 +34,7 @@ from catalyst.pipeline.factors import RecarrayField
from catalyst.pipeline.sentinels import NotSpecified
from catalyst.pipeline.term import AssetExists, Slice
from catalyst.testing import parameter_space
from catalyst.testing.fixtures import WithTradingSessions, ZiplineTestCase
from catalyst.testing.fixtures import WithTradingSessions, CatalystTestCase
from catalyst.testing.predicates import (
assert_equal,
assert_raises,
@@ -155,7 +155,7 @@ def to_dict(l):
return dict(zip(map(str, range(len(l))), l))
class DependencyResolutionTestCase(WithTradingSessions, ZiplineTestCase):
class DependencyResolutionTestCase(WithTradingSessions, CatalystTestCase):
TRADING_CALENDAR_STRS = ('NYSE',)
START_DATE = pd.Timestamp('2014-01-02', tz='UTC')
@@ -55,7 +55,7 @@ from catalyst.testing import (
)
from catalyst.testing.fixtures import (
WithAdjustmentReader,
ZiplineTestCase,
CatalystTestCase,
)
# Test calendar ranges over the month of June 2015
@@ -258,7 +258,7 @@ DIVIDENDS_EXPECTED = DataFrame(
class USEquityPricingLoaderTestCase(WithAdjustmentReader,
ZiplineTestCase):
CatalystTestCase):
START_DATE = TEST_CALENDAR_START
END_DATE = TEST_CALENDAR_STOP
asset_ids = 1, 2, 3
+2 -2
View File
@@ -18,7 +18,7 @@ import pandas as pd
import catalyst.finance.risk as risk
from catalyst.utils import factory
from catalyst.testing.fixtures import WithTradingEnvironment, ZiplineTestCase
from catalyst.testing.fixtures import WithTradingEnvironment, CatalystTestCase
from catalyst.finance.trading import SimulationParameters
@@ -30,7 +30,7 @@ BENCHMARK = [BENCHMARK_BASE] * 251
DECIMAL_PLACES = 8
class TestRisk(WithTradingEnvironment, ZiplineTestCase):
class TestRisk(WithTradingEnvironment, CatalystTestCase):
def init_instance_fixtures(self):
super(TestRisk, self).init_instance_fixtures()
+24 -2
View File
@@ -22,7 +22,7 @@ import catalyst.finance.risk as risk
from catalyst.utils import factory
from catalyst.finance.trading import SimulationParameters
from catalyst.testing.fixtures import WithTradingEnvironment, ZiplineTestCase
from catalyst.testing.fixtures import WithTradingEnvironment, CatalystTestCase
from catalyst.finance.risk.period import RiskMetricsPeriod
@@ -34,7 +34,7 @@ BENCHMARK = [BENCHMARK_BASE] * 251
DECIMAL_PLACES = 8
class TestRisk(WithTradingEnvironment, ZiplineTestCase):
class TestRisk(WithTradingEnvironment, CatalystTestCase):
def init_instance_fixtures(self):
super(TestRisk, self).init_instance_fixtures()
@@ -232,6 +232,28 @@ class TestRisk(WithTradingEnvironment, ZiplineTestCase):
# The sortino ratio is calculated by a empyrical function so testing
# of period sortino ratios will be limited to determine if the value is
# numerical. This tests for its existence and format.
# This test needs a different result set that, with some
# negative results, otherwise fails in a legitimate way.
RETURNS = (np.random.rand(251) * 0.1) - 0.05
self.algo_returns = factory.create_returns_from_list(
RETURNS,
self.sim_params
)
self.metrics = risk.RiskReport(
self.algo_returns,
self.sim_params,
benchmark_returns=self.benchmark_returns,
trading_calendar=self.trading_calendar,
treasury_curves=self.env.treasury_curves,
)
for x in self.metrics.month_periods:
print (type(x.sortino))
np.testing.assert_equal(
all(isinstance(x.sortino, float)
for x in self.metrics.month_periods),
+52 -52
View File
@@ -109,7 +109,7 @@ from catalyst.testing.fixtures import (
WithSimParams,
WithTradingEnvironment,
WithTmpDir,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.test_algorithms import (
access_account_in_init,
@@ -190,7 +190,7 @@ import catalyst.utils.factory as factory
_multiprocess_can_split_ = False
class TestRecordAlgorithm(WithSimParams, WithDataPortal, ZiplineTestCase):
class TestRecordAlgorithm(WithSimParams, WithDataPortal, CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = 133,
def test_record_incr(self):
@@ -210,7 +210,7 @@ class TestRecordAlgorithm(WithSimParams, WithDataPortal, ZiplineTestCase):
class TestMiscellaneousAPI(WithLogger,
WithSimParams,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='UTC')
END_DATE = pd.Timestamp('2006-01-04', tz='UTC')
@@ -819,7 +819,7 @@ def log_nyse_close(context, data):
class TestTransformAlgorithm(WithLogger,
WithDataPortal,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-01-06', tz='utc')
@@ -1092,7 +1092,7 @@ def before_trading_start(context, data):
class TestPositions(WithLogger,
WithDataPortal,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-01-06', tz='utc')
SIM_PARAMS_CAPITAL_BASE = 1000
@@ -1225,7 +1225,7 @@ class TestPositions(WithLogger,
class TestBeforeTradingStart(WithDataPortal,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2016-01-06', tz='utc')
END_DATE = pd.Timestamp('2016-01-07', tz='utc')
SIM_PARAMS_CAPITAL_BASE = 10000
@@ -1578,7 +1578,7 @@ class TestBeforeTradingStart(WithDataPortal,
class TestAlgoScript(WithLogger,
WithDataPortal,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-12-31', tz='utc')
DATA_PORTAL_USE_MINUTE_DATA = False
@@ -2331,7 +2331,7 @@ def handle_data(context, data):
class TestCapitalChanges(WithLogger,
WithDataPortal,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
sids = 0, 1
@@ -2339,16 +2339,16 @@ class TestCapitalChanges(WithLogger,
def make_equity_info(cls):
data = make_simple_equity_info(
cls.sids,
pd.Timestamp('2006-01-03', tz='UTC'),
pd.Timestamp('2006-01-09', tz='UTC'),
pd.Timestamp('2016-01-03', tz='UTC'),
pd.Timestamp('2016-01-09', tz='UTC'),
)
return data
@classmethod
def make_equity_minute_bar_data(cls):
minutes = cls.trading_calendar.minutes_in_range(
pd.Timestamp('2006-01-03', tz='UTC'),
pd.Timestamp('2006-01-09', tz='UTC')
pd.Timestamp('2016-01-03', tz='UTC'),
pd.Timestamp('2016-01-09', tz='UTC')
)
return trades_by_sid_to_dfs(
{
@@ -2366,8 +2366,8 @@ class TestCapitalChanges(WithLogger,
@classmethod
def make_equity_daily_bar_data(cls):
days = cls.trading_calendar.sessions_in_range(
pd.Timestamp('2006-01-03', tz='UTC'),
pd.Timestamp('2006-01-09', tz='UTC')
pd.Timestamp('2016-01-03', tz='UTC'),
pd.Timestamp('2016-01-09', tz='UTC')
)
return trades_by_sid_to_dfs(
{
@@ -2387,12 +2387,12 @@ class TestCapitalChanges(WithLogger,
])
def test_capital_changes_daily_mode(self, change_type, value):
sim_params = factory.create_simulation_parameters(
start=pd.Timestamp('2006-01-03', tz='UTC'),
end=pd.Timestamp('2006-01-09', tz='UTC')
start=pd.Timestamp('2016-01-03', tz='UTC'),
end=pd.Timestamp('2016-01-09', tz='UTC')
)
capital_changes = {
pd.Timestamp('2006-01-06', tz='UTC'):
pd.Timestamp('2016-01-06', tz='UTC'):
{'type': change_type, 'value': value}
}
@@ -2429,7 +2429,7 @@ def order_stuff(context, data):
self.assertEqual(len(capital_change_packets), 1)
self.assertEqual(
capital_change_packets[0],
{'date': pd.Timestamp('2006-01-06', tz='UTC'),
{'date': pd.Timestamp('2016-01-06', tz='UTC'),
'type': 'cash',
'target': 153000.0 if change_type == 'target' else None,
'delta': 50000.0})
@@ -2532,23 +2532,23 @@ def order_stuff(context, data):
self.assertEqual(
algo.capital_change_deltas,
{pd.Timestamp('2006-01-06', tz='UTC'): 50000.0}
{pd.Timestamp('2016-01-06', tz='UTC'): 50000.0}
)
@parameterized.expand([
('interday_target', [('2006-01-04', 2388.0)]),
('interday_delta', [('2006-01-04', 1000.0)]),
('intraday_target', [('2006-01-04 17:00', 2186.0),
('2006-01-04 18:00', 2806.0)]),
('intraday_delta', [('2006-01-04 17:00', 500.0),
('2006-01-04 18:00', 500.0)]),
('interday_target', [('2016-01-04', 2388.0)]),
('interday_delta', [('2016-01-04', 1000.0)]),
('intraday_target', [('2016-01-04 17:00', 2186.0),
('2016-01-04 18:00', 2806.0)]),
('intraday_delta', [('2016-01-04 17:00', 500.0),
('2016-01-04 18:00', 500.0)]),
])
def test_capital_changes_minute_mode_daily_emission(self, change, values):
change_loc, change_type = change.split('_')
sim_params = factory.create_simulation_parameters(
start=pd.Timestamp('2006-01-03', tz='UTC'),
end=pd.Timestamp('2006-01-05', tz='UTC'),
start=pd.Timestamp('2016-01-03', tz='UTC'),
end=pd.Timestamp('2016-01-05', tz='UTC'),
data_frequency='minute',
capital_base=1000.0
)
@@ -2692,29 +2692,29 @@ def order_stuff(context, data):
if change_loc == 'interday':
self.assertEqual(
algo.capital_change_deltas,
{pd.Timestamp('2006-01-04', tz='UTC'): 1000.0}
{pd.Timestamp('2016-01-04', tz='UTC'): 1000.0}
)
else:
self.assertEqual(
algo.capital_change_deltas,
{pd.Timestamp('2006-01-04 17:00', tz='UTC'): 500.0,
pd.Timestamp('2006-01-04 18:00', tz='UTC'): 500.0}
{pd.Timestamp('2016-01-04 17:00', tz='UTC'): 500.0,
pd.Timestamp('2016-01-04 18:00', tz='UTC'): 500.0}
)
@parameterized.expand([
('interday_target', [('2006-01-04', 2388.0)]),
('interday_delta', [('2006-01-04', 1000.0)]),
('intraday_target', [('2006-01-04 17:00', 2186.0),
('2006-01-04 18:00', 2806.0)]),
('intraday_delta', [('2006-01-04 17:00', 500.0),
('2006-01-04 18:00', 500.0)]),
('interday_target', [('2016-01-04', 2388.0)]),
('interday_delta', [('2016-01-04', 1000.0)]),
('intraday_target', [('2016-01-04 17:00', 2186.0),
('2016-01-04 18:00', 2806.0)]),
('intraday_delta', [('2016-01-04 17:00', 500.0),
('2016-01-04 18:00', 500.0)]),
])
def test_capital_changes_minute_mode_minute_emission(self, change, values):
change_loc, change_type = change.split('_')
sim_params = factory.create_simulation_parameters(
start=pd.Timestamp('2006-01-03', tz='UTC'),
end=pd.Timestamp('2006-01-05', tz='UTC'),
start=pd.Timestamp('2016-01-03', tz='UTC'),
end=pd.Timestamp('2016-01-05', tz='UTC'),
data_frequency='minute',
emission_rate='minute',
capital_base=1000.0
@@ -2933,20 +2933,20 @@ def order_stuff(context, data):
if change_loc == 'interday':
self.assertEqual(
algo.capital_change_deltas,
{pd.Timestamp('2006-01-04', tz='UTC'): 1000.0}
{pd.Timestamp('2016-01-04', tz='UTC'): 1000.0}
)
else:
self.assertEqual(
algo.capital_change_deltas,
{pd.Timestamp('2006-01-04 17:00', tz='UTC'): 500.0,
pd.Timestamp('2006-01-04 18:00', tz='UTC'): 500.0}
{pd.Timestamp('2016-01-04 17:00', tz='UTC'): 500.0,
pd.Timestamp('2016-01-04 18:00', tz='UTC'): 500.0}
)
class TestGetDatetime(WithLogger,
WithSimParams,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
SIM_PARAMS_DATA_FREQUENCY = 'minute'
START_DATE = to_utc('2014-01-02 9:31')
END_DATE = to_utc('2014-01-03 9:31')
@@ -2994,7 +2994,7 @@ class TestGetDatetime(WithLogger,
self.assertFalse(algo.first_bar)
class TestTradingControls(WithSimParams, WithDataPortal, ZiplineTestCase):
class TestTradingControls(WithSimParams, WithDataPortal, CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-01-06', tz='utc')
@@ -3468,7 +3468,7 @@ class TestTradingControls(WithSimParams, WithDataPortal, ZiplineTestCase):
algo.run(data_portal)
class TestAccountControls(WithDataPortal, WithSimParams, ZiplineTestCase):
class TestAccountControls(WithDataPortal, WithSimParams, CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-01-06', tz='utc')
@@ -3616,7 +3616,7 @@ class TestAccountControls(WithDataPortal, WithSimParams, ZiplineTestCase):
# format(i, actual_position, expected_positions[i]))
class TestFutureFlip(WithDataPortal, WithSimParams, ZiplineTestCase):
class TestFutureFlip(WithDataPortal, WithSimParams, CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-09', tz='utc')
END_DATE = pd.Timestamp('2006-01-10', tz='utc')
sid, = ASSET_FINDER_EQUITY_SIDS = (1,)
@@ -3677,7 +3677,7 @@ class TestFutureFlip(WithDataPortal, WithSimParams, ZiplineTestCase):
format(i, actual_position, expected_positions[i]))
class TestFuturesAlgo(WithDataPortal, WithSimParams, ZiplineTestCase):
class TestFuturesAlgo(WithDataPortal, WithSimParams, CatalystTestCase):
START_DATE = pd.Timestamp('2016-01-06', tz='utc')
END_DATE = pd.Timestamp('2016-01-07', tz='utc')
FUTURE_MINUTE_BAR_START_DATE = pd.Timestamp('2016-01-05', tz='UTC')
@@ -3879,7 +3879,7 @@ class TestFuturesAlgo(WithDataPortal, WithSimParams, ZiplineTestCase):
self.assertEqual(txn['price'], expected_price)
class TestTradingAlgorithm(WithTradingEnvironment, ZiplineTestCase):
class TestTradingAlgorithm(WithTradingEnvironment, CatalystTestCase):
def test_analyze_called(self):
self.perf_ref = None
@@ -3907,7 +3907,7 @@ class TestTradingAlgorithm(WithTradingEnvironment, ZiplineTestCase):
class TestOrderCancelation(WithDataPortal,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2016-01-05', tz='utc')
END_DATE = pd.Timestamp('2016-01-07', tz='utc')
@@ -4100,7 +4100,7 @@ class TestOrderCancelation(WithDataPortal,
self.assertFalse(log_catcher.has_warnings)
class TestEquityAutoClose(WithTradingEnvironment, WithTmpDir, ZiplineTestCase):
class TestEquityAutoClose(WithTradingEnvironment, WithTmpDir, CatalystTestCase):
"""
Tests if delisted equities are properly removed from a portfolio holding
positions in said equities.
@@ -4661,7 +4661,7 @@ class TestEquityAutoClose(WithTradingEnvironment, WithTmpDir, ZiplineTestCase):
)
class TestOrderAfterDelist(WithTradingEnvironment, ZiplineTestCase):
class TestOrderAfterDelist(WithTradingEnvironment, CatalystTestCase):
start = pd.Timestamp('2016-01-05', tz='utc')
day_1 = pd.Timestamp('2016-01-06', tz='utc')
day_4 = pd.Timestamp('2016-01-11', tz='utc')
@@ -4756,7 +4756,7 @@ class TestOrderAfterDelist(WithTradingEnvironment, ZiplineTestCase):
self.assertEqual(expected_message, w.message)
class AlgoInputValidationTestCase(WithTradingEnvironment, ZiplineTestCase):
class AlgoInputValidationTestCase(WithTradingEnvironment, CatalystTestCase):
def test_reject_passing_both_api_methods_and_script(self):
script = dedent(
@@ -4787,7 +4787,7 @@ class AlgoInputValidationTestCase(WithTradingEnvironment, ZiplineTestCase):
)
class TestPanelData(WithTradingEnvironment, ZiplineTestCase):
class TestPanelData(WithTradingEnvironment, CatalystTestCase):
@parameterized.expand([
('daily',
+2 -2
View File
@@ -17,7 +17,7 @@ from catalyst.testing.fixtures import (
WithCreateBarData,
WithDataPortal,
WithSimParams,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.catalyst_warnings import ZiplineDeprecationWarning
@@ -133,7 +133,7 @@ def handle_data(context, data):
class TestAPIShim(WithCreateBarData,
WithDataPortal,
WithSimParams,
ZiplineTestCase,
CatalystTestCase,
):
START_DATE = pd.Timestamp("2016-01-05", tz='UTC')
END_DATE = pd.Timestamp("2016-01-28", tz='UTC')
+5 -5
View File
@@ -80,7 +80,7 @@ from catalyst.testing import (
from catalyst.testing.predicates import assert_equal
from catalyst.testing.fixtures import (
WithAssetFinder,
ZiplineTestCase,
CatalystTestCase,
WithTradingCalendars,
)
from catalyst.utils.range import range
@@ -345,7 +345,7 @@ class AssetTestCase(TestCase):
'a' < self.asset3
class TestFuture(WithAssetFinder, ZiplineTestCase):
class TestFuture(WithAssetFinder, CatalystTestCase):
@classmethod
def make_futures_info(cls):
return pd.DataFrame.from_dict(
@@ -458,7 +458,7 @@ class TestFuture(WithAssetFinder, ZiplineTestCase):
TestFuture.asset_finder.lookup_future_symbol('XXX99')
class AssetFinderTestCase(WithTradingCalendars, ZiplineTestCase):
class AssetFinderTestCase(WithTradingCalendars, CatalystTestCase):
asset_finder_type = AssetFinder
def write_assets(self, **kwargs):
@@ -1395,7 +1395,7 @@ class AssetFinderTestCase(WithTradingCalendars, ZiplineTestCase):
)
class TestAssetDBVersioning(ZiplineTestCase):
class TestAssetDBVersioning(CatalystTestCase):
def init_instance_fixtures(self):
super(TestAssetDBVersioning, self).init_instance_fixtures()
@@ -1533,7 +1533,7 @@ class TestAssetDBVersioning(ZiplineTestCase):
assert_equal(expected_data, actual_data)
class TestVectorizedSymbolLookup(WithAssetFinder, ZiplineTestCase):
class TestVectorizedSymbolLookup(WithAssetFinder, CatalystTestCase):
@classmethod
def make_equity_info(cls):
+4 -4
View File
@@ -38,7 +38,7 @@ from catalyst.testing import (
from catalyst.testing.fixtures import (
WithCreateBarData,
WithDataPortal,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.calendars import get_calendar
from catalyst.utils.calendars.trading_calendar import days_at_time
@@ -108,7 +108,7 @@ class WithBarDataChecks(object):
class TestMinuteBarData(WithCreateBarData,
WithBarDataChecks,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2016-01-05', tz='UTC')
END_DATE = ASSET_FINDER_EQUITY_END_DATE = pd.Timestamp(
'2016-01-07',
@@ -730,7 +730,7 @@ class TestMinuteBarData(WithCreateBarData,
class TestMinuteBarDataFuturesCalendar(WithCreateBarData,
WithBarDataChecks,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2016-01-05', tz='UTC')
END_DATE = ASSET_FINDER_EQUITY_END_DATE = pd.Timestamp(
@@ -857,7 +857,7 @@ class TestMinuteBarDataFuturesCalendar(WithCreateBarData,
class TestDailyBarData(WithCreateBarData,
WithBarDataChecks,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2016-01-05', tz='UTC')
END_DATE = ASSET_FINDER_EQUITY_END_DATE = pd.Timestamp(
'2016-01-11',
+2 -2
View File
@@ -32,12 +32,12 @@ from catalyst.testing.fixtures import (
WithDataPortal,
WithSimParams,
WithTradingCalendars,
ZiplineTestCase,
CatalystTestCase,
)
class TestBenchmark(WithDataPortal, WithSimParams, WithTradingCalendars,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-12-29', tz='utc')
+3 -3
View File
@@ -41,7 +41,7 @@ from catalyst.testing.fixtures import (
WithDataPortal,
WithBcolzFutureMinuteBarReader,
WithSimParams,
ZiplineTestCase,
CatalystTestCase,
)
@@ -49,7 +49,7 @@ class ContinuousFuturesTestCase(WithCreateBarData,
WithDataPortal,
WithSimParams,
WithBcolzFutureMinuteBarReader,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2015-01-05', tz='UTC')
END_DATE = pd.Timestamp('2016-10-19', tz='UTC')
@@ -1285,7 +1285,7 @@ def record_current_contract(algo, data):
class OrderedContractsTestCase(WithAssetFinder,
ZiplineTestCase):
CatalystTestCase):
@classmethod
def make_root_symbols_info(self):
+2 -2
View File
@@ -27,7 +27,7 @@ from catalyst.data.minute_bars import (
)
from catalyst.testing import parameter_space
from catalyst.testing.fixtures import (
ZiplineTestCase,
CatalystTestCase,
WithTradingSessions,
WithDataPortal,
alias,
@@ -38,7 +38,7 @@ from catalyst.utils.numpy_utils import float64_dtype
class DataPortalTestBase(WithDataPortal,
WithTradingSessions,
ZiplineTestCase):
CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = (1, 2)
START_DATE = pd.Timestamp('2016-08-01')
+2 -2
View File
@@ -22,7 +22,7 @@ import pandas as pd
from catalyst import examples
from catalyst.data.bundles import register, unregister
from catalyst.testing import test_resource_path
from catalyst.testing.fixtures import WithTmpDir, ZiplineTestCase
from catalyst.testing.fixtures import WithTmpDir, CatalystTestCase
from catalyst.testing.predicates import assert_equal
from catalyst.utils.cache import dataframe_cache
from catalyst.utils.paths import update_modified_time
@@ -34,7 +34,7 @@ _multiprocess_can_split_ = False
matplotlib.use('Agg')
class ExamplesTests(WithTmpDir, ZiplineTestCase):
class ExamplesTests(WithTmpDir, CatalystTestCase):
# some columns contain values with unique ids that will not be the same
@classmethod
+2 -2
View File
@@ -22,14 +22,14 @@ from catalyst.test_algorithms import (
from catalyst.testing.fixtures import (
WithDataPortal,
WithSimParams,
ZiplineTestCase,
CatalystTestCase,
)
DEFAULT_TIMEOUT = 15 # seconds
EXTENDED_TIMEOUT = 90
class ExceptionTestCase(WithDataPortal, WithSimParams, ZiplineTestCase):
class ExceptionTestCase(WithDataPortal, WithSimParams, CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
START_DATE = pd.Timestamp('2006-01-07', tz='utc')
+61 -61
View File
@@ -24,11 +24,11 @@ from catalyst.finance.execution import (
)
from catalyst.testing.fixtures import (
WithLogger,
ZiplineTestCase,
CatalystTestCase,
)
class ExecutionStyleTestCase(WithLogger, ZiplineTestCase):
class ExecutionStyleTestCase(WithLogger, CatalystTestCase):
"""
Tests for catalyst ExecutionStyle classes.
"""
@@ -96,62 +96,62 @@ class ExecutionStyleTestCase(WithLogger, ZiplineTestCase):
self.assertEqual(style.get_stop_price(True), None)
self.assertEqual(style.get_stop_price(False), None)
@parameterized.expand(EXPECTED_PRICE_ROUNDING)
def test_limit_order_prices(self,
price,
expected_limit_buy_or_stop_sell,
expected_limit_sell_or_stop_buy):
"""
Test price getters for the LimitOrder class.
"""
style = LimitOrder(price)
self.assertEqual(expected_limit_buy_or_stop_sell,
style.get_limit_price(True))
self.assertEqual(expected_limit_sell_or_stop_buy,
style.get_limit_price(False))
self.assertEqual(None, style.get_stop_price(True))
self.assertEqual(None, style.get_stop_price(False))
@parameterized.expand(EXPECTED_PRICE_ROUNDING)
def test_stop_order_prices(self,
price,
expected_limit_buy_or_stop_sell,
expected_limit_sell_or_stop_buy):
"""
Test price getters for StopOrder class. Note that the expected rounding
direction for stop prices is the reverse of that for limit prices.
"""
style = StopOrder(price)
self.assertEqual(None, style.get_limit_price(False))
self.assertEqual(None, style.get_limit_price(True))
self.assertEqual(expected_limit_buy_or_stop_sell,
style.get_stop_price(False))
self.assertEqual(expected_limit_sell_or_stop_buy,
style.get_stop_price(True))
@parameterized.expand(EXPECTED_PRICE_ROUNDING)
def test_stop_limit_order_prices(self,
price,
expected_limit_buy_or_stop_sell,
expected_limit_sell_or_stop_buy):
"""
Test price getters for StopLimitOrder class. Note that the expected
rounding direction for stop prices is the reverse of that for limit
prices.
"""
style = StopLimitOrder(price, price + 1)
self.assertEqual(expected_limit_buy_or_stop_sell,
style.get_limit_price(True))
self.assertEqual(expected_limit_sell_or_stop_buy,
style.get_limit_price(False))
self.assertEqual(expected_limit_buy_or_stop_sell + 1,
style.get_stop_price(False))
self.assertEqual(expected_limit_sell_or_stop_buy + 1,
style.get_stop_price(True))
# @parameterized.expand(EXPECTED_PRICE_ROUNDING)
# def test_limit_order_prices(self,
# price,
# expected_limit_buy_or_stop_sell,
# expected_limit_sell_or_stop_buy):
# """
# Test price getters for the LimitOrder class.
# """
# style = LimitOrder()
#
# # self.assertEqual(expected_limit_buy_or_stop_sell,
# # style.get_limit_price(True))
# # self.assertEqual(expected_limit_sell_or_stop_buy,
# # style.get_limit_price(False))
#
# self.assertEqual(None, style.get_stop_price(True))
# self.assertEqual(None, style.get_stop_price(False))
#
# # @parameterized.expand(EXPECTED_PRICE_ROUNDING)
# def test_stop_order_prices(self,
# price,
# expected_limit_buy_or_stop_sell,
# expected_limit_sell_or_stop_buy):
# """
# Test price getters for StopOrder class. Note that the expected rounding
# direction for stop prices is the reverse of that for limit prices.
# """
# style = StopOrder(price)
#
# self.assertEqual(None, style.get_limit_price(False))
# self.assertEqual(None, style.get_limit_price(True))
#
# # self.assertEqual(expected_limit_buy_or_stop_sell,
# # style.get_stop_price(False))
# # self.assertEqual(expected_limit_sell_or_stop_buy,
# # style.get_stop_price(True))
#
# # @parameterized.expand(EXPECTED_PRICE_ROUNDING)
# def test_stop_limit_order_prices(self,
# price,
# expected_limit_buy_or_stop_sell,
# expected_limit_sell_or_stop_buy):
# """
# Test price getters for StopLimitOrder class. Note that the expected
# rounding direction for stop prices is the reverse of that for limit
# prices.
# """
#
# style = StopLimitOrder(price, price + 1)
#
# self.assertEqual(expected_limit_buy_or_stop_sell,
# style.get_limit_price(True))
# self.assertEqual(expected_limit_sell_or_stop_buy,
# style.get_limit_price(False))
#
# self.assertEqual(expected_limit_buy_or_stop_sell + 1,
# style.get_stop_price(False))
# self.assertEqual(expected_limit_sell_or_stop_buy + 1,
# style.get_stop_price(True))
+2 -2
View File
@@ -26,7 +26,7 @@ from catalyst.testing import FetcherDataPortal
from catalyst.testing.fixtures import (
WithResponses,
WithSimParams,
ZiplineTestCase,
CatalystTestCase,
)
from .resources.fetcher_inputs.fetcher_test_data import (
AAPL_CSV_DATA,
@@ -45,7 +45,7 @@ from .resources.fetcher_inputs.fetcher_test_data import (
class FetcherTestCase(WithResponses,
WithSimParams,
ZiplineTestCase):
CatalystTestCase):
@classmethod
def make_equity_info(cls):
+7 -7
View File
@@ -46,7 +46,7 @@ from catalyst.testing import (
from catalyst.testing.fixtures import (
WithLogger,
WithTradingEnvironment,
ZiplineTestCase,
CatalystTestCase,
)
import catalyst.utils.factory as factory
@@ -59,10 +59,10 @@ _multiprocess_can_split_ = False
class FinanceTestCase(WithLogger,
WithTradingEnvironment,
ZiplineTestCase):
CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = 1, 2, 133
start = START_DATE = pd.Timestamp('2006-01-01', tz='utc')
end = END_DATE = pd.Timestamp('2006-12-31', tz='utc')
start = START_DATE = pd.Timestamp('2016-01-01', tz='utc')
end = END_DATE = pd.Timestamp('2016-12-31', tz='utc')
def init_instance_fixtures(self):
super(FinanceTestCase, self).init_instance_fixtures()
@@ -236,7 +236,7 @@ class FinanceTestCase(WithLogger,
data_portal = DataPortal(
env.asset_finder, self.trading_calendar,
first_trading_day=equity_minute_reader.first_trading_day,
equity_minute_reader=equity_minute_reader,
minute_reader=equity_minute_reader,
)
else:
sim_params = factory.create_simulation_parameters(
@@ -267,7 +267,7 @@ class FinanceTestCase(WithLogger,
data_portal = DataPortal(
env.asset_finder, self.trading_calendar,
first_trading_day=equity_daily_reader.first_trading_day,
equity_daily_reader=equity_daily_reader,
daily_reader=equity_daily_reader,
)
if "default_slippage" not in params or \
@@ -403,7 +403,7 @@ class FinanceTestCase(WithLogger,
class TradingEnvironmentTestCase(WithLogger,
WithTradingEnvironment,
ZiplineTestCase):
CatalystTestCase):
"""
Tests for date management utilities in catalyst.finance.trading.
"""
+3 -3
View File
@@ -37,7 +37,7 @@ from catalyst.testing import (
from catalyst.testing.fixtures import (
WithCreateBarData,
WithDataPortal,
ZiplineTestCase,
CatalystTestCase,
alias,
)
@@ -530,7 +530,7 @@ MINUTE_FIELD_INFO = {
}
class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
class MinuteEquityHistoryTestCase(WithHistory, CatalystTestCase):
EQUITY_DAILY_BAR_SOURCE_FROM_MINUTE = True
DATA_PORTAL_FIRST_TRADING_DAY = alias('TRADING_START_DT')
@@ -1598,7 +1598,7 @@ class NoPrefetchMinuteEquityHistoryTestCase(MinuteEquityHistoryTestCase):
DATA_PORTAL_DAILY_HISTORY_PREFETCH = 0
class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
class DailyEquityHistoryTestCase(WithHistory, CatalystTestCase):
CREATE_BARDATA_DATA_FREQUENCY = 'daily'
@classmethod
+2 -2
View File
@@ -6,7 +6,7 @@ import numpy as np
from toolz import take
from catalyst.lib.labelarray import LabelArray
from catalyst.testing import check_arrays, parameter_space, ZiplineTestCase
from catalyst.testing import check_arrays, parameter_space, CatalystTestCase
from catalyst.testing.predicates import assert_equal
from catalyst.utils.compat import unicode
@@ -31,7 +31,7 @@ def all_ufuncs():
return (f for f in vars(np).values() if isinstance(f, ufunc_type))
class LabelArrayTestCase(ZiplineTestCase):
class LabelArrayTestCase(CatalystTestCase):
@classmethod
def init_class_fixtures(cls):
+3 -3
View File
@@ -22,7 +22,7 @@ from catalyst.data.us_equity_pricing import PanelBarReader
from catalyst.testing import ExplodingObject
from catalyst.testing.fixtures import (
WithAssetFinder,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.calendars import get_calendar
@@ -99,7 +99,7 @@ class WithPanelBarReader(WithAssetFinder):
class TestPanelDailyBarReader(WithPanelBarReader,
ZiplineTestCase):
CatalystTestCase):
FREQUENCY = 'daily'
@@ -110,7 +110,7 @@ class TestPanelDailyBarReader(WithPanelBarReader,
class TestPanelMinuteBarReader(WithPanelBarReader,
ZiplineTestCase):
CatalystTestCase):
FREQUENCY = 'minute'
+5 -5
View File
@@ -57,7 +57,7 @@ from catalyst.testing.fixtures import (
WithSimParams,
WithTmpDir,
WithTradingEnvironment,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils.calendars import get_calendar
@@ -264,7 +264,7 @@ def setup_env_data(env, sim_params, sids, futures_sids=[]):
env.write_data(futures_data=futures_data)
class TestSplitPerformance(WithSimParams, WithTmpDir, ZiplineTestCase):
class TestSplitPerformance(WithSimParams, WithTmpDir, CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-01-04', tz='utc')
SIM_PARAMS_CAPITAL_BASE = 10e3
@@ -402,7 +402,7 @@ class TestSplitPerformance(WithSimParams, WithTmpDir, ZiplineTestCase):
class TestDividendPerformance(WithSimParams,
WithInstanceTmpDir,
ZiplineTestCase):
CatalystTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-01-10', tz='utc')
ASSET_FINDER_EQUITY_SIDS = 1, 2
@@ -1030,7 +1030,7 @@ class TestDividendPerformanceHolidayStyle(TestDividendPerformance):
class TestPositionPerformance(WithInstanceTmpDir,
WithTradingEnvironment,
ZiplineTestCase):
CatalystTestCase):
def create_environment_stuff(self,
num_days=4,
@@ -1951,7 +1951,7 @@ shares in position"
class TestPositionTracker(WithTradingEnvironment,
WithInstanceTmpDir,
ZiplineTestCase):
CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = 1, 2
@classmethod
+2 -2
View File
@@ -18,7 +18,7 @@ from catalyst.finance.asset_restrictions import (
from catalyst.testing import parameter_space
from catalyst.testing.fixtures import (
WithDataPortal,
ZiplineTestCase,
CatalystTestCase,
)
@@ -31,7 +31,7 @@ ALLOWED = RESTRICTION_STATES.ALLOWED
MINUTE = pd.Timedelta(minutes=1)
class RestrictionsTestCase(WithDataPortal, ZiplineTestCase):
class RestrictionsTestCase(WithDataPortal, CatalystTestCase):
ASSET_FINDER_EQUITY_SIDS = 1, 2, 3
+2 -2
View File
@@ -16,7 +16,7 @@ from catalyst.testing import (
from catalyst.testing.fixtures import (
WithLogger,
WithTradingEnvironment,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils import factory
from catalyst.utils.security_list import (
@@ -84,7 +84,7 @@ class IterateRLAlgo(TradingAlgorithm):
class SecurityListTestCase(WithLogger,
WithTradingEnvironment,
ZiplineTestCase):
CatalystTestCase):
@classmethod
def init_class_fixtures(cls):
+2 -2
View File
@@ -19,7 +19,7 @@ from catalyst.testing import (
from catalyst.testing.fixtures import (
WithConstantEquityMinuteBarData,
WithDataPortal,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.testing.slippage import TestingSlippage
from catalyst.utils.numpy_utils import bool_dtype
@@ -123,7 +123,7 @@ class TestMakeBooleanArray(TestCase):
class TestTestingSlippage(WithConstantEquityMinuteBarData,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
ASSET_FINDER_EQUITY_SYMBOLS = ('A',)
ASSET_FINDER_EQUITY_SIDS = (1,)
+3 -3
View File
@@ -31,7 +31,7 @@ from catalyst.testing.fixtures import (
WithDataPortal,
WithSimParams,
WithTradingEnvironment,
ZiplineTestCase,
CatalystTestCase,
)
from catalyst.utils import factory
from catalyst.testing.core import FakeDataPortal
@@ -53,7 +53,7 @@ class BeforeTradingAlgorithm(TradingAlgorithm):
FREQUENCIES = {'daily': 0, 'minute': 1} # daily is less frequent than minute
class TestTradeSimulation(WithTradingEnvironment, ZiplineTestCase):
class TestTradeSimulation(WithTradingEnvironment, CatalystTestCase):
def fake_minutely_benchmark(self, dt):
return 0.01
@@ -115,7 +115,7 @@ class BeforeTradingStartsOnlyClock(object):
class TestBeforeTradingStartSimulationDt(WithSimParams,
WithDataPortal,
ZiplineTestCase):
CatalystTestCase):
def test_bts_simulation_dt(self):
code = """
+2 -2
View File
@@ -1,7 +1,7 @@
from pandas import Timestamp
from nose_parameterized import parameterized
from catalyst.testing import ZiplineTestCase
from catalyst.testing import CatalystTestCase
from catalyst.utils.calendars import get_calendar
from catalyst.utils.date_utils import compute_date_range_chunks
@@ -13,7 +13,7 @@ def T(s):
return Timestamp(s, tz='UTC')
class TestDateUtils(ZiplineTestCase):
class TestDateUtils(CatalystTestCase):
@classmethod
def init_class_fixtures(cls):
+3 -3
View File
@@ -1,4 +1,4 @@
from catalyst.testing.fixtures import ZiplineTestCase
from catalyst.testing.fixtures import CatalystTestCase
from catalyst.testing.predicates import (
assert_equal,
assert_is,
@@ -31,7 +31,7 @@ class D(object):
return 'D.delegate'
class ComposeTypesTestCase(ZiplineTestCase):
class ComposeTypesTestCase(CatalystTestCase):
def test_identity(self):
assert_is(
@@ -67,7 +67,7 @@ class N(type):
return super(N, mcls).__new__(mcls, name, bases, dict_)
class WithMetaclassesTestCase(ZiplineTestCase):
class WithMetaclassesTestCase(CatalystTestCase):
def test_with_metaclasses_no_subclasses(self):
class E(with_metaclasses((M, N))):
pass
+3 -3
View File
@@ -3,7 +3,7 @@ Tests for catalyst/utils/pandas_utils.py
"""
import pandas as pd
from catalyst.testing import parameter_space, ZiplineTestCase
from catalyst.testing import parameter_space, CatalystTestCase
from catalyst.testing.predicates import assert_equal
from catalyst.utils.pandas_utils import (
categorical_df_concat,
@@ -11,7 +11,7 @@ from catalyst.utils.pandas_utils import (
)
class TestNearestUnequalElements(ZiplineTestCase):
class TestNearestUnequalElements(CatalystTestCase):
@parameter_space(tz=['UTC', 'US/Eastern'], __fail_fast=True)
def test_nearest_unequal_elements(self, tz):
@@ -86,7 +86,7 @@ class TestNearestUnequalElements(ZiplineTestCase):
)
class TestCatDFConcat(ZiplineTestCase):
class TestCatDFConcat(CatalystTestCase):
def test_categorical_df_concat(self):
+2 -2
View File
@@ -1,8 +1,8 @@
from catalyst.testing import ZiplineTestCase
from catalyst.testing import CatalystTestCase
from catalyst.utils.sharedoc import copydoc
class TestSharedoc(ZiplineTestCase):
class TestSharedoc(CatalystTestCase):
def test_copydoc(self):
def original_docstring_function():