mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-27 17:29:56 +08:00
BLD: testing markets for each exchange
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user