Added some exchange leverage tier tests

This commit is contained in:
Sam Germain 2022-02-07 07:09:29 -06:00
parent 98f32e8964
commit eb72e5cc42
3 changed files with 110 additions and 32 deletions

View File

@ -2247,11 +2247,16 @@ class Exchange:
raise OperationalException( raise OperationalException(
"Freqtrade only supports isolated futures for leverage trading") "Freqtrade only supports isolated futures for leverage trading")
@retrier
def get_leverage_tiers_for_pair(self, pair: str): def get_leverage_tiers_for_pair(self, pair: str):
# When exchanges can load all their leverage tiers at once in the constructor # When exchanges can load all their leverage tiers at once in the constructor
# then this method does nothing, it should only be implemented when the leverage # then this method does nothing, it should only be implemented when the leverage
# tiers requires per symbol fetching to avoid excess api calls # tiers requires per symbol fetching to avoid excess api calls
if not self._ft_has['can_fetch_multiple_tiers']: if (
self._api.has['fetchLeverageTiers'] and
not self._ft_has['can_fetch_multiple_tiers'] and
self.trading_mode == TradingMode.FUTURES
):
try: try:
return self._api.fetch_leverage_tiers(pair) return self._api.fetch_leverage_tiers(pair)
except ccxt.BadRequest: except ccxt.BadRequest:

View File

@ -628,12 +628,3 @@ def test_get_maintenance_ratio_and_amt_binance(
exchange._leverage_tiers = leverage_tiers exchange._leverage_tiers = leverage_tiers
(result_ratio, result_amt) = exchange.get_maintenance_ratio_and_amt(pair, nominal_value) (result_ratio, result_amt) = exchange.get_maintenance_ratio_and_amt(pair, nominal_value)
assert (round(result_ratio, 8), round(result_amt, 8)) == (mm_ratio, amt) assert (round(result_ratio, 8), round(result_amt, 8)) == (mm_ratio, amt)
def test_load_leverage_tiers_binance(mocker, default_conf, leverage_tiers):
# TODO-lev
api_mock = MagicMock()
default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated'
exchange = get_patched_exchange(mocker, default_conf, api_mock)
assert exchange

View File

@ -3560,8 +3560,7 @@ def test__ccxt_config(
("LTC/BTC", 0.0, 1.0), ("LTC/BTC", 0.0, 1.0),
("TKN/USDT", 210.30, 1.0), ("TKN/USDT", 210.30, 1.0),
]) ])
def test_get_max_leverage(default_conf, mocker, pair, nominal_value, max_lev): def test_get_max_leverage_from_markets(default_conf, mocker, pair, nominal_value, max_lev):
# TODO-lev: Branch coverage
default_conf['trading_mode'] = 'futures' default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated' default_conf['margin_mode'] = 'isolated'
api_mock = MagicMock() api_mock = MagicMock()
@ -3570,6 +3569,11 @@ def test_get_max_leverage(default_conf, mocker, pair, nominal_value, max_lev):
assert exchange.get_max_leverage(pair, nominal_value) == max_lev assert exchange.get_max_leverage(pair, nominal_value) == max_lev
def test_get_max_leverage_from_tiers(default_conf, mocker):
# TODO-lev:
return
@pytest.mark.parametrize( @pytest.mark.parametrize(
'size,funding_rate,mark_price,time_in_ratio,funding_fee,kraken_fee', [ 'size,funding_rate,mark_price,time_in_ratio,funding_fee,kraken_fee', [
(10, 0.0001, 2.0, 1.0, 0.002, 0.002), (10, 0.0001, 2.0, 1.0, 0.002, 0.002),
@ -4227,45 +4231,123 @@ def test_get_max_pair_stake_amount(
def test_load_leverage_tiers(mocker, default_conf, leverage_tiers): def test_load_leverage_tiers(mocker, default_conf, leverage_tiers):
# TODO-lev
api_mock = MagicMock() api_mock = MagicMock()
default_conf['trading_mode'] = 'futures' api_mock.fetch_leverage_tiers = MagicMock()
default_conf['margin_mode'] = 'isolated'
exchange = get_patched_exchange(mocker, default_conf, api_mock)
api_mock = MagicMock()
api_mock.set_margin_mode = MagicMock()
type(api_mock).has = PropertyMock(return_value={'fetchLeverageTiers': True}) type(api_mock).has = PropertyMock(return_value={'fetchLeverageTiers': True})
default_conf['dry_run'] = False default_conf['dry_run'] = False
default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated'
ccxt_exceptionhandlers( ccxt_exceptionhandlers(
mocker, mocker,
default_conf, default_conf,
api_mock, api_mock,
"binance", "binance",
"set_margin_mode", "load_leverage_tiers",
"set_margin_mode", "fetch_leverage_tiers",
pair="XRP/USDT",
margin_mode=margin_mode
) )
def test_parse_leverage_tier(mocker, default_conf, leverage_tiers): def test_parse_leverage_tier(mocker, default_conf):
# TODO-lev exchange = get_patched_exchange(mocker, default_conf)
api_mock = MagicMock()
default_conf['trading_mode'] = 'futures' tier = {
default_conf['margin_mode'] = 'isolated' "tier": 1,
exchange = get_patched_exchange(mocker, default_conf, api_mock) "notionalFloor": 0,
assert exchange "notionalCap": 100000,
"maintenanceMarginRatio": 0.025,
"maxLeverage": 20,
"info": {
"bracket": "1",
"initialLeverage": "20",
"notionalCap": "100000",
"notionalFloor": "0",
"maintMarginRatio": "0.025",
"cum": "0.0"
}
}
assert exchange.parse_leverage_tier(tier) == {
"min": 0,
"max": 100000,
"mmr": 0.025,
"lev": 20,
"maintAmt": 0.0,
}
tier2 = {
'tier': 1,
'notionalFloor': 0,
'notionalCap': 2000,
'maintenanceMarginRatio': 0.01,
'maxLeverage': 75,
'info': {
'baseMaxLoan': '',
'imr': '0.013',
'instId': '',
'maxLever': '75',
'maxSz': '2000',
'minSz': '0',
'mmr': '0.01',
'optMgnFactor': '0',
'quoteMaxLoan': '',
'tier': '1',
'uly': 'SHIB-USDT'
}
}
assert exchange.parse_leverage_tier(tier2) == {
'min': 0,
'max': 2000,
'mmr': 0.01,
'lev': 75,
"maintAmt": None,
}
def test_get_leverage_tiers_for_pair(mocker, default_conf, leverage_tiers): def test_get_leverage_tiers_for_pair(mocker, default_conf, leverage_tiers):
# TODO-lev
api_mock = MagicMock() api_mock = MagicMock()
api_mock.fetch_leverage_tiers = MagicMock()
# Spot
type(api_mock)._ft_has = PropertyMock(return_value={'fetchLeverageTiers': True})
exchange = get_patched_exchange(mocker, default_conf, api_mock)
exchange._ft_has['can_fetch_multiple_tiers'] = False
assert exchange.get_leverage_tiers_for_pair('ADA/USDT') is None
# 'can_fetch_multiple_tiers': True
default_conf['trading_mode'] = 'futures' default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated' default_conf['margin_mode'] = 'isolated'
type(api_mock).has = PropertyMock(return_value={'fetchLeverageTiers': True})
exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange = get_patched_exchange(mocker, default_conf, api_mock)
assert exchange exchange._ft_has['can_fetch_multiple_tiers'] = True
assert exchange.get_leverage_tiers_for_pair('ADA/USDT:USDT') is None
# 'fetchLeverageTiers': False
type(api_mock).has = PropertyMock(return_value={'fetchLeverageTiers': False})
exchange = get_patched_exchange(mocker, default_conf, api_mock)
exchange._ft_has['can_fetch_multiple_tiers'] = False
assert exchange.get_leverage_tiers_for_pair('ADA/USDT:USDT') is None
# 'fetchLeverageTiers': False
type(api_mock).has = PropertyMock(return_value={'fetchLeverageTiers': True})
exchange = get_patched_exchange(mocker, default_conf, api_mock)
exchange._ft_has['can_fetch_multiple_tiers'] = False
assert exchange.get_leverage_tiers_for_pair('ADA/USDT:USDT') is not None
type(api_mock).has = PropertyMock(return_value={'fetchLeverageTiers': True})
default_conf['dry_run'] = False
exchange = get_patched_exchange(mocker, default_conf, api_mock)
ccxt_exceptionhandlers(
mocker,
default_conf,
api_mock,
"binance",
"get_leverage_tiers_for_pair",
"fetch_leverage_tiers",
pair='ETH/USDT:USDT',
)
def test_get_maintenance_ratio_and_amt(mocker, default_conf, leverage_tiers): def test_get_maintenance_ratio_and_amt(mocker, default_conf, leverage_tiers):