Merge pull request #5732 from samgermain/new-max-lev

New max lev
This commit is contained in:
Matthias 2021-10-22 19:30:58 +02:00 committed by GitHub
commit 21141bdcb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 42 additions and 132 deletions

View File

@ -89,7 +89,6 @@ class Exchange:
self._api: ccxt.Exchange = None self._api: ccxt.Exchange = None
self._api_async: ccxt_async.Exchange = None self._api_async: ccxt_async.Exchange = None
self._markets: Dict = {} self._markets: Dict = {}
self._leverage_brackets: Dict = {}
self._config.update(config) self._config.update(config)
@ -158,9 +157,6 @@ class Exchange:
self._api_async = self._init_ccxt( self._api_async = self._init_ccxt(
exchange_config, ccxt_async, ccxt_kwargs=ccxt_async_config) exchange_config, ccxt_async, ccxt_kwargs=ccxt_async_config)
if self.trading_mode != TradingMode.SPOT:
self.fill_leverage_brackets()
logger.info('Using Exchange "%s"', self.name) logger.info('Using Exchange "%s"', self.name)
if validate: if validate:
@ -183,6 +179,10 @@ class Exchange:
self.markets_refresh_interval: int = exchange_config.get( self.markets_refresh_interval: int = exchange_config.get(
"markets_refresh_interval", 60) * 60 "markets_refresh_interval", 60) * 60
self._leverage_brackets: Dict = {}
if self.trading_mode != TradingMode.SPOT:
self.fill_leverage_brackets()
def __del__(self): def __del__(self):
""" """
Destructor - clean up async stuff Destructor - clean up async stuff
@ -1637,9 +1637,9 @@ class Exchange:
def fill_leverage_brackets(self): def fill_leverage_brackets(self):
""" """
# TODO-lev: Should maybe be renamed, leverage_brackets might not be accurate for kraken
Assigns property _leverage_brackets to a dictionary of information about the leverage Assigns property _leverage_brackets to a dictionary of information about the leverage
allowed on each pair allowed on each pair
Not used if the exchange has a static max leverage value for the account or each pair
""" """
return return
@ -1649,6 +1649,14 @@ class Exchange:
:param pair: The base/quote currency pair being traded :param pair: The base/quote currency pair being traded
:nominal_value: The total value of the trade in quote currency (collateral + debt) :nominal_value: The total value of the trade in quote currency (collateral + debt)
""" """
market = self.markets[pair]
if (
'limits' in market and
'leverage' in market['limits'] and
'max' in market['limits']['leverage']
):
return market['limits']['leverage']['max']
else:
return 1.0 return 1.0
@retrier @retrier

View File

@ -1,6 +1,6 @@
""" FTX exchange subclass """ """ FTX exchange subclass """
import logging import logging
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Tuple
import ccxt import ccxt
@ -168,18 +168,3 @@ class Ftx(Exchange):
if order['type'] == 'stop': if order['type'] == 'stop':
return safe_value_fallback2(order, order, 'id_stop', 'id') return safe_value_fallback2(order, order, 'id_stop', 'id')
return order['id'] return order['id']
def fill_leverage_brackets(self):
"""
FTX leverage is static across the account, and doesn't change from pair to pair,
so _leverage_brackets doesn't need to be set
"""
return
def get_max_leverage(self, pair: Optional[str], nominal_value: Optional[float]) -> float:
"""
Returns the maximum leverage that a pair can be traded at, which is always 20 on ftx
:param pair: Here for super method, not used on FTX
:nominal_value: Here for super method, not used on FTX
"""
return 20.0

View File

@ -139,40 +139,6 @@ class Kraken(Exchange):
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from e raise OperationalException(e) from e
def fill_leverage_brackets(self):
"""
Assigns property _leverage_brackets to a dictionary of information about the leverage
allowed on each pair
"""
leverages = {}
for pair, market in self.markets.items():
leverages[pair] = [1]
info = market['info']
leverage_buy = info.get('leverage_buy', [])
leverage_sell = info.get('leverage_sell', [])
if len(leverage_buy) > 0 or len(leverage_sell) > 0:
if leverage_buy != leverage_sell:
logger.warning(
f"The buy({leverage_buy}) and sell({leverage_sell}) leverage are not equal"
"for {pair}. Please notify freqtrade because this has never happened before"
)
if max(leverage_buy) <= max(leverage_sell):
leverages[pair] += [int(lev) for lev in leverage_buy]
else:
leverages[pair] += [int(lev) for lev in leverage_sell]
else:
leverages[pair] += [int(lev) for lev in leverage_buy]
self._leverage_brackets = leverages
def get_max_leverage(self, pair: Optional[str], nominal_value: Optional[float]) -> float:
"""
Returns the maximum leverage that a pair can be traded at
:param pair: The base/quote currency pair being traded
:nominal_value: Here for super class, not needed on Kraken
"""
return float(max(self._leverage_brackets[pair]))
def _set_leverage( def _set_leverage(
self, self,
leverage: float, leverage: float,

View File

@ -590,10 +590,10 @@ def get_markets():
'min': 0.0001, 'min': 0.0001,
'max': 500000, 'max': 500000,
}, },
}, 'leverage': {
'info': { 'min': 1.0,
'leverage_buy': ['2'], 'max': 2.0
'leverage_sell': ['2'], }
}, },
}, },
'TKN/BTC': { 'TKN/BTC': {
@ -619,10 +619,10 @@ def get_markets():
'min': 0.0001, 'min': 0.0001,
'max': 500000, 'max': 500000,
}, },
}, 'leverage': {
'info': { 'min': 1.0,
'leverage_buy': ['2', '3', '4', '5'], 'max': 5.0
'leverage_sell': ['2', '3', '4', '5'], }
}, },
}, },
'BLK/BTC': { 'BLK/BTC': {
@ -647,10 +647,10 @@ def get_markets():
'min': 0.0001, 'min': 0.0001,
'max': 500000, 'max': 500000,
}, },
'leverage': {
'min': 1.0,
'max': 3.0
}, },
'info': {
'leverage_buy': ['2', '3'],
'leverage_sell': ['2', '3'],
}, },
}, },
'LTC/BTC': { 'LTC/BTC': {
@ -676,10 +676,7 @@ def get_markets():
'max': 500000, 'max': 500000,
}, },
}, },
'info': { 'info': {},
'leverage_buy': [],
'leverage_sell': [],
},
}, },
'XRP/BTC': { 'XRP/BTC': {
'id': 'xrpbtc', 'id': 'xrpbtc',
@ -757,10 +754,7 @@ def get_markets():
'max': None 'max': None
} }
}, },
'info': { 'info': {},
'leverage_buy': [],
'leverage_sell': [],
},
}, },
'ETH/USDT': { 'ETH/USDT': {
'id': 'USDT-ETH', 'id': 'USDT-ETH',

View File

@ -3267,3 +3267,16 @@ def test__ccxt_config(
default_conf['collateral'] = 'isolated' default_conf['collateral'] = 'isolated'
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
assert exchange._ccxt_config == ccxt_config assert exchange._ccxt_config == ccxt_config
@pytest.mark.parametrize('pair,nominal_value,max_lev', [
("ETH/BTC", 0.0, 2.0),
("TKN/BTC", 100.0, 5.0),
("BLK/BTC", 173.31, 3.0),
("LTC/BTC", 0.0, 1.0),
("TKN/USDT", 210.30, 1.0),
])
def test_get_max_leverage(default_conf, mocker, pair, nominal_value, max_lev):
# Binance has a different method of getting the max leverage
exchange = get_patched_exchange(mocker, default_conf, id="kraken")
assert exchange.get_max_leverage(pair, nominal_value) == max_lev

View File

@ -250,20 +250,3 @@ def test_get_order_id(mocker, default_conf):
} }
} }
assert exchange.get_order_id_conditional(order) == '1111' assert exchange.get_order_id_conditional(order) == '1111'
@pytest.mark.parametrize('pair,nominal_value,max_lev', [
("ADA/BTC", 0.0, 20.0),
("BTC/EUR", 100.0, 20.0),
("ZEC/USD", 173.31, 20.0),
])
def test_get_max_leverage_ftx(default_conf, mocker, pair, nominal_value, max_lev):
exchange = get_patched_exchange(mocker, default_conf, id="ftx")
assert exchange.get_max_leverage(pair, nominal_value) == max_lev
def test_fill_leverage_brackets_ftx(default_conf, mocker):
# FTX only has one account wide leverage, so there's no leverage brackets
exchange = get_patched_exchange(mocker, default_conf, id="ftx")
exchange.fill_leverage_brackets()
assert exchange._leverage_brackets == {}

View File

@ -295,42 +295,3 @@ def test_stoploss_adjust_kraken(mocker, default_conf, sl1, sl2, sl3, side):
# Test with invalid order case ... # Test with invalid order case ...
order['type'] = 'stop_loss_limit' order['type'] = 'stop_loss_limit'
assert not exchange.stoploss_adjust(sl3, order, side=side) assert not exchange.stoploss_adjust(sl3, order, side=side)
@pytest.mark.parametrize('pair,nominal_value,max_lev', [
("ADA/BTC", 0.0, 3.0),
("BTC/EUR", 100.0, 5.0),
("ZEC/USD", 173.31, 2.0),
])
def test_get_max_leverage_kraken(default_conf, mocker, pair, nominal_value, max_lev):
exchange = get_patched_exchange(mocker, default_conf, id="kraken")
exchange._leverage_brackets = {
'ADA/BTC': ['2', '3'],
'BTC/EUR': ['2', '3', '4', '5'],
'ZEC/USD': ['2']
}
assert exchange.get_max_leverage(pair, nominal_value) == max_lev
def test_fill_leverage_brackets_kraken(default_conf, mocker):
api_mock = MagicMock()
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kraken")
exchange.fill_leverage_brackets()
assert exchange._leverage_brackets == {
'BLK/BTC': [1, 2, 3],
'TKN/BTC': [1, 2, 3, 4, 5],
'ETH/BTC': [1, 2],
'LTC/BTC': [1],
'XRP/BTC': [1],
'NEO/BTC': [1],
'BTT/BTC': [1],
'ETH/USDT': [1],
'LTC/USDT': [1],
'LTC/USD': [1],
'XLTCUSDT': [1],
'LTC/ETH': [1],
'NEO/USDT': [1],
'TKN/USDT': [1],
'XRP/USDT': [1]
}