okex loads all leverage tiers at beginning, removed get tiers for pair

This commit is contained in:
Sam Germain 2022-02-11 06:50:23 -06:00
parent 8657e99c26
commit 7a0f7da128
4 changed files with 27 additions and 148 deletions

View File

@ -1894,28 +1894,6 @@ class Exchange:
'maintAmt': float(info['cum']) if 'cum' in info else None, 'maintAmt': float(info['cum']) if 'cum' in info else None,
} }
@retrier
def get_leverage_tiers_for_pair(self, pair: str) -> List:
# 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
# tiers requires per symbol fetching to avoid excess api calls
if pair not in self._leverage_tiers:
self._leverage_tiers[pair] = []
if (
self._api.has['fetchLeverageTiers'] and
not self._ft_has['can_fetch_multiple_tiers'] and
self.trading_mode == TradingMode.FUTURES
):
try:
tiers = self._api.fetch_leverage_tiers(pair)
for tier in tiers[pair]:
self._leverage_tiers[pair].append(self.parse_leverage_tier(tier))
except ccxt.BadRequest:
return []
return self._leverage_tiers[pair]
def get_max_leverage(self, pair: str, stake_amount: Optional[float]) -> float: def get_max_leverage(self, pair: str, stake_amount: Optional[float]) -> float:
""" """
Returns the maximum leverage that a pair can be traded at Returns the maximum leverage that a pair can be traded at
@ -1926,7 +1904,7 @@ class Exchange:
if self.trading_mode == TradingMode.SPOT: if self.trading_mode == TradingMode.SPOT:
return 1.0 return 1.0
if self._api.has['fetchLeverageTiers']: if self.trading_mode == TradingMode.FUTURES:
# Checks and edge cases # Checks and edge cases
if stake_amount is None: if stake_amount is None:
@ -1934,20 +1912,21 @@ class Exchange:
f'{self.name}.get_max_leverage requires argument stake_amount' f'{self.name}.get_max_leverage requires argument stake_amount'
) )
pair_tiers = self.get_leverage_tiers_for_pair(pair) if pair not in self._leverage_tiers:
num_tiers = len(pair_tiers) # Maybe raise exception because it can't be traded on futures?
if num_tiers < 1:
return 1.0 return 1.0
pair_tiers = self._leverage_tiers[pair]
if stake_amount == 0: if stake_amount == 0:
return self._leverage_tiers[pair][0]['lev'] # Max lev for lowest amount return self._leverage_tiers[pair][0]['lev'] # Max lev for lowest amount
for tier_index in range(num_tiers): for tier_index in range(len(pair_tiers)):
tier = pair_tiers[tier_index] tier = pair_tiers[tier_index]
lev = tier['lev'] lev = tier['lev']
if tier_index < num_tiers - 1: if tier_index < len(pair_tiers) - 1:
next_tier = pair_tiers[tier_index+1] next_tier = pair_tiers[tier_index+1]
next_floor = next_tier['min'] / next_tier['lev'] next_floor = next_tier['min'] / next_tier['lev']
if next_floor > stake_amount: # Next tier min too high for stake amount if next_floor > stake_amount: # Next tier min too high for stake amount
@ -2280,13 +2259,13 @@ class Exchange:
if self._api.has['fetchLeverageTiers']: if self._api.has['fetchLeverageTiers']:
pair_tiers = self.get_leverage_tiers_for_pair(pair) if pair not in self._leverage_tiers:
if len(pair_tiers) < 1:
raise InvalidOrderException( raise InvalidOrderException(
f"Maintenance margin rate for {pair} is unavailable for {self.name}" f"Maintenance margin rate for {pair} is unavailable for {self.name}"
) )
pair_tiers = self._leverage_tiers[pair]
for tier in reversed(pair_tiers): for tier in reversed(pair_tiers):
if nominal_value >= tier['min']: if nominal_value >= tier['min']:
return (tier['mmr'], tier['maintAmt']) return (tier['mmr'], tier['maintAmt'])

View File

@ -59,14 +59,25 @@ class Okx(Exchange):
return float('inf') # Not actually inf, but this probably won't matter for SPOT return float('inf') # Not actually inf, but this probably won't matter for SPOT
if pair not in self._leverage_tiers: if pair not in self._leverage_tiers:
tiers = self.get_leverage_tiers_for_pair(pair) return float('inf')
if not tiers: # Not a leveraged market
return float('inf')
else:
self._leverage_tiers[pair] = tiers
pair_tiers = self._leverage_tiers[pair] pair_tiers = self._leverage_tiers[pair]
return pair_tiers[-1]['max'] / leverage return pair_tiers[-1]['max'] / leverage
def load_leverage_tiers(self) -> Dict[str, List[Dict]]: def load_leverage_tiers(self) -> Dict[str, List[Dict]]:
return {} if self.trading_mode == TradingMode.FUTURES:
markets = self.markets
symbols = []
for symbol, market in markets.items():
if (market["swap"] and market["linear"]):
symbols.append(market["symbol"])
tiers = {}
for symbol in symbols:
res = self._api.fetchLeverageTiers(symbol)
tiers[symbol] = res[symbol]
return tiers
else:
return {}

View File

@ -4300,115 +4300,6 @@ def test_parse_leverage_tier(mocker, default_conf):
} }
def test_get_leverage_tiers_for_pair(
mocker,
default_conf,
leverage_tiers,
):
api_mock = MagicMock()
api_mock.fetch_leverage_tiers = MagicMock(return_value={
'DOGE/USDT:USDT': [
{
'tier': 1,
'notionalFloor': 0,
'notionalCap': 500,
'maintenanceMarginRatio': 0.02,
'maxLeverage': 75,
'info': {
'baseMaxLoan': '',
'imr': '0.013',
'instId': '',
'maxLever': '75',
'maxSz': '500',
'minSz': '0',
'mmr': '0.01',
'optMgnFactor': '0',
'quoteMaxLoan': '',
'tier': '1',
'uly': 'DOGE-USDT'
}
},
{
'tier': 2,
'notionalFloor': 501,
'notionalCap': 1000,
'maintenanceMarginRatio': 0.025,
'maxLeverage': 50,
'info': {
'baseMaxLoan': '',
'imr': '0.02',
'instId': '',
'maxLever': '50',
'maxSz': '1000',
'minSz': '501',
'mmr': '0.015',
'optMgnFactor': '0',
'quoteMaxLoan': '',
'tier': '2',
'uly': 'DOGE-USDT'
}
}
],
})
# 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('DOGE/USDT:USDT') == []
# 'can_fetch_multiple_tiers': True
default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated'
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'] = True
assert exchange.get_leverage_tiers_for_pair('DOGE/USDT:USDT') == []
# '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('DOGE/USDT:USDT') == []
# 'fetchLeverageTiers': True
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('DOGE/USDT:USDT') == [
{
'min': 0,
'max': 500,
'mmr': 0.02,
'lev': 75,
'maintAmt': None
},
{
'min': 501,
'max': 1000,
'mmr': 0.025,
'lev': 50,
'maintAmt': None
}
]
# exception_handlers
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='DOGE/USDT:USDT',
)
def test_get_maintenance_ratio_and_amt_exceptions(mocker, default_conf, leverage_tiers): def test_get_maintenance_ratio_and_amt_exceptions(mocker, default_conf, leverage_tiers):
api_mock = MagicMock() api_mock = MagicMock()
default_conf['trading_mode'] = 'futures' default_conf['trading_mode'] = 'futures'
@ -4423,7 +4314,6 @@ def test_get_maintenance_ratio_and_amt_exceptions(mocker, default_conf, leverage
exchange.get_maintenance_ratio_and_amt('1000SHIB/USDT', -1) exchange.get_maintenance_ratio_and_amt('1000SHIB/USDT', -1)
exchange._leverage_tiers = {} exchange._leverage_tiers = {}
exchange.get_leverage_tiers_for_pair = MagicMock(return_value=[])
with pytest.raises( with pytest.raises(
InvalidOrderException, InvalidOrderException,

View File

@ -162,5 +162,4 @@ def test_get_max_pair_stake_amount_okex(default_conf, mocker, leverage_tiers):
assert exchange.get_max_pair_stake_amount('BTC/USDT', 1.0) == 1000000000 assert exchange.get_max_pair_stake_amount('BTC/USDT', 1.0) == 1000000000
assert exchange.get_max_pair_stake_amount('BTC/USDT', 1.0, 10.0) == 100000000 assert exchange.get_max_pair_stake_amount('BTC/USDT', 1.0, 10.0) == 100000000
exchange.get_leverage_tiers_for_pair = MagicMock(return_value=None)
assert exchange.get_max_pair_stake_amount('TTT/USDT', 1.0) == float('inf') # Not in tiers assert exchange.get_max_pair_stake_amount('TTT/USDT', 1.0) == float('inf') # Not in tiers