From 2eb1d18c2a8f788fa47826ae8fca45795bcba56d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 23 Jul 2022 19:56:38 +0200 Subject: [PATCH 1/3] Don't load leverage tiers when not necessary --- freqtrade/exchange/exchange.py | 5 +++-- freqtrade/freqtradebot.py | 3 ++- freqtrade/optimize/backtesting.py | 3 ++- freqtrade/resolvers/exchange_resolver.py | 13 +++++++++---- freqtrade/rpc/api_server/deps.py | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index a430cdac5..11e37b953 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -88,7 +88,8 @@ class Exchange: # TradingMode.SPOT always supported and not required in this list ] - def __init__(self, config: Dict[str, Any], validate: bool = True) -> None: + def __init__(self, config: Dict[str, Any], validate: bool = True, + load_leverage_tiers: bool = False) -> None: """ Initializes this module with the given config, it does basic validation whether the specified exchange and pairs are valid. @@ -186,7 +187,7 @@ class Exchange: self.markets_refresh_interval: int = exchange_config.get( "markets_refresh_interval", 60) * 60 - if self.trading_mode != TradingMode.SPOT: + if self.trading_mode != TradingMode.SPOT and load_leverage_tiers: self.fill_leverage_tiers() self.additional_exchange_init() diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 2007f9b4e..43608cae7 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -65,7 +65,8 @@ class FreqtradeBot(LoggingMixin): # Check config consistency here since strategies can set certain options validate_config_consistency(config) - self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config) + self.exchange = ExchangeResolver.load_exchange( + self.config['exchange']['name'], self.config, load_leverage_tiers=True) init_db(self.config['db_url']) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index da28a8d93..4d16dc0f1 100755 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -84,7 +84,8 @@ class Backtesting: self.processed_dfs: Dict[str, Dict] = {} self._exchange_name = self.config['exchange']['name'] - self.exchange = ExchangeResolver.load_exchange(self._exchange_name, self.config) + self.exchange = ExchangeResolver.load_exchange( + self._exchange_name, self.config, load_leverage_tiers=True) self.dataprovider = DataProvider(self.config, self.exchange) if self.config.get('strategy_list'): diff --git a/freqtrade/resolvers/exchange_resolver.py b/freqtrade/resolvers/exchange_resolver.py index 4dfbf445b..a2f572ff2 100644 --- a/freqtrade/resolvers/exchange_resolver.py +++ b/freqtrade/resolvers/exchange_resolver.py @@ -18,7 +18,8 @@ class ExchangeResolver(IResolver): object_type = Exchange @staticmethod - def load_exchange(exchange_name: str, config: dict, validate: bool = True) -> Exchange: + def load_exchange(exchange_name: str, config: dict, validate: bool = True, + load_leverage_tiers: bool = False) -> Exchange: """ Load the custom class from config parameter :param exchange_name: name of the Exchange to load @@ -29,9 +30,13 @@ class ExchangeResolver(IResolver): exchange_name = exchange_name.title() exchange = None try: - exchange = ExchangeResolver._load_exchange(exchange_name, - kwargs={'config': config, - 'validate': validate}) + exchange = ExchangeResolver._load_exchange( + exchange_name, + kwargs={ + 'config': config, + 'validate': validate, + 'load_leverage_tiers': load_leverage_tiers} + ) except ImportError: logger.info( f"No {exchange_name} specific subclass found. Using the generic class instead.") diff --git a/freqtrade/rpc/api_server/deps.py b/freqtrade/rpc/api_server/deps.py index f5e61602e..81c013efa 100644 --- a/freqtrade/rpc/api_server/deps.py +++ b/freqtrade/rpc/api_server/deps.py @@ -37,7 +37,7 @@ def get_exchange(config=Depends(get_config)): if not ApiServer._exchange: from freqtrade.resolvers import ExchangeResolver ApiServer._exchange = ExchangeResolver.load_exchange( - config['exchange']['name'], config) + config['exchange']['name'], config, load_leverage_tiers=False) return ApiServer._exchange From 6e691a016d1ae3fcd18596d45ab48d24fecf4d35 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 24 Jul 2022 10:24:59 +0200 Subject: [PATCH 2/3] Use leverage-tiers loading in tests --- tests/conftest.py | 2 +- tests/exchange/test_ccxt_compat.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 3158e9ede..237c3fcc0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -148,7 +148,7 @@ def get_patched_exchange(mocker, config, api_mock=None, id='binance', patch_exchange(mocker, api_mock, id, mock_markets, mock_supported_modes) config['exchange']['name'] = id try: - exchange = ExchangeResolver.load_exchange(id, config) + exchange = ExchangeResolver.load_exchange(id, config, load_leverage_tiers=True) except ImportError: exchange = Exchange(config) return exchange diff --git a/tests/exchange/test_ccxt_compat.py b/tests/exchange/test_ccxt_compat.py index 74106f28b..7bb52ccaf 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -137,7 +137,8 @@ def exchange_futures(request, exchange_conf, class_mocker): 'freqtrade.exchange.binance.Binance.fill_leverage_tiers') class_mocker.patch('freqtrade.exchange.exchange.Exchange.fetch_trading_fees') class_mocker.patch('freqtrade.exchange.okx.Okx.additional_exchange_init') - exchange = ExchangeResolver.load_exchange(request.param, exchange_conf, validate=True) + exchange = ExchangeResolver.load_exchange( + request.param, exchange_conf, validate=True, load_leverage_tiers=True) yield exchange, request.param From 83cac7bee2e6d94e47db336e1b83f2d55873c3d9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 24 Jul 2022 10:51:13 +0200 Subject: [PATCH 3/3] Improve some more tests by adding proper orders --- tests/conftest.py | 19 ++++++++++++++++++- tests/rpc/test_rpc.py | 2 ++ tests/test_freqtradebot.py | 24 +++++++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 237c3fcc0..ff3e1007f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2609,7 +2609,7 @@ def open_trade_usdt(): pair='ADA/USDT', open_rate=2.0, exchange='binance', - open_order_id='123456789', + open_order_id='123456789_exit', amount=30.0, fee_open=0.0, fee_close=0.0, @@ -2634,6 +2634,23 @@ def open_trade_usdt(): cost=trade.open_rate * trade.amount, order_date=trade.open_date, order_filled_date=trade.open_date, + ), + Order( + ft_order_side='exit', + ft_pair=trade.pair, + ft_is_open=True, + order_id='123456789_exit', + status="open", + symbol=trade.pair, + order_type="limit", + side="sell", + price=trade.open_rate, + average=trade.open_rate, + filled=trade.amount, + remaining=0, + cost=trade.open_rate * trade.amount, + order_date=trade.open_date, + order_filled_date=trade.open_date, ) ] return trade diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index d20646e60..6e19fcaf3 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -830,6 +830,8 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: assert cancel_order_mock.call_count == 2 assert trade.amount == amount + trade = Trade.query.filter(Trade.id == '3').first() + # make an limit-sell open trade mocker.patch( 'freqtrade.exchange.Exchange.fetch_order', diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index a4b10fbcd..66cbd7d9b 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -2759,6 +2759,8 @@ def test_check_handle_cancelled_exit( cancel_order_mock = MagicMock() limit_sell_order_old.update({"status": "canceled", 'filled': 0.0}) limit_sell_order_old['side'] = 'buy' if is_short else 'sell' + limit_sell_order_old['id'] = open_trade_usdt.open_order_id + patch_exchange(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -3098,7 +3100,27 @@ def test_handle_cancel_exit_limit(mocker, default_conf_usdt, fee) -> None: close_date=arrow.utcnow().datetime, exit_reason="sell_reason_whatever", ) - order = {'remaining': 1, + trade.orders = [ + Order( + ft_order_side='buy', + ft_pair=trade.pair, + ft_is_open=True, + order_id='123456', + status="closed", + symbol=trade.pair, + order_type="market", + side="buy", + price=trade.open_rate, + average=trade.open_rate, + filled=trade.amount, + remaining=0, + cost=trade.open_rate * trade.amount, + order_date=trade.open_date, + order_filled_date=trade.open_date, + ), + ] + order = {'id': "123456", + 'remaining': 1, 'amount': 1, 'status': "open"} reason = CANCEL_REASON['TIMEOUT']