updated get_max_leverage to use new ccxt unified property

This commit is contained in:
Sam Germain 2021-10-17 07:06:55 -06:00
parent 3fffc315ac
commit 0329da1a57
8 changed files with 45 additions and 133 deletions

View File

@ -2,7 +2,7 @@
import json import json
import logging import logging
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
import arrow import arrow
import ccxt import ccxt
@ -38,6 +38,12 @@ class Binance(Exchange):
# (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported # (TradingMode.FUTURES, Collateral.ISOLATED) # TODO-lev: Uncomment once supported
] ]
def __init__(self, config: Dict[str, Any], validate: bool = True) -> None:
super().__init__(config, validate)
self._leverage_brackets: Dict = {}
if self.trading_mode != TradingMode.SPOT:
self.fill_leverage_brackets()
@property @property
def _ccxt_config(self) -> Dict: def _ccxt_config(self) -> Dict:
# Parameters to add directly to ccxt sync/async initialization. # Parameters to add directly to ccxt sync/async initialization.

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:
@ -1637,9 +1633,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 by most exchanges, only used by Binance at time of writing
""" """
return return
@ -1649,6 +1645,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]
}