mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-03 11:43:23 +08:00
216 lines
6.8 KiB
Python
216 lines
6.8 KiB
Python
import json
|
|
import os
|
|
import random
|
|
from logging import Logger, WARNING
|
|
from time import sleep
|
|
|
|
import pandas as pd
|
|
from catalyst.assets._assets import TradingPair
|
|
from logbook import TestHandler
|
|
|
|
from catalyst.exchange.exchange_errors import ExchangeRequestError
|
|
from catalyst.exchange.exchange_execution import ExchangeLimitOrder
|
|
from catalyst.exchange.utils.exchange_utils import get_exchange_folder
|
|
from catalyst.exchange.utils.test_utils import select_random_exchanges, \
|
|
handle_exchange_error, select_random_assets
|
|
from catalyst.testing import ZiplineTestCase
|
|
from catalyst.testing.fixtures import WithLogger
|
|
from catalyst.exchange.utils.factory import get_exchanges, get_exchange
|
|
|
|
log = Logger('TestSuiteExchange')
|
|
|
|
|
|
class TestSuiteExchange(WithLogger, ZiplineTestCase):
|
|
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:
|
|
print(
|
|
're-trying an exchange request {} {}'.format(
|
|
exchange.name, attempts
|
|
)
|
|
)
|
|
self._test_markets_exchange(exchange, attempts + 1)
|
|
|
|
except Exception as e:
|
|
handle_exchange_error(exchange, e)
|
|
|
|
return assets
|
|
|
|
def test_markets(self):
|
|
population = 3
|
|
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, 'whitelist.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_tickers(self):
|
|
exchange_population = 3
|
|
asset_population = 15
|
|
|
|
# exchanges = select_random_exchanges(
|
|
# exchange_population,
|
|
# features=['fetchTickers'],
|
|
# ) # Type: list[Exchange]
|
|
exchanges = list(get_exchanges(['binance']).values())
|
|
for exchange in exchanges:
|
|
exchange.init()
|
|
|
|
if exchange.assets and len(exchange.assets) >= asset_population:
|
|
assets = select_random_assets(
|
|
exchange.assets, asset_population
|
|
)
|
|
tickers = exchange.tickers(assets)
|
|
|
|
assert len(tickers) == asset_population
|
|
|
|
else:
|
|
print(
|
|
'skipping exchange without assets {}'.format(exchange.name)
|
|
)
|
|
exchange_population -= 1
|
|
pass
|
|
|
|
def test_candles(self):
|
|
exchange_population = 3
|
|
asset_population = 3
|
|
|
|
# exchanges = select_random_exchanges(
|
|
# population=exchange_population,
|
|
# features=['fetchOHLCV'],
|
|
# ) # Type: list[Exchange]
|
|
exchanges = list(get_exchanges(['binance']).values())
|
|
for exchange in exchanges:
|
|
exchange.init()
|
|
|
|
if exchange.assets and len(exchange.assets) >= asset_population:
|
|
frequencies = exchange.get_candle_frequencies()
|
|
freq = random.sample(frequencies, 1)[0]
|
|
|
|
bar_count = random.randint(1, 10)
|
|
end_dt = pd.Timestamp.utcnow().floor('1T')
|
|
dt_range = pd.date_range(
|
|
end=end_dt, periods=bar_count, freq=freq
|
|
)
|
|
assets = select_random_assets(
|
|
exchange.assets, asset_population
|
|
)
|
|
|
|
candles = exchange.get_candles(
|
|
freq=freq,
|
|
assets=assets,
|
|
bar_count=bar_count,
|
|
start_dt=dt_range[0],
|
|
)
|
|
|
|
assert len(candles) == asset_population
|
|
|
|
else:
|
|
print(
|
|
'skipping exchange without assets {}'.format(exchange.name)
|
|
)
|
|
exchange_population -= 1
|
|
pass
|
|
|
|
def test_orders(self):
|
|
population = 3
|
|
quote_currency = 'eth'
|
|
order_amount = 0.1
|
|
|
|
# exchanges = select_random_exchanges(
|
|
# population=population,
|
|
# features=['fetchOrder'],
|
|
# is_authenticated=True,
|
|
# base_currency=quote_currency,
|
|
# ) # Type: list[Exchange]
|
|
|
|
exchanges = [
|
|
get_exchange(
|
|
'binance',
|
|
base_currency=quote_currency,
|
|
must_authenticate=True,
|
|
)
|
|
]
|
|
log_catcher = TestHandler()
|
|
with log_catcher:
|
|
for exchange in exchanges:
|
|
exchange.init()
|
|
|
|
assets = exchange.get_assets(quote_currency=quote_currency)
|
|
asset = select_random_assets(assets, 1)[0]
|
|
self.assertIsInstance(asset, TradingPair)
|
|
|
|
tickers = exchange.tickers([asset])
|
|
price = tickers[asset]['last_price']
|
|
|
|
amount = order_amount / price
|
|
|
|
limit_price = price * 0.8
|
|
style = ExchangeLimitOrder(limit_price=limit_price)
|
|
|
|
order = exchange.order(
|
|
asset=asset,
|
|
amount=amount,
|
|
style=style,
|
|
)
|
|
sleep(1)
|
|
|
|
open_order = exchange.get_order(order.id, asset)
|
|
self.assertEqual(0, open_order.status)
|
|
|
|
exchange.cancel_order(open_order, asset)
|
|
sleep(1)
|
|
|
|
canceled_order = exchange.get_order(open_order.id, asset)
|
|
warnings = [record for record in log_catcher.records if
|
|
record.level == WARNING]
|
|
|
|
self.assertEqual(0, len(warnings))
|
|
self.assertEqual(2, canceled_order.status)
|
|
print(
|
|
'tested {exchange} / {symbol}, order: {order}'.format(
|
|
exchange=exchange.name,
|
|
symbol=asset.symbol,
|
|
order=order.id,
|
|
)
|
|
)
|
|
pass
|