From 25d3e884cae1a026ba1e445882826a105959b98c Mon Sep 17 00:00:00 2001 From: qmatias Date: Tue, 10 May 2022 19:47:09 -0500 Subject: [PATCH] fix tests --- .../interfaces/abc_base_exchange_interface.py | 4 +- .../interfaces/binance/binance_interface.py | 14 ++--- .../coinbase_pro/coinbase_pro_interface.py | 2 +- .../exchanges/interfaces/ftx/ftx_interface.py | 2 +- .../interfaces/oanda/oanda_interface.py | 4 +- blankly/exchanges/orders/stop_loss.py | 4 ++ blankly/exchanges/orders/take_profit.py | 4 ++ blankly/utils/utils.py | 3 +- tests/config/settings.json | 1 - tests/exchanges/test_interface_homogeneity.py | 56 ++++++++----------- tests/new_interface_tests/test_interfaces.py | 4 -- tests/new_interface_tests/test_utils.py | 5 ++ 12 files changed, 51 insertions(+), 52 deletions(-) diff --git a/blankly/exchanges/interfaces/abc_base_exchange_interface.py b/blankly/exchanges/interfaces/abc_base_exchange_interface.py index 93783ec5..8a1fbdaf 100644 --- a/blankly/exchanges/interfaces/abc_base_exchange_interface.py +++ b/blankly/exchanges/interfaces/abc_base_exchange_interface.py @@ -127,9 +127,7 @@ def calculate_epochs(self, start_date, end_date, resolution, to): parsed_date = end_date valid_time_in_past = utils.ceil_date(parsed_date, seconds=resolution_seconds).timestamp() - resolution_seconds - epoch_stop = valid_time_in_past - if is_backtesting is None: - epoch_stop -= resolution_seconds + epoch_stop = valid_time_in_past - resolution_seconds count_from = valid_time_in_past if start_date is None and end_date is None: if isinstance(to, int): diff --git a/blankly/exchanges/interfaces/binance/binance_interface.py b/blankly/exchanges/interfaces/binance/binance_interface.py index 7edddeff..fb6d0553 100644 --- a/blankly/exchanges/interfaces/binance/binance_interface.py +++ b/blankly/exchanges/interfaces/binance/binance_interface.py @@ -441,16 +441,16 @@ def take_profit_order(self, symbol, price, size) -> TakeProfitOrder: """ side = 'sell' - type = 'TAKE_PROFIT' order = { 'size': size, 'side': side, 'price': price, 'symbol': symbol, - 'type': type + 'type': 'take_profit' } modified_symbol = utils.to_exchange_symbol(symbol, 'binance') - response = self.calls.create_order(symbol=modified_symbol, side=side, stopPrice=price, quantity=size, type=type) + response = self.calls.create_order(symbol=modified_symbol, side=side, stopPrice=price, quantity=size, + type='TAKE_PROFIT') response = self._fix_response(needed, response) return TakeProfitOrder(order, response, self) @@ -497,16 +497,16 @@ def stop_loss_order(self, symbol, price, size) -> StopLossOrder: """ side = 'sell' - type = 'STOP_LOSS' order = { 'size': size, 'side': side, 'price': price, 'symbol': symbol, - 'type': type + 'type': 'stop_loss' } modified_symbol = utils.to_exchange_symbol(symbol, 'binance') - response = self.calls.create_order(symbol=modified_symbol, side=side, stopPrice=price, quantity=size, type=type) + response = self.calls.create_order(symbol=modified_symbol, side=side, stopPrice=price, quantity=size, + type='STOP_LOSS') response = self._fix_response(needed, response) return StopLossOrder(order, response, self) @@ -700,7 +700,7 @@ def get_product_history(self, symbol, epoch_start, epoch_stop, resolution): Returns: Dataframe with *at least* 'time (epoch)', 'low', 'high', 'open', 'close', 'volume' as columns. """ - self._binance_get_product_history(self.calls, symbol, epoch_start, epoch_stop, resolution) + return self._binance_get_product_history(self.calls, symbol, epoch_start, epoch_stop, resolution) @staticmethod def _binance_get_product_history(calls, symbol, epoch_start, epoch_stop, resolution): diff --git a/blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_interface.py b/blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_interface.py index 2811890d..b88db10e 100644 --- a/blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_interface.py +++ b/blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_interface.py @@ -327,7 +327,7 @@ def stop_limit(self, symbol, side, stop_price, limit_price, size, stop='loss') - order = { 'symbol': symbol, 'side': side, - 'type': 'stop', + 'type': 'stop_loss', 'stop': stop, 'stop_price': stop_price, 'size': size, diff --git a/blankly/exchanges/interfaces/ftx/ftx_interface.py b/blankly/exchanges/interfaces/ftx/ftx_interface.py index df98343a..69195137 100644 --- a/blankly/exchanges/interfaces/ftx/ftx_interface.py +++ b/blankly/exchanges/interfaces/ftx/ftx_interface.py @@ -331,7 +331,7 @@ def take_profit_order(self, response = self.get_calls().place_conditional_order(symbol, side, size, order_type="takeProfit", trigger_price=price) - order = utils.build_order_info(price, side, size, symbol, 'limit') + order = utils.build_order_info(price, side, size, symbol, 'take_profit') response = self._fix_response(needed, response) diff --git a/blankly/exchanges/interfaces/oanda/oanda_interface.py b/blankly/exchanges/interfaces/oanda/oanda_interface.py index 348e5fcc..e86a9cfb 100644 --- a/blankly/exchanges/interfaces/oanda/oanda_interface.py +++ b/blankly/exchanges/interfaces/oanda/oanda_interface.py @@ -28,7 +28,7 @@ from blankly.exchanges.orders.market_order import MarketOrder from blankly.exchanges.orders.stop_loss import StopLossOrder from blankly.exchanges.orders.take_profit import TakeProfitOrder -from blankly.utils import utils as utils +from blankly.utils import utils, time_builder from blankly.utils.exceptions import APIException, InvalidOrder @@ -361,7 +361,7 @@ def overridden_history(self, symbol, epoch_start, epoch_stop, resolution, **kwar def get_product_history(self, symbol: str, epoch_start: float, epoch_stop: float, resolution: int): symbol = self.__convert_blankly_to_oanda(symbol) - resolution = int(utils.time_interval_to_seconds(resolution)) + resolution = int(time_builder.time_interval_to_seconds(resolution)) if resolution not in self.multiples_keys: utils.info_print("Granularity is not an accepted granularity...rounding to nearest valid value.") diff --git a/blankly/exchanges/orders/stop_loss.py b/blankly/exchanges/orders/stop_loss.py index 08b6cd1a..7599f8fb 100644 --- a/blankly/exchanges/orders/stop_loss.py +++ b/blankly/exchanges/orders/stop_loss.py @@ -57,3 +57,7 @@ def __str__(self): return_string = self.add_new_line(return_string, self.get_price()) return return_string + + # override this here to homogenize these strings + def get_type(self) -> str: + return 'stop_loss' diff --git a/blankly/exchanges/orders/take_profit.py b/blankly/exchanges/orders/take_profit.py index 8f4509e3..86b688ec 100644 --- a/blankly/exchanges/orders/take_profit.py +++ b/blankly/exchanges/orders/take_profit.py @@ -57,3 +57,7 @@ def __str__(self): return_string = self.add_new_line(return_string, self.get_price()) return return_string + + # override this here to homogenize these strings + def get_type(self) -> str: + return 'take_profit' diff --git a/blankly/utils/utils.py b/blankly/utils/utils.py index bed377c5..51ae78e8 100644 --- a/blankly/utils/utils.py +++ b/blankly/utils/utils.py @@ -441,7 +441,8 @@ def isolate_specific(needed, compare_dictionary): # Now we need to remove the keys that we appended to exchange_specific for k, v in exchange_specific.items(): - del compare_dictionary[k] + if k in compare_dictionary: + del compare_dictionary[k] # If there exists the exchange specific dict in the compare dictionary # This is done because after renaming, if there are naming conflicts they will already have been pushed here diff --git a/tests/config/settings.json b/tests/config/settings.json index 67e4fbcb..e7dd3b5c 100644 --- a/tests/config/settings.json +++ b/tests/config/settings.json @@ -3,7 +3,6 @@ "use_sandbox_websockets": false, "websocket_buffer_size": 10000, "test_connectivity_on_auth": false, - "auto_truncate": true, "coinbase_pro": { "cash": "USD" diff --git a/tests/exchanges/test_interface_homogeneity.py b/tests/exchanges/test_interface_homogeneity.py index 93358b43..cb8dbd84 100644 --- a/tests/exchanges/test_interface_homogeneity.py +++ b/tests/exchanges/test_interface_homogeneity.py @@ -287,9 +287,9 @@ def test_market_order(self): except Exception as e: print(f"Failed canceling order for reason {e} - may have already executed") - def check_limit_order(self, limit_order: LimitOrder, expected_side: str, size, product_id): + def check_limit_order(self, limit_order: LimitOrder, expected_side: str, size, product_id, type_='limit'): self.assertEqual(limit_order.get_side(), expected_side) - self.assertEqual(limit_order.get_type(), 'limit') + self.assertEqual(limit_order.get_type(), type_) self.assertEqual(limit_order.get_time_in_force(), 'GTC') # TODO fix status homogeneity # self.assertEqual(limit_order.get_status(), {'status': 'new'}) @@ -409,10 +409,16 @@ def evaluate_limit_order(interface: ABCExchangeInterface, symbol: str, buy_price self.assertTrue(compare_responses(cancels, force_exchange_specific=False)) - def evaluate_tp_sl_order(self, sorted_orders: dict, order_func, symbol: str, sell_price: [float, int], + def evaluate_tp_sl_order(self, sorted_orders: dict, interface, type_, symbol: str, sell_price: [float, int], size: [float, int]) -> list: + if type_ == 'stop_loss': + order_func = interface.stop_loss_order + elif type_ == 'take_profit': + order_func = interface.take_profit_order + else: + raise ValueError('order type must be take_profit or stop_loss') sell = order_func(symbol, sell_price, size) - self.check_limit_order(sell, 'sell', size, symbol) + self.check_limit_order(sell, 'sell', size, symbol, type_) sorted_orders[sell.exchange] = {'sell': sell} return [sell] @@ -420,17 +426,14 @@ def test_take_profit_order(self): limits = [] sorted_orders = {} - limits += self.evaluate_tp_sl_order(sorted_orders, self.Alpaca_Interface.take_profit_order, 'AAPL', 100000, 1) + limits += self.evaluate_tp_sl_order(sorted_orders, self.Alpaca_Interface, 'take_profit', 'AAPL', 100000, 1) - binance_limits = self.Binance_Interface.get_order_filter('BTC-USDT')["limit_order"] - limits += self.evaluate_tp_sl_order(sorted_orders, self.Binance_Interface.take_profit_order, 'BTC-USDT', - int(binance_limits['max_price'] - 100), .01) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Coinbase_Pro_Interface.take_profit_order, 'BTC-USD', + limits += self.evaluate_tp_sl_order(sorted_orders, self.Coinbase_Pro_Interface, 'take_profit', 'BTC-USD', 100000, 1) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Kucoin_Interface.take_profit_order, 'ETH-USDT', 100000, + limits += self.evaluate_tp_sl_order(sorted_orders, self.Kucoin_Interface, 'take_profit', 'ETH-USDT', 100000, 1) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Oanda_Interface.take_profit_order, 'EUR-USD', 100000, 1) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Okx_Interface.take_profit_order, 'BTC-USDT', 100000, + limits += self.evaluate_tp_sl_order(sorted_orders, self.Oanda_Interface, 'take_profit', 'EUR-USD', 100000, 1) + limits += self.evaluate_tp_sl_order(sorted_orders, self.Okx_Interface, 'take_profit', 'BTC-USDT', 100000, .01) responses = [] @@ -439,7 +442,6 @@ def test_take_profit_order(self): open_orders = { 'coinbase_pro': self.Coinbase_Pro_Interface.get_open_orders('BTC-USD'), - 'binance': self.Binance_Interface.get_open_orders('BTC-USDT'), 'kucoin': self.Kucoin_Interface.get_open_orders('ETH-USDT'), 'alpaca': self.Alpaca_Interface.get_open_orders('AAPL'), 'oanda': self.Oanda_Interface.get_open_orders('EUR-USD'), @@ -452,7 +454,6 @@ def test_take_profit_order(self): # Just scan through both simultaneously to reduce code copying all_orders = open_orders['coinbase_pro'] - all_orders = all_orders + open_orders['binance'] all_orders = all_orders + open_orders['okx'] all_orders = all_orders + open_orders['kucoin'] all_orders = all_orders + open_orders['alpaca'] @@ -483,8 +484,6 @@ def test_take_profit_order(self): self.assertTrue(compare_responses(responses)) self.assertTrue(compare_responses(status)) - cancels.append(self.Binance_Interface.cancel_order('BTC-USDT', sorted_orders['binance']['sell'].get_id())) - cancels.append(self.Kucoin_Interface.cancel_order('ETH-USDT', sorted_orders['kucoin']['sell'].get_id())) cancels.append(self.Okx_Interface.cancel_order('BTC-USDT', sorted_orders['okx']['sell'].get_id())) @@ -503,11 +502,11 @@ def check_account_delta_market(self, before: dict, after: dict, order: MarketOrd # The symbol should have gained less than the size on the buy if there were fees # Before + requested size >= the filled size - before['available'] = int(float(before['available'])) # added this and line below - after['available'] = int(float(after['available'])) + before['available'] = float(before['available']) + after['available'] = float(after['available']) - self.assertGreaterEqual(blankly.trunc(before['available'], 2) + order.get_size(), - blankly.trunc(after['available'], 2)) + self.assertAlmostEqual(blankly.trunc(before['available'], 2) + order.get_size(), + blankly.trunc(after['available'], 2), delta=1) def check_account_delta_limit(self, before: dict, after: dict, order: LimitOrder) -> None: # On a buy the quote asset should get moved to hold @@ -530,16 +529,13 @@ def test_stop_loss_order(self): limits = [] sorted_orders = {} - limits += self.evaluate_tp_sl_order(sorted_orders, self.Alpaca_Interface.take_profit_order, 'AAPL', 100000, 1) + limits += self.evaluate_tp_sl_order(sorted_orders, self.Alpaca_Interface, 'stop_loss', 'AAPL', 1, 1) - binance_limits = self.Binance_Interface.get_order_filter('BTC-USDT')["limit_order"] - limits += self.evaluate_tp_sl_order(sorted_orders, self.Binance_Interface.stop_loss_order, 'BTC-USDT', - int(binance_limits['min_price'] + 100), .01) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Coinbase_Pro_Interface.stop_loss_order, 'BTC-USD', 0.01, + limits += self.evaluate_tp_sl_order(sorted_orders, self.Coinbase_Pro_Interface, 'stop_loss', 'BTC-USD', 0.01, 1) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Kucoin_Interface.stop_loss_order, 'ETH-USDT', 0.01, 1) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Oanda_Interface.stop_loss_order, 'EUR-USD', 0.01, 1) - limits += self.evaluate_tp_sl_order(sorted_orders, self.Okx_Interface.stop_loss_order, 'BTC-USDT', 0.5, .01) + limits += self.evaluate_tp_sl_order(sorted_orders, self.Kucoin_Interface, 'stop_loss', 'ETH-USDT', 0.01, 1) + limits += self.evaluate_tp_sl_order(sorted_orders, self.Oanda_Interface, 'stop_loss', 'EUR-USD', 0.01, 1) + limits += self.evaluate_tp_sl_order(sorted_orders, self.Okx_Interface, 'stop_loss', 'BTC-USDT', 0.5, .01) responses = [] status = [] @@ -547,7 +543,6 @@ def test_stop_loss_order(self): open_orders = { 'coinbase_pro': self.Coinbase_Pro_Interface.get_open_orders('BTC-USD'), - 'binance': self.Binance_Interface.get_open_orders('BTC-USDT'), 'kucoin': self.Kucoin_Interface.get_open_orders('ETH-USDT'), 'alpaca': self.Alpaca_Interface.get_open_orders('AAPL'), 'oanda': self.Oanda_Interface.get_open_orders('EUR-USD'), @@ -560,7 +555,6 @@ def test_stop_loss_order(self): # Just scan through both simultaneously to reduce code copying all_orders = open_orders['coinbase_pro'] - all_orders = all_orders + open_orders['binance'] all_orders = all_orders + open_orders['okx'] all_orders = all_orders + open_orders['kucoin'] all_orders = all_orders + open_orders['alpaca'] @@ -591,8 +585,6 @@ def test_stop_loss_order(self): self.assertTrue(compare_responses(responses)) self.assertTrue(compare_responses(status)) - cancels.append(self.Binance_Interface.cancel_order('BTC-USDT', sorted_orders['binance']['sell'].get_id())) - cancels.append(self.Kucoin_Interface.cancel_order('ETH-USDT', sorted_orders['kucoin']['sell'].get_id())) cancels.append(self.Okx_Interface.cancel_order('BTC-USDT', sorted_orders['okx']['sell'].get_id())) diff --git a/tests/new_interface_tests/test_interfaces.py b/tests/new_interface_tests/test_interfaces.py index c1fee9af..7e453cd7 100644 --- a/tests/new_interface_tests/test_interfaces.py +++ b/tests/new_interface_tests/test_interfaces.py @@ -16,10 +16,6 @@ close_all -# TODO auto truncate -# TODO min size/min notional api - - def valid_product_helper(interface: ABCBaseExchangeInterface, product): base = product['base_asset'] quote = product['quote_asset'] diff --git a/tests/new_interface_tests/test_utils.py b/tests/new_interface_tests/test_utils.py index a9327a8e..5319658e 100644 --- a/tests/new_interface_tests/test_utils.py +++ b/tests/new_interface_tests/test_utils.py @@ -86,6 +86,11 @@ ftx ] +for exchange in FUTURES_EXCHANGES + SPOT_EXCHANGES: + # override auto trunc for new tests + # old tests use the default if auto_truncate is not set, which is False + exchange.user_preferences['settings']['auto_truncate'] = True + def get_symbols(exchange: ABCBaseExchangeInterface): exchange_type = exchange.get_exchange_type()