diff --git a/catalyst/exchange/ccxt/ccxt_exchange.py b/catalyst/exchange/ccxt/ccxt_exchange.py index af140468..0a48c0b4 100644 --- a/catalyst/exchange/ccxt/ccxt_exchange.py +++ b/catalyst/exchange/ccxt/ccxt_exchange.py @@ -570,7 +570,9 @@ class CCXT(Exchange): The Catalyst order object """ - if order_status['status'] == 'canceled': + if order_status['status'] == 'canceled' \ + or (order_status['status'] == 'closed' + and order_status['filled'] == 0): status = ORDER_STATUS.CANCELLED elif order_status['status'] == 'closed' and order_status['filled'] > 0: diff --git a/catalyst/exchange/exchange.py b/catalyst/exchange/exchange.py index 873ac29e..2b213226 100644 --- a/catalyst/exchange/exchange.py +++ b/catalyst/exchange/exchange.py @@ -149,7 +149,7 @@ class Exchange: def get_assets(self, symbols=None, data_frequency=None, is_exchange_symbol=False, - is_local=None): + is_local=None, quote_currency=None): """ The list of markets for the specified symbols. @@ -173,6 +173,14 @@ class Exchange: if symbols is None: # Make a distinct list of all symbols symbols = list(set([asset.symbol for asset in self.assets])) + + if quote_currency is not None: + for symbol in symbols[:]: + suffix = '_{}'.format(quote_currency.lower()) + + if not symbol.endswith(suffix): + symbols.remove(symbol) + is_exchange_symbol = False assets = [] diff --git a/catalyst/exchange/factory.py b/catalyst/exchange/factory.py index 4451aff0..6f7dd0ac 100644 --- a/catalyst/exchange/factory.py +++ b/catalyst/exchange/factory.py @@ -47,7 +47,8 @@ def get_exchanges(exchange_names): return exchanges -def find_exchanges(features=None, skip_blacklist=True): +def find_exchanges(features=None, skip_blacklist=True, is_authenticated=False, + base_currency=None): """ Find exchanges filtered by a list of feature. @@ -61,13 +62,18 @@ def find_exchanges(features=None, skip_blacklist=True): list[Exchange] """ - exchange_names = CCXT.find_exchanges(features) + exchange_names = CCXT.find_exchanges(features, is_authenticated) exchanges = [] for exchange_name in exchange_names: if skip_blacklist and is_blacklist(exchange_name): continue - exchanges.append(get_exchange(exchange_name, skip_init=True)) + exchange = get_exchange( + exchange_name=exchange_name, + skip_init=True, + base_currency=base_currency, + ) + exchanges.append(exchange) return exchanges diff --git a/tests/exchange/test_suite_exchange.py b/tests/exchange/test_suite_exchange.py index f41e7f20..75d5b660 100644 --- a/tests/exchange/test_suite_exchange.py +++ b/tests/exchange/test_suite_exchange.py @@ -1,7 +1,6 @@ import json import os import random -import unittest from logging import Logger from time import sleep @@ -9,6 +8,7 @@ import pandas as pd from ccxt import AuthenticationError from catalyst.exchange.exchange_errors import ExchangeRequestError +from catalyst.exchange.exchange_execution import ExchangeLimitOrder from catalyst.exchange.exchange_utils import get_exchange_folder from catalyst.exchange.factory import find_exchanges @@ -42,10 +42,18 @@ def handle_exchange_error(exchange, e): handle.write(message) -def select_random_exchanges(population=3, features=None): - all_exchanges = find_exchanges(features) +def select_random_exchanges(population=3, features=None, + is_authenticated=False, base_currency=None): + all_exchanges = find_exchanges( + features=features, + is_authenticated=is_authenticated, + base_currency=base_currency, + ) if population is not None: + if len(all_exchanges) < population: + population = len(all_exchanges) + exchanges = random.sample(all_exchanges, population) else: @@ -153,7 +161,7 @@ class TestSuiteExchange: asset_population = 3 exchanges = select_random_exchanges( - exchange_population, + population=exchange_population, features=['fetchOHLCV'], ) # Type: list[Exchange] for exchange in exchanges: @@ -190,4 +198,45 @@ class TestSuiteExchange: 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] + + for exchange in exchanges: + exchange.init() + + assets = exchange.get_assets(quote_currency=quote_currency) + asset = select_random_assets(assets, 1)[0] + assert asset + + 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) + assert open_order.status == 0 + + exchange.cancel_order(open_order, asset) + sleep(1) + + canceled_order, _ = exchange.get_order(open_order.id, asset) + assert canceled_order.status == 2 pass