From 9dd1ce71ca165045f0b484f7aec49774e07729c8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 18 Apr 2025 14:01:34 +0200 Subject: [PATCH] fix: improve get_max_leverage logic --- freqtrade/exchange/exchange.py | 46 ++++++++++----------------------- tests/exchange/test_exchange.py | 2 +- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 8b6bbfa58..6d0b0925c 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -3363,40 +3363,20 @@ class Exchange: if stake_amount == 0: return pair_tiers[0]["maxLeverage"] # Max lev for lowest amount - for tier_index in range(len(pair_tiers)): - tier = pair_tiers[tier_index] - lev = tier["maxLeverage"] + # Find the appropriate tier based on stake_amount + prior_max_lev = None + for tier in pair_tiers: + min_stake = tier["minNotional"] / (prior_max_lev or tier["maxLeverage"]) + max_stake = tier["maxNotional"] / tier["maxLeverage"] + prior_max_lev = tier["maxLeverage"] + # Adjust notional by leverage to do a proper comparison + if min_stake <= stake_amount <= max_stake: + return tier["maxLeverage"] - if tier_index < len(pair_tiers) - 1: - next_tier = pair_tiers[tier_index + 1] - next_floor = next_tier["minNotional"] / next_tier["maxLeverage"] - if next_floor > stake_amount: # Next tier min too high for stake amount - return min((tier["maxNotional"] / stake_amount), lev) - # - # With the two leverage tiers below, - # - a stake amount of 150 would mean a max leverage of (10000 / 150) = 66.66 - # - stakes below 133.33 = max_lev of 75 - # - stakes between 133.33-200 = max_lev of 10000/stake = 50.01-74.99 - # - stakes from 200 + 1000 = max_lev of 50 - # - # { - # "min": 0, # stake = 0.0 - # "max": 10000, # max_stake@75 = 10000/75 = 133.33333333333334 - # "lev": 75, - # }, - # { - # "min": 10000, # stake = 200.0 - # "max": 50000, # max_stake@50 = 50000/50 = 1000.0 - # "lev": 50, - # } - # - - else: # if on the last tier - if stake_amount > tier["maxNotional"]: - # If stake is > than max tradeable amount - raise InvalidOrderException(f"Amount {stake_amount} too high for {pair}") - else: - return tier["maxLeverage"] + # else: # if on the last tier + if stake_amount > max_stake: + # If stake is > than max tradeable amount + raise InvalidOrderException(f"Amount {stake_amount} too high for {pair}") raise OperationalException( "Looped through all tiers without finding a max leverage. Should never be reached" diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index c0023f0ad..bc20d1262 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -5902,7 +5902,7 @@ def test_get_max_leverage_futures(default_conf, mocker, leverage_tiers): assert exchange.get_max_leverage("XRP/USDT:USDT", 1.0) == 20.0 assert exchange.get_max_leverage("BNB/USDT:USDT", 100.0) == 75.0 assert exchange.get_max_leverage("BTC/USDT:USDT", 170.30) == 125.0 - assert pytest.approx(exchange.get_max_leverage("XRP/USDT:USDT", 99999.9)) == 5.000005 + assert pytest.approx(exchange.get_max_leverage("XRP/USDT:USDT", 99999.9)) == 20 assert pytest.approx(exchange.get_max_leverage("BNB/USDT:USDT", 1500)) == 33.333333333333333 assert exchange.get_max_leverage("BTC/USDT:USDT", 300000000) == 2.0 assert exchange.get_max_leverage("BTC/USDT:USDT", 600000000) == 1.0 # Last tier