From 8b6a48633d2100ab0b4abdf5cf10bfcdf2cead2e Mon Sep 17 00:00:00 2001 From: fredfortier Date: Wed, 30 Aug 2017 17:09:13 -0400 Subject: [PATCH] Poloshing unit tests and finalizing Bittrex implementation --- catalyst/exchange/bitfinex/bitfinex.py | 7 +--- catalyst/exchange/bittrex/bittrex.py | 51 +++++++++++++++----------- catalyst/exchange/exchange.py | 10 +++-- catalyst/utils/run_algo.py | 9 +++++ tests/exchange/test_bittrex.py | 2 + 5 files changed, 49 insertions(+), 30 deletions(-) diff --git a/catalyst/exchange/bitfinex/bitfinex.py b/catalyst/exchange/bitfinex/bitfinex.py index cbecfa9c..2ca0b816 100644 --- a/catalyst/exchange/bitfinex/bitfinex.py +++ b/catalyst/exchange/bitfinex/bitfinex.py @@ -210,10 +210,6 @@ class Bitfinex(Exchange): return account - @property - def positions(self): - return self.portfolio.positions - @property def time_skew(self): # TODO: research the time skew conditions @@ -387,9 +383,8 @@ class Bitfinex(Exchange): limit=style.get_limit_price(is_buy), id=order_id ) - self.portfolio.create_order(order) - return order_id + return order def get_open_orders(self, asset=None): """Retrieve all of the current open orders. diff --git a/catalyst/exchange/bittrex/bittrex.py b/catalyst/exchange/bittrex/bittrex.py index b1df213e..c9093b16 100644 --- a/catalyst/exchange/bittrex/bittrex.py +++ b/catalyst/exchange/bittrex/bittrex.py @@ -1,9 +1,7 @@ import json import pandas as pd -import pytz from catalyst.assets._assets import TradingPair -from catalyst.finance.order import Order, ORDER_STATUS from logbook import Logger from six.moves import urllib @@ -13,6 +11,7 @@ from catalyst.exchange.exchange_errors import InvalidHistoryFrequencyError, \ ExchangeRequestError, InvalidOrderStyle, OrderNotFound, OrderCancelError, \ CreateOrderError from catalyst.finance.execution import LimitOrder, StopLimitOrder +from catalyst.finance.order import Order, ORDER_STATUS log = Logger('Bittrex') @@ -33,17 +32,10 @@ class Bittrex(Exchange): def account(self): pass - @property - def portfolio(self): - pass - - @property - def positions(self): - pass - @property def time_skew(self): - pass + # TODO: research the time skew conditions + return pd.Timedelta('0s') def sanitize_curency_symbol(self, exchange_symbol): """ @@ -102,26 +94,42 @@ class Bittrex(Exchange): price = style.get_limit_price(is_buy) try: if is_buy: - order = self.api.buylimit(exchange_symbol, amount, price) + order_status = self.api.buylimit(exchange_symbol, amount, price) else: - order = self.api.selllimit(exchange_symbol, amount, price) + order_status = self.api.selllimit(exchange_symbol, amount, price) except Exception as e: raise ExchangeRequestError(error=e) - if 'uuid' in order: - return order['uuid'] + if 'uuid' in order_status: + order_id = order_status['uuid'] + 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 else: - raise CreateOrderError(exchange=self.name, error=order) + raise CreateOrderError(exchange=self.name, error=order_status) else: raise InvalidOrderStyle(exchange=self.name, style=style.__class__.__name__) def get_open_orders(self, asset): - pass + symbol = self.get_symbol(asset) + try: + open_orders = self.api.getopenorders(symbol) + except Exception as e: + raise ExchangeRequestError(error=e) - def open_orders(self): - log.info('retrieving open orders') - pass + orders = list() + for order_status in open_orders: + order = self._create_order(order_status) + orders.append(order) + + return orders def _create_order(self, order_status): log.info( @@ -184,16 +192,17 @@ class Bittrex(Exchange): def get_candles(self, data_frequency, assets, bar_count=None): """ - Supported Intervals ------------------- day, oneMin, fiveMin, thirtyMin, hour + :param data_frequency: :param assets: :param bar_count: :return: """ log.info('retrieving candles') + if data_frequency == 'minute' or data_frequency == '1m': frequency = 'oneMin' elif data_frequency == '5m': diff --git a/catalyst/exchange/exchange.py b/catalyst/exchange/exchange.py index ecc59f9e..081ef9b5 100644 --- a/catalyst/exchange/exchange.py +++ b/catalyst/exchange/exchange.py @@ -37,9 +37,9 @@ class Exchange: self.minute_reader = None self.base_currency = None - @abstractproperty + @property def positions(self): - pass + return self.portfolio.positions @property def portfolio(self): @@ -507,7 +507,11 @@ class Exchange: price='{}{}'.format(display_price, asset.base_currency) ) ) - return self.create_order(asset, amount, is_buy, style) + order = self.create_order(asset, amount, is_buy, style) + + self._portfolio.create_order(order) + + return order.id @abstractmethod def get_open_orders(self, asset): diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index 4bcb4b6e..c14493c9 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -10,6 +10,8 @@ import pandas as pd import click +from catalyst.exchange.bittrex.bittrex import Bittrex + try: from pygments import highlight from pygments.lexers import PythonLexer @@ -506,6 +508,13 @@ def run_algorithm(initialize, base_currency=base_currency, portfolio=portfolio ) + elif exchange_name == 'bittrex': + exchange = Bittrex( + key=exchange_auth['key'], + secret=exchange_auth['secret'], + base_currency=base_currency, + portfolio=portfolio + ) else: raise NotImplementedError( 'exchange not supported: %s' % exchange_name) diff --git a/tests/exchange/test_bittrex.py b/tests/exchange/test_bittrex.py index 2ad863eb..825af970 100644 --- a/tests/exchange/test_bittrex.py +++ b/tests/exchange/test_bittrex.py @@ -32,6 +32,8 @@ class BittrexTestCase(BaseExchangeTestCase): def test_open_orders(self): log.info('retrieving open orders') + asset = self.exchange.get_asset('neo_btc') + orders = self.exchange.get_open_orders(asset) pass def test_get_order(self):