BLD: testing markets for each exchange

This commit is contained in:
Frederic Fortier
2017-12-14 15:42:39 -05:00
parent 2a9fe7dbe2
commit 4740aebd7f
4 changed files with 189 additions and 20 deletions
+37 -18
View File
@@ -1,23 +1,26 @@
import talib
import pandas as pd
from logbook import Logger, INFO
from catalyst import run_algorithm
from catalyst.api import symbol, record
from catalyst.exchange.stats_utils import get_pretty_stats, \
extract_transactions
log = Logger('simple_loop', level=INFO)
def initialize(context):
print('initializing')
log.info('initializing')
context.asset = symbol('eth_btc')
context.base_price = None
def handle_data(context, data):
print('handling bar: {}'.format(data.current_dt))
log.info('handling bar: {}'.format(data.current_dt))
price = data.current(context.asset, 'close')
print('got price {price}'.format(price=price))
log.info('got price {price}'.format(price=price))
prices = data.history(
context.asset,
@@ -26,10 +29,10 @@ def handle_data(context, data):
frequency='30T'
)
last_traded = prices.index[-1]
print('last candle date: {}'.format(last_traded))
log.info('last candle date: {}'.format(last_traded))
rsi = talib.RSI(prices.values, timeperiod=14)[-1]
print('got rsi: {}'.format(rsi))
log.info('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.
@@ -51,7 +54,7 @@ def handle_data(context, data):
def analyze(context, perf):
import matplotlib.pyplot as plt
print('the stats: {}'.format(get_pretty_stats(perf)))
log.info('the stats: {}'.format(get_pretty_stats(perf)))
# The base currency of the algo exchange
base_currency = context.exchanges.values()[0].base_currency.upper()
@@ -111,15 +114,31 @@ def analyze(context, perf):
if __name__ == '__main__':
run_algorithm(
capital_base=1,
initialize=initialize,
handle_data=handle_data,
analyze=None,
exchange_name='poloniex',
live=True,
algo_namespace='simple_loop',
base_currency='eth',
live_graph=False,
simulate_orders=True
)
mode = 'backtest'
if mode == 'backtest':
run_algorithm(
capital_base=1,
initialize=initialize,
handle_data=handle_data,
analyze=None,
exchange_name='poloniex',
algo_namespace='simple_loop',
base_currency='eth',
data_frequency='minute',
start=pd.to_datetime('2017-9-1', utc=True),
end=pd.to_datetime('2017-12-1', utc=True),
)
else:
run_algorithm(
capital_base=1,
initialize=initialize,
handle_data=handle_data,
analyze=None,
exchange_name='binance',
live=True,
algo_namespace='simple_loop',
base_currency='eth',
live_graph=False,
simulate_orders=True
)
+10 -1
View File
@@ -71,8 +71,12 @@ class CCXT(Exchange):
self.bundle = ExchangeBundle(self.name)
self.markets = None
self._is_init = False
def init(self):
if self._is_init:
return
exchange_folder = get_exchange_folder(self.name)
filename = os.path.join(exchange_folder, 'cctx_markets.json')
@@ -97,12 +101,13 @@ class CCXT(Exchange):
self.markets = self.api.fetch_markets()
with open(filename, 'w+') as f:
json.dump(self.markets, f)
json.dump(self.markets, f, indent=4)
except ExchangeNotAvailable as e:
raise ExchangeRequestError(error=e)
self.load_assets()
self._is_init = True
@staticmethod
def find_exchanges(features=None):
@@ -408,6 +413,10 @@ class CCXT(Exchange):
self.assets = []
for market in self.markets:
if 'id' not in market:
log.warn('invalid market: {}'.format(market))
continue
asset_defs = self.get_asset_defs(market)
asset = None
+1 -1
View File
@@ -32,7 +32,7 @@ Test:
Fetch historical data for each market using the selected frequency
Assert:
- No error and not blank
- Date of each candle is consistent with the Catalyst desired pattern:
- Date of each candle is consistent with the Catalyst desired pattern,
- All candle start at fix intervals
- Last candle partial and forward looking from the end date
+141
View File
@@ -0,0 +1,141 @@
import json
import os
import random
import unittest
from logging import Logger
from time import sleep
import pandas as pd
from ccxt import AuthenticationError
from catalyst.exchange.exchange_errors import ExchangeRequestError
from catalyst.exchange.exchange_utils import get_exchange_folder
from catalyst.exchange.factory import find_exchanges
from catalyst.utils.paths import data_root
log = Logger('TestSuiteExchange')
def handle_exchange_error(exchange, e):
is_blacklist = False
if isinstance(e, AuthenticationError):
is_blacklist = True
elif isinstance(e, ValueError) or isinstance(e, ExchangeRequestError):
is_blacklist = True
else:
log.warn('unexpected error: {}'.format(e))
is_blacklist = True
if is_blacklist:
root = data_root()
filename = os.path.join(root, 'exchanges', 'blacklist.json')
if os.path.isfile(filename):
with open(filename) as handle:
try:
bl_data = json.load(handle)
except ValueError:
bl_data = dict()
else:
bl_data = dict()
if exchange.name not in bl_data:
bl_data[exchange.name] = '{}: {}'.format(e.__class__, e.message)
with open(filename, 'wt') as handle:
json.dump(bl_data, handle, indent=4)
def select_random_exchanges(population=3, features=None):
all_exchanges = find_exchanges(features)
if population is not None:
exchanges = random.sample(all_exchanges, population)
else:
exchanges = all_exchanges
return exchanges
def select_random_assets(exchange, population=3):
all_assets = exchange.assets
assets = random.sample(all_assets, population)
return assets
# TODO: convert to Nosetest
class TestSuiteExchange(unittest.TestCase):
def _test_markets_exchange(self, exchange, attempts=0):
assets = None
try:
exchange.init()
# Verify that the assets and markets are populated
if not exchange.markets:
raise ValueError(
'no markets found'
)
if not exchange.assets:
raise ValueError(
'no assets derived from markets'
)
assets = exchange.assets
except ExchangeRequestError as e:
sleep(5)
if attempts > 5:
handle_exchange_error(exchange, e)
else:
self._test_markets_exchange(exchange, attempts + 1)
except Exception as e:
handle_exchange_error(exchange, e)
return assets
def test_markets(self):
population = None
results = dict()
exchanges = select_random_exchanges(population) # Type: list[Exchange]
for exchange in exchanges:
assets = self._test_markets_exchange(exchange)
if assets is not None:
results[exchange.name] = len(assets)
folder = get_exchange_folder(exchange.name)
filename = os.path.join(folder, 'supported_assets.json')
symbols = [asset.symbol for asset in assets]
with open(filename, 'wt') as handle:
json.dump(symbols, handle, indent=4)
series = pd.Series(results)
print('the tested markets\n{}'.format(series))
if population is not None:
assert (len(results) == population)
pass
def test_ticker(self):
exchanges = select_random_exchanges(3) # Type: list[Exchange]
for exchange in exchanges:
exchange.init()
assets = select_random_assets(exchange, 3)
exchange.tickers()
pass
def test_candles(self):
pass
def test_orders(self):
pass